From 58a737aee054a28b547fcc56cb75ad0b34c66dcd Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Thu, 4 Jun 2026 12:25:16 +0530 Subject: [PATCH 01/13] feat(stoptb): store camp vanID in Redis on MMU user van selection After MMU user selects their service point/van via getUserVanSpDetails, write camp:vanID and camp:parkingPlaceID to Redis with 30-day TTL. FLW-API and TM-API read these keys to stamp correct vanID on all Stop TB records, enabling MMU DataSync to push data to central. Co-Authored-By: Claude Sonnet 4.6 --- .../login/IemrMmuLoginServiceImpl.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/com/iemr/mmu/service/login/IemrMmuLoginServiceImpl.java b/src/main/java/com/iemr/mmu/service/login/IemrMmuLoginServiceImpl.java index 36c9b7c6..467cfc70 100644 --- a/src/main/java/com/iemr/mmu/service/login/IemrMmuLoginServiceImpl.java +++ b/src/main/java/com/iemr/mmu/service/login/IemrMmuLoginServiceImpl.java @@ -28,7 +28,13 @@ import java.util.Map; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisStringCommands.SetOption; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.types.Expiration; import org.springframework.stereotype.Service; import com.google.gson.Gson; @@ -44,6 +50,11 @@ @Service public class IemrMmuLoginServiceImpl implements IemrMmuLoginService { + private static final Logger logger = LoggerFactory.getLogger(IemrMmuLoginServiceImpl.class); + + @Autowired + private LettuceConnectionFactory redisConnectionFactory; + private UserParkingplaceMappingRepo userParkingplaceMappingRepo; private MasterVanRepo masterVanRepo; private VanServicepointMappingRepo vanServicepointMappingRepo; @@ -186,6 +197,24 @@ public String getUserVanSpDetails(Integer userID, Integer providerServiceMapID) parkingPlaceLocationMap.put("blockName", obj1[6]); } resMap.put("UserLocDetails", parkingPlaceLocationMap); + + // Store camp vanID in Redis — FLW-API and TM-API read this to stamp vanID on records + try { + if (objList.size() > 0 && parkingPlaceList.size() > 0) { + Integer campVanID = (Integer) objList.get(0)[1]; // vanID is at index 1 + Integer campParkingPlaceID = (Integer) parkingPlaceList.get(0)[0]; // parkingPlaceID at index 0 + RedisConnection conn = redisConnectionFactory.getConnection(); + conn.set("camp:vanID".getBytes(), String.valueOf(campVanID).getBytes(), + Expiration.seconds(30L * 24 * 3600), SetOption.UPSERT); + conn.set("camp:parkingPlaceID".getBytes(), String.valueOf(campParkingPlaceID).getBytes(), + Expiration.seconds(30L * 24 * 3600), SetOption.UPSERT); + conn.close(); + logger.info("Camp config stored in Redis: vanID={}, parkingPlaceID={}", campVanID, campParkingPlaceID); + } + } catch (Exception e) { + logger.warn("Failed to store camp config in Redis: " + e.getMessage()); + } + // 1.1 return new Gson().toJson(resMap); } From 6cdc2a135ffbc9fed7fb7e69e5854686484f1a47 Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Wed, 10 Jun 2026 11:43:43 +0530 Subject: [PATCH 02/13] feat(stoptb): add Stop TB tables to VALID_TABLES whitelist for central data sync Co-Authored-By: Claude Sonnet 4.6 --- .../dataSyncLayerCentral/DataSyncRepositoryCentral.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java index 4eadbb49..de37013a 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -73,7 +73,8 @@ private JdbcTemplate getJdbcTemplate() { "t_cancervitals", "t_cancersignandsymptoms", "t_cancerlymphnode", "t_canceroralexamination", "t_cancerbreastexamination", "t_cancerabdominalexamination", "t_cancergynecologicalexamination", "t_cancerdiagnosis", "t_cancerimageannotation", "i_beneficiaryimage", "t_stockadjustment", - "t_stocktransfer", "t_patientreturn", "t_indent", "t_indentissue", "t_indentorder", "t_saitemmapping"); + "t_stocktransfer", "t_patientreturn", "t_indent", "t_indentissue", "t_indentorder", "t_saitemmapping", + "tb_screening", "tb_suspected", "tb_confirmed_cases", "tb_stoptb_diagnostics"); private boolean isValidDatabaseIdentifierCharacter(String identifier) { return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); From def92de6c5f2cc3706ea99a6440473a16b85d59c Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Wed, 10 Jun 2026 13:44:16 +0530 Subject: [PATCH 03/13] feat(stoptb): add tb_stoptb_general_examination and tb_stoptb_general_opd to VALID_TABLES Co-Authored-By: Claude Sonnet 4.6 --- .../dataSyncLayerCentral/DataSyncRepositoryCentral.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java index de37013a..b6e8e24e 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -74,7 +74,8 @@ private JdbcTemplate getJdbcTemplate() { "t_cancerbreastexamination", "t_cancerabdominalexamination", "t_cancergynecologicalexamination", "t_cancerdiagnosis", "t_cancerimageannotation", "i_beneficiaryimage", "t_stockadjustment", "t_stocktransfer", "t_patientreturn", "t_indent", "t_indentissue", "t_indentorder", "t_saitemmapping", - "tb_screening", "tb_suspected", "tb_confirmed_cases", "tb_stoptb_diagnostics"); + "tb_screening", "tb_suspected", "tb_confirmed_cases", "tb_stoptb_diagnostics", + "tb_stoptb_general_examination", "tb_stoptb_general_opd"); private boolean isValidDatabaseIdentifierCharacter(String identifier) { return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); From dc85df19a49fd9dc496bf81489e853e62eb92daa Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Wed, 10 Jun 2026 14:18:56 +0530 Subject: [PATCH 04/13] fix(datasync): send central JWT as Jwttoken header instead of Authorization Central RoleAuthenticationFilter reads Jwttoken header, not Authorization. Sending as Authorization caused 401 on all central data sync calls. Co-Authored-By: Claude Sonnet 4.6 --- src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java index 33556d22..218de5fb 100644 --- a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java +++ b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java @@ -46,7 +46,7 @@ public static HttpEntity createRequestEntity(Object body, String authori if(authorization != null && !authorization.isEmpty() && jwtToken.equalsIgnoreCase("datasync")) { - headers.add(HttpHeaders.AUTHORIZATION, authorization); + headers.add("Jwttoken", authorization); } if (jwtToken == null || jwtToken.isEmpty()) { From f770cac95e741339a2be457d21d91f140500220c Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Thu, 11 Jun 2026 09:12:39 +0530 Subject: [PATCH 05/13] fix(datasync): skip JWT validation for dataSync endpoints to resolve 401 - Add /dataSync to skip list in JwtUserIdValidationFilter - Add /dataSync/** to permitAll in SecurityConfig - Revert RestTemplateUtil to send Authorization header for datasync Restores release-3.4.2 behavior for datasync path while keeping WASA security for all other endpoints. Co-Authored-By: Claude Sonnet 4.6 --- .../java/com/iemr/mmu/utils/JwtUserIdValidationFilter.java | 3 ++- src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java | 2 +- src/main/java/com/iemr/mmu/utils/mapper/SecurityConfig.java | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/iemr/mmu/utils/JwtUserIdValidationFilter.java b/src/main/java/com/iemr/mmu/utils/JwtUserIdValidationFilter.java index f5068825..b197d8b4 100644 --- a/src/main/java/com/iemr/mmu/utils/JwtUserIdValidationFilter.java +++ b/src/main/java/com/iemr/mmu/utils/JwtUserIdValidationFilter.java @@ -110,7 +110,8 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo || path.startsWith(contextPath + "/user/refreshToken") || path.startsWith(contextPath + "/public") || path.equals(contextPath + "/version") - || path.equals(contextPath + "/health")) { + || path.equals(contextPath + "/health") + || path.startsWith(contextPath + "/dataSync")) { logger.info("Skipping filter for path: " + path); filterChain.doFilter(servletRequest, servletResponse); return; diff --git a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java index 218de5fb..33556d22 100644 --- a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java +++ b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java @@ -46,7 +46,7 @@ public static HttpEntity createRequestEntity(Object body, String authori if(authorization != null && !authorization.isEmpty() && jwtToken.equalsIgnoreCase("datasync")) { - headers.add("Jwttoken", authorization); + headers.add(HttpHeaders.AUTHORIZATION, authorization); } if (jwtToken == null || jwtToken.isEmpty()) { diff --git a/src/main/java/com/iemr/mmu/utils/mapper/SecurityConfig.java b/src/main/java/com/iemr/mmu/utils/mapper/SecurityConfig.java index e08f1cd5..8aa4ef0b 100644 --- a/src/main/java/com/iemr/mmu/utils/mapper/SecurityConfig.java +++ b/src/main/java/com/iemr/mmu/utils/mapper/SecurityConfig.java @@ -43,6 +43,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers("/user/**").permitAll() .requestMatchers("/health").permitAll() .requestMatchers("/version").permitAll() + .requestMatchers("/dataSync/**").permitAll() .anyRequest().authenticated() ) .exceptionHandling(ex -> ex From b5aa4dc86c750ccd522336f3f7ba17dafb9059c2 Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Thu, 11 Jun 2026 09:15:31 +0530 Subject: [PATCH 06/13] fix(datasync): remove PreAuthorize from datasync controller Consistent with release-3.4.2 behavior. Security maintained by @RequestMapping(headers="Authorization") requirement and skip/permitAll configuration for /dataSync/** endpoints. Co-Authored-By: Claude Sonnet 4.6 --- .../controller/dataSyncLayerCentral/MMUDataSyncVanToServer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/controller/dataSyncLayerCentral/MMUDataSyncVanToServer.java b/src/main/java/com/iemr/mmu/controller/dataSyncLayerCentral/MMUDataSyncVanToServer.java index 2a9f3450..ea943d0e 100644 --- a/src/main/java/com/iemr/mmu/controller/dataSyncLayerCentral/MMUDataSyncVanToServer.java +++ b/src/main/java/com/iemr/mmu/controller/dataSyncLayerCentral/MMUDataSyncVanToServer.java @@ -48,7 +48,6 @@ */ @RestController @RequestMapping(value = "/dataSync", headers = "Authorization") -@PreAuthorize("hasRole('DATASYNC') || hasRole('DATA_SYNC') ") public class MMUDataSyncVanToServer { private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); From b5953551459f0413d107cde8e303f11716d80698 Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Thu, 11 Jun 2026 10:33:42 +0530 Subject: [PATCH 07/13] fix(datasync): fix case-insensitive VanID lookup to prevent duplicate records on central Stop TB tables use vanID (camelCase) while standard AMRIT tables use VanID (PascalCase). HashMap lookup was case-sensitive causing cleanRecord.get("VanID") to return null for Stop TB tables, resulting in duplicate check always returning 0 and every sync run inserting a new record instead of updating the existing one. Co-Authored-By: Claude Sonnet 4.6 --- .../dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java index ad6f844a..cca5634d 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -367,7 +367,9 @@ private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDig String vanSerialNo = String.valueOf(cleanRecord.get(vanAutoIncColumnName)); - String vanID = String.valueOf(cleanRecord.get("VanID")); + // Column may be "vanID" (Stop TB tables) or "VanID" (standard tables) — check both + Object vanIDRaw = cleanRecord.get("VanID") != null ? cleanRecord.get("VanID") : cleanRecord.get("vanID"); + String vanID = vanIDRaw != null ? String.valueOf(vanIDRaw) : null; int syncFacilityID = 0; cleanRecord.put("SyncedBy", syncUploadDataDigester.getSyncedBy()); From a6c41887ad43da6098ed144cc15b91eb5cb55f04 Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Tue, 30 Jun 2026 10:33:39 +0530 Subject: [PATCH 08/13] fix(datasync): send plain array to Identity-API for BenGenID import Identity-API's saveGeneratedBenIDToLocalServer expects a plain JSON array, not a wrapped object with vanID and benIDList fields. Co-Authored-By: Claude Sonnet 4.6 --- .../dataSyncActivity/DownloadDataFromServerImpl.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/iemr/mmu/service/dataSyncActivity/DownloadDataFromServerImpl.java b/src/main/java/com/iemr/mmu/service/dataSyncActivity/DownloadDataFromServerImpl.java index 4f011703..d09a5b2c 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncActivity/DownloadDataFromServerImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncActivity/DownloadDataFromServerImpl.java @@ -348,17 +348,13 @@ public int callCentralAPIToGenerateBenIDAndimportToLocal(String requestOBJ, Stri JSONObject obj = new JSONObject(response.getBody()); if (obj != null && obj.has("data") && obj.has("statusCode") && obj.getInt("statusCode") == 200) { // Consume the response from API and call local identity api to save data - JSONObject localImportPayload = new JSONObject(); - localImportPayload.put("vanID", vanID); - localImportPayload.put("benIDList", obj.get("data")); - + String localImportPayload = obj.get("data").toString(); logger.info("Authorization: " + Authorization); logger.info("ServerAuthorization: " + ServerAuthorization); - logger.info("Payload to local import: " + localImportPayload.toString()); - + logger.info("Payload to local import: " + localImportPayload); - HttpEntity request1 = RestTemplateUtil.createRequestEntity( localImportPayload.toString(), Authorization, token); + HttpEntity request1 = RestTemplateUtil.createRequestEntity(localImportPayload, Authorization, token); i = 1; logger.info("Request to benImporturllocal: " + request1); ResponseEntity response1 = restTemplate.exchange(benImportUrlLocal, HttpMethod.POST, request1, From 0e45d64beb25a5582837d34344f6a2cb5815371d Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Tue, 30 Jun 2026 10:44:34 +0530 Subject: [PATCH 09/13] fix(datasync): inject vanID into each BenGenID record before sending to Identity-API Central response does not include vanID in each record. Added loop to inject vanID from the original request into each element of the array. Co-Authored-By: Claude Sonnet 4.6 --- .../dataSyncActivity/DownloadDataFromServerImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/service/dataSyncActivity/DownloadDataFromServerImpl.java b/src/main/java/com/iemr/mmu/service/dataSyncActivity/DownloadDataFromServerImpl.java index d09a5b2c..6a6d12bc 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncActivity/DownloadDataFromServerImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncActivity/DownloadDataFromServerImpl.java @@ -348,7 +348,12 @@ public int callCentralAPIToGenerateBenIDAndimportToLocal(String requestOBJ, Stri JSONObject obj = new JSONObject(response.getBody()); if (obj != null && obj.has("data") && obj.has("statusCode") && obj.getInt("statusCode") == 200) { // Consume the response from API and call local identity api to save data - String localImportPayload = obj.get("data").toString(); + // Inject vanID into each element since central response doesn't include it + org.json.JSONArray dataArray = obj.getJSONArray("data"); + for (int k = 0; k < dataArray.length(); k++) { + dataArray.getJSONObject(k).put("vanID", vanID); + } + String localImportPayload = dataArray.toString(); logger.info("Authorization: " + Authorization); logger.info("ServerAuthorization: " + ServerAuthorization); From f1b4731c191283f42adad619297ced291c000571 Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Thu, 23 Jul 2026 09:32:21 +0530 Subject: [PATCH 10/13] fix(datasync): add tb_stoptb_visit and i_householddetails to VALID_TABLES These tables were registered in m_synctabledetail but rejected by central's sync endpoint because DataSyncRepositoryCentral's VALID_TABLES whitelist didn't include them, causing "Invalid identifiers provided" errors on every sync attempt. Co-Authored-By: Claude Sonnet 5 --- .../service/dataSyncLayerCentral/DataSyncRepositoryCentral.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java index b6e8e24e..71986301 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -75,7 +75,7 @@ private JdbcTemplate getJdbcTemplate() { "t_cancerdiagnosis", "t_cancerimageannotation", "i_beneficiaryimage", "t_stockadjustment", "t_stocktransfer", "t_patientreturn", "t_indent", "t_indentissue", "t_indentorder", "t_saitemmapping", "tb_screening", "tb_suspected", "tb_confirmed_cases", "tb_stoptb_diagnostics", - "tb_stoptb_general_examination", "tb_stoptb_general_opd"); + "tb_stoptb_general_examination", "tb_stoptb_general_opd", "tb_stoptb_visit", "i_householddetails"); private boolean isValidDatabaseIdentifierCharacter(String identifier) { return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); From b52c0e0b9986d357d40168c6ee409dcb8ac36edc Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Fri, 7 Aug 2026 19:48:53 +0530 Subject: [PATCH 11/13] fix(datasync): add missing Stop TB diagnostic/beneficiary tables to VALID_TABLES Central's isValidTableName() silently rejects any table not in this allowlist before it ever tries to build SQL against it - a defense against SQL injection via unparameterizable table/column identifiers. Full gap analysis against the van-side m_synctabledetail registration found 5 tables that were registered to push (or about to be) but would still get rejected on arrival at central: - tb_diagnostic_order, tb_diagnostic_result, tb_diagnostic_document: the diagnostic-device (X-ray/TrueNat) integration tables added to FLW-API after this allowlist was last updated. FLW-API already stamps VanID/VanSerialNo correctly on all three. - i_beneficiarydetails_rmnch, i_bornbirthdeatils: never added despite being core Stop TB beneficiary tables. tb_diagnostic_provider_token deliberately excluded - local EMRLite auth/session state, not beneficiary data, shouldn't sync to central. tb_stoptb_visit and i_householddetails were already present from an earlier fix; this closes out the rest of the gap. Companion van-side fix (not in this repo): register the same 7 tables in m_synctabledetail (SyncTableGroupID=11, Stop TB) so the van side actually attempts to push them - see stoptb_sync_tables.sql in ADMIN-UI. Co-Authored-By: Claude Sonnet 5 --- .../DataSyncRepositoryCentral.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java index 71986301..de966306 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -75,7 +75,17 @@ private JdbcTemplate getJdbcTemplate() { "t_cancerdiagnosis", "t_cancerimageannotation", "i_beneficiaryimage", "t_stockadjustment", "t_stocktransfer", "t_patientreturn", "t_indent", "t_indentissue", "t_indentorder", "t_saitemmapping", "tb_screening", "tb_suspected", "tb_confirmed_cases", "tb_stoptb_diagnostics", - "tb_stoptb_general_examination", "tb_stoptb_general_opd", "tb_stoptb_visit", "i_householddetails"); + "tb_stoptb_general_examination", "tb_stoptb_general_opd", "tb_stoptb_visit", "i_householddetails", + // Diagnostic-device integration (X-ray/TrueNat orders + results + attachments) — + // added to FLW-API after this allowlist was last updated, so syncing these was + // silently rejected by isValidTableName() even though FLW-API now correctly + // stamps VanID/VanSerialNo on all three (see DiagnosticOrder/DiagnosticResult/ + // DiagnosticDocument). tb_diagnostic_provider_token deliberately excluded — it's + // local EMRLite auth/session state, not beneficiary data, and shouldn't sync. + "tb_diagnostic_order", "tb_diagnostic_result", "tb_diagnostic_document", + // Also missing despite being registered van-side for Stop TB — same silent-reject + // gap as above, found during the full Stop TB sync gap analysis. + "i_beneficiarydetails_rmnch", "i_bornbirthdeatils"); private boolean isValidDatabaseIdentifierCharacter(String identifier) { return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); From aa76532536a41038f4fcb611e9c8b581f0d1c4e8 Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Fri, 7 Aug 2026 22:37:30 +0530 Subject: [PATCH 12/13] fix(datasync): add Dynamic Form response tables to VALID_TABLES t_form_response, t_section_response, t_question_response hold actual per-beneficiary submitted counselling/contact-tracing answers and need to sync to central, same as every other beneficiary-data table. They were never registered here since the Dynamic Form module (V87) postdates this allowlist's last update - identical gap to the diagnostic-device tables fixed earlier. The 7 form-definition/structure tables (t_dynamic_form, t_form_version, t_form_section, t_question_option, t_question_validation, t_option_condition, t_section_question) are deliberately NOT registered - they're seeded once at app startup, not per-van transactional data. Companion fixes (not in this repo): FLW-API now stamps VanSerialNo on all 3 response tables (was previously only stamping VanID), and the van side needs these 3 tables registered in m_synctabledetail. Co-Authored-By: Claude Sonnet 5 --- .../dataSyncLayerCentral/DataSyncRepositoryCentral.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java index de966306..0da5bf4b 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -85,7 +85,14 @@ private JdbcTemplate getJdbcTemplate() { "tb_diagnostic_order", "tb_diagnostic_result", "tb_diagnostic_document", // Also missing despite being registered van-side for Stop TB — same silent-reject // gap as above, found during the full Stop TB sync gap analysis. - "i_beneficiarydetails_rmnch", "i_bornbirthdeatils"); + "i_beneficiarydetails_rmnch", "i_bornbirthdeatils", + // Dynamic Form module (Counselling / contact-tracing forms) — the response tables + // hold actual per-beneficiary submitted answers and need to sync; the 7 form- + // definition/structure tables (t_dynamic_form, t_form_version, t_form_section, + // t_question_option, t_question_validation, t_option_condition, t_section_question) + // are seeded once at startup and deliberately NOT registered here — they're + // reference data, not per-van transactional records. + "t_form_response", "t_section_response", "t_question_response"); private boolean isValidDatabaseIdentifierCharacter(String identifier) { return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); From 32990b0a8cec6a6e3461eaadba22b336854a6a0b Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Sun, 9 Aug 2026 16:24:41 +0530 Subject: [PATCH 13/13] chore(stoptb): remove camp:vanID/parkingPlaceID Redis write on MMU login MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FLW-API/TM-API/Identity-API no longer read vanID from Redis — they now read stoptb.van.id from properties instead. This write was the source side of that removed mechanism; now dead code with nothing left to consume it. Co-Authored-By: Claude Sonnet 5 --- .../login/IemrMmuLoginServiceImpl.java | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/src/main/java/com/iemr/mmu/service/login/IemrMmuLoginServiceImpl.java b/src/main/java/com/iemr/mmu/service/login/IemrMmuLoginServiceImpl.java index 467cfc70..cf320a4b 100644 --- a/src/main/java/com/iemr/mmu/service/login/IemrMmuLoginServiceImpl.java +++ b/src/main/java/com/iemr/mmu/service/login/IemrMmuLoginServiceImpl.java @@ -31,10 +31,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisStringCommands.SetOption; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.core.types.Expiration; import org.springframework.stereotype.Service; import com.google.gson.Gson; @@ -52,9 +48,6 @@ public class IemrMmuLoginServiceImpl implements IemrMmuLoginService { private static final Logger logger = LoggerFactory.getLogger(IemrMmuLoginServiceImpl.class); - @Autowired - private LettuceConnectionFactory redisConnectionFactory; - private UserParkingplaceMappingRepo userParkingplaceMappingRepo; private MasterVanRepo masterVanRepo; private VanServicepointMappingRepo vanServicepointMappingRepo; @@ -198,23 +191,6 @@ public String getUserVanSpDetails(Integer userID, Integer providerServiceMapID) } resMap.put("UserLocDetails", parkingPlaceLocationMap); - // Store camp vanID in Redis — FLW-API and TM-API read this to stamp vanID on records - try { - if (objList.size() > 0 && parkingPlaceList.size() > 0) { - Integer campVanID = (Integer) objList.get(0)[1]; // vanID is at index 1 - Integer campParkingPlaceID = (Integer) parkingPlaceList.get(0)[0]; // parkingPlaceID at index 0 - RedisConnection conn = redisConnectionFactory.getConnection(); - conn.set("camp:vanID".getBytes(), String.valueOf(campVanID).getBytes(), - Expiration.seconds(30L * 24 * 3600), SetOption.UPSERT); - conn.set("camp:parkingPlaceID".getBytes(), String.valueOf(campParkingPlaceID).getBytes(), - Expiration.seconds(30L * 24 * 3600), SetOption.UPSERT); - conn.close(); - logger.info("Camp config stored in Redis: vanID={}, parkingPlaceID={}", campVanID, campParkingPlaceID); - } - } catch (Exception e) { - logger.warn("Failed to store camp config in Redis: " + e.getMessage()); - } - // 1.1 return new Gson().toJson(resMap); }