Skip to content

Commit 3433a5b

Browse files
committed
feat(event): rest api for number assessment events
#2236
1 parent e9401f5 commit 3433a5b

2 files changed

Lines changed: 88 additions & 1 deletion

File tree

pom-dependency-tree.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ai.elimu:webapp:war:2.6.87-SNAPSHOT
1+
ai.elimu:webapp:war:2.6.88-SNAPSHOT
22
+- ai.elimu:model:jar:model-2.0.114:compile
33
| \- com.google.code.gson:gson:jar:2.13.1:compile
44
| \- com.google.errorprone:error_prone_annotations:jar:2.38.0:compile
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package ai.elimu.rest.v2.analytics;
2+
3+
import ai.elimu.model.v2.enums.Language;
4+
import ai.elimu.util.AnalyticsHelper;
5+
import ai.elimu.util.ConfigHelper;
6+
import java.io.File;
7+
import jakarta.servlet.http.HttpServletResponse;
8+
import lombok.extern.slf4j.Slf4j;
9+
10+
import org.apache.commons.io.FileUtils;
11+
import org.json.JSONObject;
12+
import org.springframework.http.HttpStatus;
13+
import org.springframework.http.MediaType;
14+
import org.springframework.web.bind.annotation.PostMapping;
15+
import org.springframework.web.bind.annotation.RequestMapping;
16+
import org.springframework.web.bind.annotation.RequestParam;
17+
import org.springframework.web.bind.annotation.RestController;
18+
import org.springframework.web.multipart.MultipartFile;
19+
20+
/**
21+
* REST API endpoint for receiving number assessment events from the
22+
* <a href="https://github.com/elimu-ai/analytics">Analytics</a> application.
23+
*/
24+
@RestController
25+
@RequestMapping(value = "/rest/v2/analytics/number-assessment-events/csv", produces = MediaType.APPLICATION_JSON_VALUE)
26+
@Slf4j
27+
public class NumberAssessmentEventsRestController {
28+
29+
@PostMapping
30+
public String handleUploadCsvRequest(
31+
@RequestParam("file") MultipartFile multipartFile,
32+
HttpServletResponse response
33+
) {
34+
log.info("handleUploadCsvRequest");
35+
36+
JSONObject jsonResponseObject = new JSONObject();
37+
try {
38+
String contentType = multipartFile.getContentType();
39+
log.info("contentType: " + contentType);
40+
41+
long size = multipartFile.getSize();
42+
log.info("size: " + size);
43+
if (size == 0) {
44+
throw new IllegalArgumentException("Empty file");
45+
}
46+
47+
// Expected format: "7161a85a0e4751cd_4000022_number-assessment-events_2025-07-01.csv"
48+
String originalFilename = multipartFile.getOriginalFilename();
49+
log.info("originalFilename: " + originalFilename);
50+
if (originalFilename.length() != "7161a85a0e4751cd_4000022_number-assessment-events_2025-07-01.csv".length()) {
51+
throw new IllegalArgumentException("Unexpected filename");
52+
}
53+
54+
String androidIdExtractedFromFilename = AnalyticsHelper.extractAndroidIdFromCsvFilename(originalFilename);
55+
log.info("androidIdExtractedFromFilename: \"" + androidIdExtractedFromFilename + "\"");
56+
57+
byte[] bytes = multipartFile.getBytes();
58+
log.info("bytes.length: " + bytes.length);
59+
60+
// Store the original CSV file on the filesystem
61+
File elimuAiDir = new File(System.getProperty("user.home"), ".elimu-ai");
62+
File languageDir = new File(elimuAiDir, "lang-" + Language.valueOf(ConfigHelper.getProperty("content.language")));
63+
File analyticsDir = new File(languageDir, "analytics");
64+
File androidIdDir = new File(analyticsDir, "android-id-" + androidIdExtractedFromFilename);
65+
File numberAssessmentEventsDir = new File(androidIdDir, "number-assessment-events");
66+
numberAssessmentEventsDir.mkdirs();
67+
File csvFile = new File(numberAssessmentEventsDir, originalFilename);
68+
log.info("Storing CSV file at " + csvFile);
69+
FileUtils.writeByteArrayToFile(csvFile, bytes);
70+
log.info("csvFile.exists(): " + csvFile.exists());
71+
72+
jsonResponseObject.put("result", "success");
73+
jsonResponseObject.put("successMessage", "The CSV file was uploaded");
74+
response.setStatus(HttpStatus.OK.value());
75+
} catch (Exception ex) {
76+
log.error(ex.getMessage());
77+
78+
jsonResponseObject.put("result", "error");
79+
jsonResponseObject.put("errorMessage", ex.getMessage());
80+
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
81+
}
82+
83+
String jsonResponse = jsonResponseObject.toString();
84+
log.info("jsonResponse: " + jsonResponse);
85+
return jsonResponse;
86+
}
87+
}

0 commit comments

Comments
 (0)