Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/main/environment/common_docker.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ spring.datasource.password=${DATABASE_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

## S3 storage for diagnostic documents pushed from a van
aws.s3.access-key=${AWS_S3_ACCESS_KEY}
aws.s3.secret-key=${AWS_S3_SECRET_KEY}
aws.s3.region=${AWS_S3_REGION}
diagnostic.documents.s3.bucket=${DIAGNOSTIC_DOCUMENTS_S3_BUCKET}
aws.s3.access-key=${AWS_S3_ACCESS_KEY:}
aws.s3.secret-key=${AWS_S3_SECRET_KEY:}
aws.s3.region=${AWS_S3_REGION:ap-south-1}
diagnostic.documents.s3.bucket=${DIAGNOSTIC_DOCUMENTS_S3_BUCKET:}

## Carestream URLs, local
carestreamOrderCreateURL=${COMMON_API}carestream/createOrder
Expand All @@ -36,7 +36,7 @@ dataSyncDownloadUrl=${MMU_CENTRAL_SERVER}dataSync/server-to-van

## Diagnostic document push (this server -> further central server)
diagnosticDocumentUploadUrl=${MMU_CENTRAL_SERVER}dataSync/diagnostic-documents
diagnosticDocument.push.batchSize=${DIAGNOSTIC_DOCUMENT_PUSH_BATCH_SIZE}
diagnosticDocument.push.batchSize=${DIAGNOSTIC_DOCUMENT_PUSH_BATCH_SIZE:3}
diagnostic.documents.storage-root=${DIAGNOSTIC_DOCUMENTS_STORAGE_ROOT}

## TC specialist slot booking, # not required
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/com/iemr/mmu/config/S3ClientConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.springframework.context.annotation.Configuration;

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
Expand All @@ -26,7 +28,16 @@ public class S3ClientConfig {
@Value("${aws.s3.region}")
private String region;

private StaticCredentialsProvider credentialsProvider() {
/*
* Only the central server talks to S3; a van (camp laptop) runs the same war but never
* calls it, so it must be able to start without AWS keys. AwsBasicCredentials rejects blank
* keys at construction time, so fall back to the SDK default chain, which is resolved lazily
* on the first S3 call rather than at startup.
*/
private AwsCredentialsProvider credentialsProvider() {
if (accessKey == null || accessKey.isBlank() || secretKey == null || secretKey.isBlank()) {
return DefaultCredentialsProvider.create();
}
return StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,64 @@
// ---------------------------------- End of Upload repository

// ---------------------------------- Download Repository

/**
* Down-sync copies the beneficiary tables but not i_ben_flow_outreach, and the tab download
* (FLW-API getBeneficiaryData) only serves beneficiaries that have a worklist row. So a
* beneficiary registered elsewhere and down-synced here never reached this laptop's tabs.
* Creates the missing worklist row for this van's beneficiaries, filled as TM-API does at
* registration. Processed = 'P' so it is not uploaded back: central already has its own row.
*/
public int createMissingWorklistRows(int vanID, int providerServiceMapID) {
jdbcTemplate = getJdbcTemplate();

String village = "(SELECT h.%s FROM db_identity.i_beneficiarydetails_rmnch r "
+ " JOIN db_identity.i_householddetails h ON h.houseoldId = r.houseoldId "
+ " WHERE r.BeneficiaryRegID = bm.BenRegId LIMIT 1)";

String insert = "INSERT INTO db_iemr.i_ben_flow_outreach "
+ " (beneficiary_reg_id, beneficiary_id, visit_no, ben_name, ben_age, ben_dob, ben_gender, "
+ " ben_gender_val, ben_age_val, ben_phone_no, father_name, spouse_name, nurse_flag, doctor_flag, "
+ " pharmacist_flag, doctor_signature_flag, BenArrivedFlag, created_by, created_date, modified_by, "
+ " modified_date, registrationDate, districtID, district, villageID, village, "
+ " providerServiceMapID, vanID, Processed, deleted) "
+ " SELECT * FROM ( SELECT bm.BenRegId, rg.BeneficiaryID, 1 AS visit_no, "
+ " TRIM(CONCAT_WS(' ', d.FirstName, NULLIF(d.MiddleName, ''), d.LastName)) AS ben_name, "
+ " CONCAT(TIMESTAMPDIFF(YEAR, d.DOB, bm.CreatedDate), ' years - ', "
+ " MOD(TIMESTAMPDIFF(MONTH, d.DOB, bm.CreatedDate), 12), ' months') AS ben_age, "
+ " d.DOB, d.Gender, d.GenderId, TIMESTAMPDIFF(YEAR, d.DOB, bm.CreatedDate) AS ben_age_val, "
+ " COALESCE(c.PreferredPhoneNum, c.PhoneNum1) AS phone, "
+ " COALESCE(d.FatherName, '') AS father, COALESCE(d.SpouseName, '') AS spouse, "
+ " 1 AS nf, 0 AS df, 0 AS pf, 0 AS dsf, 0 AS baf, bm.CreatedBy, bm.CreatedDate AS cdate, "
+ " 'downsync' AS mby, NOW() AS mdate, bm.CreatedDate AS rdate, "
+ " COALESCE(a.CurrDistrictId, a.PermDistrictId) AS districtID, "
+ " COALESCE(a.CurrDistrict, a.PermDistrict) AS district, "
+ " COALESCE(" + String.format(village, "villageid") + ", a.CurrVillageId, a.PermVillageId) AS villageID, "
+ " COALESCE(" + String.format(village, "village") + ", a.CurrVillage, a.PermVillage) AS village, "
+ " ? AS psm, bm.VanID, 'P' AS processed, 0 AS deleted "
+ " FROM db_identity.i_beneficiarymapping bm "
+ " JOIN db_identity.m_beneficiaryregidmapping rg ON rg.BenRegId = bm.BenRegId "
+ " JOIN db_identity.i_beneficiarydetails d ON d.BeneficiaryDetailsId = bm.BenDetailsId "
+ " LEFT JOIN db_identity.i_beneficiarycontacts c ON c.BenContactsID = bm.BenContactsId "
+ " LEFT JOIN db_identity.i_beneficiaryaddress a ON a.BenAddressID = bm.BenAddressId "
+ " WHERE bm.VanID = ? AND bm.Deleted = false "
// the van can hold beneficiaries of other service lines; only its own get a row
+ " AND (SELECT r.ProviderServiceMapID FROM db_identity.i_beneficiarydetails_rmnch r "
+ " WHERE r.BeneficiaryRegID = bm.BenRegId LIMIT 1) = ? "
+ " AND NOT EXISTS (SELECT 1 FROM db_iemr.i_ben_flow_outreach f "
+ " WHERE f.beneficiary_reg_id = bm.BenRegId) ) x "
+ " WHERE x.villageID IS NOT NULL";

int inserted = jdbcTemplate.update(insert, providerServiceMapID, vanID, providerServiceMapID);

Check warning on line 220 in src/main/java/com/iemr/mmu/service/dataSyncActivity/DataSyncRepository.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make sure using a dynamically formatted SQL query is safe here.

See more on https://sonarcloud.io/project/issues?id=PSMRI_MMU-API&issues=AaFm6PB3dd2BBd6Yg8uL&open=AaFm6PB3dd2BBd6Yg8uL&pullRequest=203

if (inserted > 0)
// same convention as TM-API: VanSerialNo is the row's own id
jdbcTemplate.update("UPDATE db_iemr.i_ben_flow_outreach SET VanSerialNo = ben_flow_id "
+ " WHERE modified_by = 'downsync' AND VanSerialNo IS NULL");

return inserted;
}

public int[] updateLatestMasterInLocal(String query, List<Object[]> syncDataList) {
int[] i = null;
// get JDBC template
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ public String startDownSync(String serverAuthorization, String jwtToken, Integer
}
progressCounter++;
}
createMissingWorklistRows(vanID, providerServiceMapID);
countOutstandingConflicts(downSyncTables, vanID);
} finally {
IN_PROGRESS.set(false);
Expand Down Expand Up @@ -207,6 +208,23 @@ public Map<String, Object> getDownSyncStatus() {
return resultMap;
}

/** Down-synced beneficiaries need a worklist row before this laptop's tabs can download them. */
private void createMissingWorklistRows(Integer vanID, Integer providerServiceMapID) {
try {
Integer psm = providerServiceMapID != null ? providerServiceMapID
: dataSyncRepository.getVanProviderServiceMapID(vanID);
if (psm == null) {
logger.warn("Worklist rows not created after down-sync: no service line for van {}", vanID);
return;
}
int created = dataSyncRepository.createMissingWorklistRows(vanID, psm);
logger.info("Created {} worklist rows for down-synced beneficiaries of van {}", created, vanID);
} catch (Exception e) {
// the down-sync itself already succeeded; a failure here must not undo it
logger.error("Creating worklist rows after down-sync failed for van " + vanID + " : " + e.getMessage(), e);
}
}

private void countOutstandingConflicts(List<DownSyncTableDetail> downSyncTables, Integer vanID) {
outstandingConflictCounter = 0;
outstandingConflictTables.clear();
Expand Down
Loading