diff --git a/src/main/java/com/iemr/mmu/controller/dataSyncActivity/StartSyncActivity.java b/src/main/java/com/iemr/mmu/controller/dataSyncActivity/StartSyncActivity.java index 55884642..3d1f211e 100644 --- a/src/main/java/com/iemr/mmu/controller/dataSyncActivity/StartSyncActivity.java +++ b/src/main/java/com/iemr/mmu/controller/dataSyncActivity/StartSyncActivity.java @@ -105,10 +105,10 @@ public String dataSyncToServer(@RequestBody String requestOBJ, @PostMapping(value = { "/diagnostic-documents-to-server" }) public String diagnosticDocumentsToServer(@RequestHeader(value = "Authorization") String authorization, @RequestHeader(value = "ServerAuthorization") String serverAuthorization, - @RequestParam Long villageId) { + @RequestParam(required = false) Long villageId) { OutputResponse response = new OutputResponse(); try { - String s = diagnosticDocumentPushServiceImpl.pushPendingDocuments(serverAuthorization, villageId); + String s = diagnosticDocumentPushServiceImpl.pushPendingDocuments(serverAuthorization); if (s != null) response.setResponse(s); else diff --git a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DiagnosticDocumentIngestService.java b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DiagnosticDocumentIngestService.java index 507ff235..81fa0acf 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DiagnosticDocumentIngestService.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DiagnosticDocumentIngestService.java @@ -80,16 +80,16 @@ private Map ingestOne(Map item) { } Long beneficiaryId = asLong(item.get("beneficiaryId")); - Long villageId = asLong(item.get("villageId")); + Long vanId = asLong(item.get("vanID")); String orderType = (String) item.get("orderType"); String storedFileName = (String) item.get("storedFileName"); - if (villageId == null || beneficiaryId == null || orderType == null || documentType == null + if (vanId == null || beneficiaryId == null || orderType == null || documentType == null || storedFileName == null) { ack.put("status", "FAILED"); - ack.put("error", "Missing villageId, beneficiaryId, orderType, documentType or storedFileName"); + ack.put("error", "Missing vanID, beneficiaryId, orderType, documentType or storedFileName"); return ack; } - String s3Key = villageId + "/" + beneficiaryId + "/" + orderType + "/" + documentType + "/" + String s3Key = vanId + "/" + beneficiaryId + "/" + orderType + "/" + documentType + "/" + storedFileName; String contentType = (String) item.get("contentType"); diff --git a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DiagnosticDocumentPushServiceImpl.java b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DiagnosticDocumentPushServiceImpl.java index 9374d93b..cc817200 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DiagnosticDocumentPushServiceImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DiagnosticDocumentPushServiceImpl.java @@ -6,6 +6,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -66,11 +67,10 @@ public class DiagnosticDocumentPushServiceImpl { @Autowired private CryptoUtil cryptoUtil; - public String pushPendingDocuments(String Authorization, Long villageId) throws Exception { + public String pushPendingDocuments(String Authorization) throws Exception { List> pendingRows = diagnosticDocumentRepository.findPendingDocuments(); - boolean anyRowsFound = !pendingRows.isEmpty(); - int totalAttempted = 0; int totalSucceeded = 0; + List failureReasons = new ArrayList<>(); for (int offset = 0; offset < pendingRows.size(); offset += batchSize) { List> rows = pendingRows.subList(offset, Math.min(offset + batchSize, pendingRows.size())); @@ -88,13 +88,12 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws } catch (Exception e) { logger.warn("Skipping diagnostic document push, could not read file off disk: id={}, error={}", rowId, e.getMessage()); - diagnosticDocumentRepository.markPushFailed(rowId, - "Could not read file off shared filesystem: " + e.getMessage()); + markFailed(rowId, "Could not read file off shared filesystem: " + e.getMessage(), failureReasons); continue; } if (base64Plaintext == null) { logger.warn("Skipping diagnostic document push, decrypt failed: id={}", rowId); - diagnosticDocumentRepository.markPushFailed(rowId, "Decrypt failed"); + markFailed(rowId, "Decrypt failed", failureReasons); continue; } @@ -118,7 +117,6 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws item.put("vanID", row.get("vanID")); item.put("parkingPlaceID", row.get("parkingPlaceID")); item.put("vanSerialNo", row.get("vanSerialNo")); - item.put("villageId", villageId); item.put("fileContentBase64", base64Plaintext); payloadItems.add(item); rowsById.put(rowId, row); @@ -128,8 +126,6 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws continue; } - totalAttempted += payloadItems.size(); - String requestOBJ = new Gson().toJson(payloadItems); List> acks; try { @@ -140,7 +136,7 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws if (response == null || !response.hasBody()) { logger.warn("No response body from central server for diagnostic document push, marking batch failed"); - markBatchFailed(rowsById, "No response body from central server"); + markBatchFailed(rowsById, "No response body from central server", failureReasons); continue; } @@ -149,7 +145,7 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws JsonElement parsedBody = JsonParser.parseString(response.getBody()); if (!parsedBody.isJsonObject()) { logger.warn("Unexpected response shape from central server for diagnostic document push, marking batch failed"); - markBatchFailed(rowsById, "Unexpected response shape from central server"); + markBatchFailed(rowsById, "Unexpected response shape from central server", failureReasons); continue; } JsonObject envelope = parsedBody.getAsJsonObject(); @@ -157,7 +153,7 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws || !envelope.has("data")) { logger.warn("Central server reported failure for diagnostic document push batch, marking batch failed: {}", response.getBody()); - markBatchFailed(rowsById, "Central server reported failure: " + response.getBody()); + markBatchFailed(rowsById, "Central server reported failure: " + response.getBody(), failureReasons); continue; } @@ -165,12 +161,12 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws }.getType(); acks = new Gson().fromJson(envelope.get("data"), ackListType); if (acks == null) { - markBatchFailed(rowsById, "Central server returned no acknowledgements"); + markBatchFailed(rowsById, "Central server returned no acknowledgements", failureReasons); continue; } } catch (Exception e) { logger.error("Error calling central server for diagnostic document push, marking batch failed", e); - markBatchFailed(rowsById, "Error calling central server: " + e.getMessage()); + markBatchFailed(rowsById, "Error calling central server: " + e.getMessage(), failureReasons); continue; } @@ -188,8 +184,7 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws String reason = (String) ack.get("error"); logger.warn("Central server rejected diagnostic document push: id={}, externalOrderId={}, documentType={}, error={}", rowId, ack.get("externalOrderId"), ack.get("documentType"), reason); - diagnosticDocumentRepository.markPushFailed(rowId, - reason != null ? reason : "Central server rejected the document"); + markFailed(rowId, reason != null ? reason : "Central server rejected the document", failureReasons); } } if (!unmatchedRowsById.isEmpty()) { @@ -198,7 +193,7 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws logger.warn( "Diagnostic document push: {} row(s) in this batch got no matching ack back, marking failed", unmatchedRowsById.size()); - markBatchFailed(unmatchedRowsById, "No acknowledgement received from central server"); + markBatchFailed(unmatchedRowsById, "No acknowledgement received from central server", failureReasons); } totalSucceeded += batchSuccessCount; @@ -206,22 +201,47 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws batchSuccessCount); } - if (!anyRowsFound) { - return "No pending diagnostic documents to sync"; + if (pendingRows.isEmpty()) { + return "No data to sync"; } - if (totalAttempted == 0) { - return "No documents could be decrypted for push"; + + // Same table-level summary shape as /van-to-server (UploadDataToServerImpl) so the + // data sync screen can read both the same way. + int totalRecords = pendingRows.size(); + int failedRecords = failureReasons.size(); + String status; + if (failedRecords == 0) { + status = "success"; + } else if (totalSucceeded == 0) { + status = "failed"; + } else { + status = "partial"; } - if (totalSucceeded == 0) { - // Documents WERE decrypted and sent, but none were accepted (e.g. the central - // server rejected every batch) - the specific reason for each row is recorded in - // its own docSyncFailureReason, this is just the overall-outcome summary. - return "Documents were sent but none were accepted by the central server"; + + Map finalResponse = new LinkedHashMap<>(); + finalResponse.put("response", + "success".equals(status) ? "Data sync completed successfully" : "Data sync completed with failures"); + finalResponse.put("schemaName", "db_iemr"); + finalResponse.put("tableName", "tb_diagnostic_document"); + finalResponse.put("status", status); + finalResponse.put("totalRecords", totalRecords); + finalResponse.put("successfulRecords", totalSucceeded); + finalResponse.put("failedRecords", failedRecords); + if (!failureReasons.isEmpty()) { + finalResponse.put("failureReasons", failureReasons); } - logger.info("Diagnostic document push complete overall: attempted={}, succeeded={}", totalAttempted, - totalSucceeded); - return "Data successfully synced"; + logger.info("Diagnostic document push complete: {} (Success: {}, Failed: {}, Total: {})", status, + totalSucceeded, failedRecords, totalRecords); + return new Gson().toJson(finalResponse); + } + + /*** + * @purpose Marks one row failed locally and records its reason for the run summary. + */ + private void markFailed(Long rowId, String reason, List failureReasons) { + diagnosticDocumentRepository.markPushFailed(rowId, reason); + failureReasons.add("documentId " + rowId + ": " + reason); } /*** @@ -230,9 +250,9 @@ public String pushPendingDocuments(String Authorization, Long villageId) throws * batch as failed, matching how /van-to-server marks a whole batch failed on a * connection error, rather than leaving them stuck at docsProcessed='N' forever. */ - private void markBatchFailed(Map> rowsById, String reason) { + private void markBatchFailed(Map> rowsById, String reason, List failureReasons) { for (Long rowId : rowsById.keySet()) { - diagnosticDocumentRepository.markPushFailed(rowId, reason); + markFailed(rowId, reason, failureReasons); } }