From 54c7ad099ad5baee3abceac2edf58dc85f474d30 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Wed, 2 Jul 2025 15:08:51 +0530 Subject: [PATCH 01/18] fix: Data Sync batch processing for large data --- .../DataSyncRepositoryCentral.java | 6 ++ .../GetDataFromVanAndSyncToDBImpl.java | 76 ++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) 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 6b62af69..663515d8 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -204,5 +204,11 @@ else if (masterType.equalsIgnoreCase("P")) { return resultSetList; } +public List> getBatchForBenDetails(String schema, String table, String columnNames, + String whereClause, int limit, int offset) { + jdbcTemplate = getJdbcTemplate(); + String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; + return jdbcTemplate.queryForList(query, limit, offset); + } // End of Data Download Repository } 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 d70404bb..cdef5ced 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -60,10 +60,16 @@ public String syncDataToServer(String requestOBJ, String Authorization) throws E */ String syncTableName = syncUploadDataDigester.getTableName(); if (syncUploadDataDigester != null && syncTableName != null - && syncTableName.equalsIgnoreCase("m_beneficiaryregidmapping")) { + && (syncTableName.equalsIgnoreCase("m_beneficiaryregidmapping"))) { String s = update_M_BeneficiaryRegIdMapping_for_provisioned_benID(syncUploadDataDigester); return s; - } else { + } + else if (syncUploadDataDigester != null && syncTableName != null + && (syncTableName.equalsIgnoreCase("i_beneficiarydetails"))) { + String s = update_I_BeneficiaryDetails_for_processed_in_batches(syncUploadDataDigester); + return s; + } + else { List> dataToBesync = syncUploadDataDigester.getSyncData(); @@ -291,6 +297,72 @@ private String getqueryFor_M_BeneficiaryRegIdMapping(String schemaName, String t return query; } + public String update_I_BeneficiaryDetails_for_processed_in_batches( + SyncUploadDataDigester syncUploadDataDigester) { + + String returnOBJ = null; + List syncData = new ArrayList<>(); + Object[] objArr; + + String query = getQueryFor_I_BeneficiaryDetails(syncUploadDataDigester.getSchemaName(), + syncUploadDataDigester.getTableName()); + + int limit = 1000; + int offset = 0; + + while (true) { + List> batch = dataSyncRepositoryCentral.getBatchForBenDetails( + syncUploadDataDigester.getSchemaName(), + syncUploadDataDigester.getTableName(), + syncUploadDataDigester.getServerColumns(), + " WHERE Processed != 'P' AND VanID IS NOT NULL ", + limit, + offset); + + if (batch == null || batch.isEmpty()) { + break; + } + + for (Map map : batch) { + if (map.get("BeneficiaryDetailsId") != null && map.get("VanID") != null) { + objArr = new Object[3]; + objArr[0] = String.valueOf(syncUploadDataDigester.getSyncedBy()); + objArr[1] = String.valueOf(map.get("BeneficiaryDetailsId")); + objArr[2] = String.valueOf(map.get("VanID")); + syncData.add(objArr); + } + } + + offset += limit; + } + + int[] i = null; + if (syncData != null && syncData.size() > 0) { + i = dataSyncRepositoryCentral.syncDataToCentralDB(syncUploadDataDigester.getSchemaName(), + syncUploadDataDigester.getTableName(), ServerColumnsNotRequired, query, syncData); + + if (i.length == syncData.size()) { + returnOBJ = "data sync passed"; + } + } else { + returnOBJ = "data sync passed"; + } + + return returnOBJ; + } + + private String getQueryFor_I_BeneficiaryDetails(String schemaName, String tableName) { + StringBuilder queryBuilder = new StringBuilder(" UPDATE "); + queryBuilder.append(schemaName + "." + tableName); + queryBuilder.append(" SET "); + queryBuilder.append("Processed = 'P', SyncedDate = now(), SyncedBy = ? "); + queryBuilder.append(" WHERE "); + queryBuilder.append("BeneficiaryDetailsId = ? "); + queryBuilder.append(" AND "); + queryBuilder.append("VanID = ? "); + return queryBuilder.toString(); + } + public String getQueryToInsertDataToServerDB(String schemaName, String tableName, String serverColumns) { String[] columnsArr = null; if (serverColumns != null) From ee6d4592525b72a5048bb14cb64c601ca318cb95 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Thu, 3 Jul 2025 10:46:50 +0530 Subject: [PATCH 02/18] fix: use parameterized query --- .../DataSyncRepositoryCentral.java | 70 +++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) 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 663515d8..6a851e99 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -204,11 +204,71 @@ else if (masterType.equalsIgnoreCase("P")) { return resultSetList; } -public List> getBatchForBenDetails(String schema, String table, String columnNames, - String whereClause, int limit, int offset) { - jdbcTemplate = getJdbcTemplate(); - String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; - return jdbcTemplate.queryForList(query, limit, offset); +// public List> getBatchForBenDetails(String schema, String table, String columnNames, +// String whereClause, int limit, int offset) { +// jdbcTemplate = getJdbcTemplate(); +// String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; +// return jdbcTemplate.queryForList(query, limit, offset); +// } + + +public List> getBatchForBenDetails( + String schema, + String table, + String columnNames, + String whereClause, + int limit, + int offset +) { + // Validate identifiers + validateIdentifier(schema, "Schema"); + validateIdentifier(table, "Table"); + validateColumnNames(columnNames); + validateWhereClause(whereClause); + + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append("SELECT ") + .append(columnNames) + .append(" FROM ") + .append(schema).append(".").append(table); + + if (whereClause != null && !whereClause.trim().isEmpty()) { + queryBuilder.append(" ").append(whereClause); } + + queryBuilder.append(" LIMIT ? OFFSET ?"); + + String query = queryBuilder.toString(); + + List> results = getJdbcTemplate().queryForList( + query, + limit, + offset + ); + + return results; +} + +private void validateIdentifier(String identifier, String type) { + if (identifier == null || !identifier.matches("^[a-zA-Z0-9_]+$")) { + throw new IllegalArgumentException(type + " contains invalid characters: " + identifier); + } +} + +private void validateColumnNames(String columnNames) { + if (columnNames == null || !columnNames.matches("^[a-zA-Z0-9_, ]+$")) { + throw new IllegalArgumentException("Column names contain invalid characters: " + columnNames); + } +} + +private void validateWhereClause(String whereClause) { + if (whereClause != null && !whereClause.trim().isEmpty()) { + if (!whereClause.matches("^[a-zA-Z0-9_ ='<>()!]+$")) { + throw new IllegalArgumentException("Where clause contains invalid characters: " + whereClause); + } + } +} + + // End of Data Download Repository } From 3ea78f040a26a3075f4a967889da66c0458ca662 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Fri, 11 Jul 2025 12:48:14 +0530 Subject: [PATCH 03/18] fix: revert the updated query --- .../DataSyncRepositoryCentral.java | 68 ++----------------- 1 file changed, 5 insertions(+), 63 deletions(-) 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 6a851e99..a671f457 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -204,71 +204,13 @@ else if (masterType.equalsIgnoreCase("P")) { return resultSetList; } -// public List> getBatchForBenDetails(String schema, String table, String columnNames, -// String whereClause, int limit, int offset) { -// jdbcTemplate = getJdbcTemplate(); -// String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; -// return jdbcTemplate.queryForList(query, limit, offset); -// } - - -public List> getBatchForBenDetails( - String schema, - String table, - String columnNames, - String whereClause, - int limit, - int offset -) { - // Validate identifiers - validateIdentifier(schema, "Schema"); - validateIdentifier(table, "Table"); - validateColumnNames(columnNames); - validateWhereClause(whereClause); - - StringBuilder queryBuilder = new StringBuilder(); - queryBuilder.append("SELECT ") - .append(columnNames) - .append(" FROM ") - .append(schema).append(".").append(table); - - if (whereClause != null && !whereClause.trim().isEmpty()) { - queryBuilder.append(" ").append(whereClause); +public List> getBatchForBenDetails(String schema, String table, String columnNames, + String whereClause, int limit, int offset) { + jdbcTemplate = getJdbcTemplate(); + String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; + return jdbcTemplate.queryForList(query, limit, offset); } - queryBuilder.append(" LIMIT ? OFFSET ?"); - - String query = queryBuilder.toString(); - - List> results = getJdbcTemplate().queryForList( - query, - limit, - offset - ); - - return results; -} - -private void validateIdentifier(String identifier, String type) { - if (identifier == null || !identifier.matches("^[a-zA-Z0-9_]+$")) { - throw new IllegalArgumentException(type + " contains invalid characters: " + identifier); - } -} - -private void validateColumnNames(String columnNames) { - if (columnNames == null || !columnNames.matches("^[a-zA-Z0-9_, ]+$")) { - throw new IllegalArgumentException("Column names contain invalid characters: " + columnNames); - } -} - -private void validateWhereClause(String whereClause) { - if (whereClause != null && !whereClause.trim().isEmpty()) { - if (!whereClause.matches("^[a-zA-Z0-9_ ='<>()!]+$")) { - throw new IllegalArgumentException("Where clause contains invalid characters: " + whereClause); - } - } -} - // End of Data Download Repository } From 4357ca18837568e30fea638c8fd46dd37541e662 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Mon, 14 Jul 2025 17:17:25 +0530 Subject: [PATCH 04/18] fix: add token if it is missing while calling restTemplate --- .../MMUDataSyncVanToServer.java | 11 +++++- .../GetDataFromVanAndSyncToDBImpl.java | 4 +- .../com/iemr/mmu/utils/RestTemplateUtil.java | 38 ++++++++++++++----- 3 files changed, 39 insertions(+), 14 deletions(-) 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 dedad0eb..eeb54e9f 100644 --- a/src/main/java/com/iemr/mmu/controller/dataSyncLayerCentral/MMUDataSyncVanToServer.java +++ b/src/main/java/com/iemr/mmu/controller/dataSyncLayerCentral/MMUDataSyncVanToServer.java @@ -36,9 +36,11 @@ import com.iemr.mmu.service.dataSyncLayerCentral.FetchDownloadDataImpl; import com.iemr.mmu.service.dataSyncLayerCentral.GetDataFromVanAndSyncToDBImpl; import com.iemr.mmu.service.dataSyncLayerCentral.GetMasterDataFromCentralForVanImpl; +import com.iemr.mmu.utils.CookieUtil; import com.iemr.mmu.utils.response.OutputResponse; import io.swagger.v3.oas.annotations.Operation; +import jakarta.servlet.http.HttpServletRequest; /*** * @operation Class used for data sync from van-to-server & server-to-van @@ -58,10 +60,15 @@ public class MMUDataSyncVanToServer { @Operation(summary = "Sync data from van-to-server") @PostMapping(value = { "/van-to-server" }, consumes = "application/json", produces = "application/json") public String dataSyncToServer(@RequestBody String requestOBJ, - @RequestHeader(value = "Authorization") String Authorization) { + @RequestHeader(value = "Authorization") String Authorization, HttpServletRequest request) { OutputResponse response = new OutputResponse(); + + logger.info("test: vanto server auth="+Authorization); try { - String s = getDataFromVanAndSyncToDBImpl.syncDataToServer(requestOBJ, Authorization); + String jwtToken = CookieUtil.getJwtTokenFromCookie(request); + logger.info("test: vanto server token="+jwtToken); + + String s = getDataFromVanAndSyncToDBImpl.syncDataToServer(requestOBJ, Authorization, jwtToken); if (s != null) response.setResponse(s); else 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 cdef5ced..cbee19e3 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -49,8 +49,8 @@ public class GetDataFromVanAndSyncToDBImpl implements GetDataFromVanAndSyncToDB @Autowired private DataSyncRepositoryCentral dataSyncRepositoryCentral; - public String syncDataToServer(String requestOBJ, String Authorization) throws Exception { - + public String syncDataToServer(String requestOBJ, String Authorization, String token) throws Exception { +System.out.println("Test: token from sync data="+token); // feed sync request ObjectMapper mapper = new ObjectMapper(); SyncUploadDataDigester syncUploadDataDigester = mapper.readValue(requestOBJ, SyncUploadDataDigester.class); diff --git a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java index cf07391c..0c61681f 100644 --- a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java +++ b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java @@ -23,16 +23,33 @@ public static HttpEntity createRequestEntity(Object body, String authori headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + authorization); } - if (jwtToken == null || jwtToken.isEmpty()) { - ServletRequestAttributes attrs = - (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (attrs != null) { - HttpServletRequest request = attrs.getRequest(); - try { - jwtToken = CookieUtil.getJwtTokenFromCookie(request); - } catch (Exception e) { - logger.error("Error while getting JWT token from cookie: {}", e.getMessage()); - } + // if (jwtToken == null || jwtToken.isEmpty()) { + // ServletRequestAttributes attrs = + // (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + // if (attrs != null) { + // HttpServletRequest request = attrs.getRequest(); + // try { + // jwtToken = CookieUtil.getJwtTokenFromCookie(request); + // } catch (Exception e) { + // logger.error("Error while getting JWT token from cookie: {}", e.getMessage()); + // } + // } + // } + + ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + + if ((jwtToken == null || jwtToken.isEmpty()) && attrs != null) { + HttpServletRequest request = attrs.getRequest(); + try { + jwtToken = CookieUtil.getJwtTokenFromCookie(request); + } catch (Exception e) { + logger.error("Error while getting JWT token from cookie: {}", e.getMessage()); + } + + String jwtTokenHeader = request.getHeader("JwtToken"); + if (jwtTokenHeader != null && !jwtTokenHeader.isEmpty()) { + // headers.add("JwtToken", jwtTokenHeader); + jwtToken = jwtTokenHeader; } } @@ -41,6 +58,7 @@ public static HttpEntity createRequestEntity(Object body, String authori headers.add(HttpHeaders.COOKIE, "Jwttoken=" + jwtToken); } + logger.info("Test header token="+headers); return new HttpEntity<>(body, headers); } From 5bdf92b4290487f2d6d852934714f1003b190ae2 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 15 Jul 2025 10:10:29 +0530 Subject: [PATCH 05/18] fix: update the properties --- .../GetDataFromVanAndSyncToDBImpl.java | 5 +++-- src/main/resources/application.properties | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) 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 cbee19e3..aab8e150 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -50,7 +50,7 @@ public class GetDataFromVanAndSyncToDBImpl implements GetDataFromVanAndSyncToDB private DataSyncRepositoryCentral dataSyncRepositoryCentral; public String syncDataToServer(String requestOBJ, String Authorization, String token) throws Exception { -System.out.println("Test: token from sync data="+token); +System.out.println("Test: token from sync data="+ requestOBJ); // feed sync request ObjectMapper mapper = new ObjectMapper(); SyncUploadDataDigester syncUploadDataDigester = mapper.readValue(requestOBJ, SyncUploadDataDigester.class); @@ -59,6 +59,7 @@ public String syncDataToServer(String requestOBJ, String Authorization, String t * InputMapper.gson().fromJson(requestOBJ, SyncUploadDataDigester.class); */ String syncTableName = syncUploadDataDigester.getTableName(); + System.out.println("Test: syncTableName from sync data="+ syncTableName); if (syncUploadDataDigester != null && syncTableName != null && (syncTableName.equalsIgnoreCase("m_beneficiaryregidmapping"))) { String s = update_M_BeneficiaryRegIdMapping_for_provisioned_benID(syncUploadDataDigester); @@ -307,7 +308,7 @@ public String update_I_BeneficiaryDetails_for_processed_in_batches( String query = getQueryFor_I_BeneficiaryDetails(syncUploadDataDigester.getSchemaName(), syncUploadDataDigester.getTableName()); - int limit = 1000; + int limit = 500; int offset = 0; while (true) { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d172f4aa..2e6ce84f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,6 +7,8 @@ spring.datasource.tomcat.remove-abandoned=true spring.datasource.tomcat.remove-abandoned-timeout=1800 spring.datasource.tomcat.logAbandoned=true spring.datasource.continue-on-error=true +spring.datasource.tomcat.max-wait=60000 + ## below line added by neeraj for reset abandoned DB connection from connection pool spring.datasource.tomcat.jdbc-interceptors=ResetAbandonedTimer @@ -46,3 +48,8 @@ logging.level.org.springframework=INFO spring.main.allow-circular-references=true spring.main.allow-bean-definition-overriding=true + +spring.datasource.tomcat.testOnBorrow=true +spring.datasource.tomcat.validationQuery=SELECT 1 +spring.datasource.tomcat.validationInterval=30000 # 30 sec +logging.level.org.apache.tomcat.jdbc.pool=DEBUG From acb09a0d824b819c17ec7cd35defed03d9599c42 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 15 Jul 2025 14:16:26 +0530 Subject: [PATCH 06/18] fix: sync group wise --- .../DataSyncRepositoryCentral.java | 361 +++---- .../GetDataFromVanAndSyncToDBImpl.java | 949 ++++++++++-------- 2 files changed, 670 insertions(+), 640 deletions(-) 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 a671f457..f583b357 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -1,216 +1,175 @@ -/* -* AMRIT – Accessible Medical Records via Integrated Technology -* Integrated EHR (Electronic Health Records) Solution -* -* Copyright (C) "Piramal Swasthya Management and Research Institute" -* -* This file is part of AMRIT. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ package com.iemr.mmu.service.dataSyncLayerCentral; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.sql.DataSource; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; -/*** - * - * @author NE298657 - * - */ +import javax.sql.DataSource; +import java.sql.Timestamp; +import java.sql.Statement; // Import Statement for batchUpdate result interpretation +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; @Service public class DataSyncRepositoryCentral { - @Autowired - private DataSource dataSource; - - private JdbcTemplate jdbcTemplate; - - private JdbcTemplate getJdbcTemplate() { - return new JdbcTemplate(dataSource); - - } - - private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); - - // Data Upload Repository - public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, String vanSerialNo, String vanID, - String vanAutoIncColumnName, int syncFacilityID) { - jdbcTemplate = getJdbcTemplate(); - - List params = new ArrayList<>(); - - StringBuilder queryBuilder = new StringBuilder("SELECT "); - queryBuilder.append(vanAutoIncColumnName); - queryBuilder.append(" FROM "); - queryBuilder.append(schemaName+"."+tableName); - - //params.add(vanAutoIncColumnName); - //params.add(schemaName); - //params.add(tableName); - - StringBuilder whereClause = new StringBuilder(); - whereClause.append(" WHERE "); - whereClause.append("VanSerialNo = ?"); - params.add(vanSerialNo); - - if ((tableName.equalsIgnoreCase("t_patientissue") || tableName.equalsIgnoreCase("t_physicalstockentry") - || tableName.equalsIgnoreCase("t_stockadjustment") || tableName.equalsIgnoreCase("t_saitemmapping") - || tableName.equalsIgnoreCase("t_stocktransfer") || tableName.equalsIgnoreCase("t_patientreturn") - || tableName.equalsIgnoreCase("t_facilityconsumption") || tableName.equalsIgnoreCase("t_indent") - || tableName.equalsIgnoreCase("t_indentorder") || tableName.equalsIgnoreCase("t_indentissue") - || tableName.equalsIgnoreCase("t_itemstockentry") || tableName.equalsIgnoreCase("t_itemstockexit")) - && syncFacilityID > 0) { - - whereClause.append(" AND "); - whereClause.append("SyncFacilityID = ?"); - params.add(syncFacilityID); - - } - - else { - - whereClause.append(" AND "); - whereClause.append("VanID = ?"); - params.add(vanID); - - } - - queryBuilder.append(whereClause); - String query = queryBuilder.toString(); - Object[] queryParams = params.toArray(); - List> resultSet = jdbcTemplate.queryForList(query, queryParams); - if (resultSet != null && resultSet.size() > 0) - return 1; - else - return 0; - } - - // Method for synchronization of data to central DB - public int[] syncDataToCentralDB(String schema, String tableName, String serverColumns, String query, - List syncDataList) { - jdbcTemplate = getJdbcTemplate(); - if (query.startsWith("INSERT")) { - for (int i = 0; i < syncDataList.size(); i++) { - Object[] array = syncDataList.get(i);// Arrey 1 - - if (query.startsWith("INSERT")) { -// array = new Object[] {serverColumns, array }; - syncDataList.set(i, array); - } - } - } else { - for (int i = 0; i < syncDataList.size(); i++) { - - Object[] array = syncDataList.get(i);// Arrey 1 - String[] columnsArray = null; - if(null != serverColumns) - columnsArray = serverColumns.split(","); // arrey 2 - - List Newarray = new ArrayList<>(); - - int arrayIndex = 0; - int columnsArrayIndex = 0; - //Newarray.add(schema); - //Newarray.add(tableName); - //while (columnsArrayIndex < columnsArray.length || arrayIndex < array.length) { - if (null != columnsArray && columnsArrayIndex < columnsArray.length) { - Newarray.add(columnsArray[columnsArrayIndex]); - columnsArrayIndex++; - } - - /* - * if (arrayIndex < array.length) { Newarray.add(array); arrayIndex++; } - */ - //} - - // Convert Newarray back to an array - //Object[] resultArray = Newarray.toArray(new Object[0]); - syncDataList.set(i, array); - - } - } - // start batch insert/update - int[] i = jdbcTemplate.batchUpdate(query, syncDataList); - return i; - - } - - // End of Data Upload Repository - - public List> getMasterDataFromTable(String schema, String table, String columnNames, - String masterType, Timestamp lastDownloadDate, Integer vanID, Integer psmID) throws Exception { - jdbcTemplate = getJdbcTemplate(); - List> resultSetList =new ArrayList<>(); - String baseQuery = ""; - if (masterType != null) { - if (lastDownloadDate != null) { - if (masterType.equalsIgnoreCase("A")) { - baseQuery += " SELECT " + columnNames + " FROM " + schema + "." + table - + " WHERE LastModDate >= ? "; - resultSetList = jdbcTemplate.queryForList(baseQuery,lastDownloadDate); - - } - else if (masterType.equalsIgnoreCase("V")) { - baseQuery += " SELECT " + columnNames + " FROM " + schema + "." + table - + " WHERE LastModDate >= ? AND VanID = ? "; - resultSetList = jdbcTemplate.queryForList(baseQuery,lastDownloadDate,vanID); - } - else if (masterType.equalsIgnoreCase("P")) { - baseQuery += " SELECT " + columnNames + " FROM " + schema + "." + table - + " WHERE LastModDate >= ? AND ProviderServiceMapID = ? "; - resultSetList = jdbcTemplate.queryForList(baseQuery,lastDownloadDate,psmID); - } - } else { - if (masterType.equalsIgnoreCase("A")) { - baseQuery += " SELECT " + columnNames + " FROM " + schema + "." + table; - resultSetList = jdbcTemplate.queryForList(baseQuery); - } - else if (masterType.equalsIgnoreCase("V")) { - baseQuery += " SELECT " + columnNames + " FROM " + schema + "." + table + " WHERE VanID = ? "; - resultSetList = jdbcTemplate.queryForList(baseQuery,vanID); - } - else if (masterType.equalsIgnoreCase("P")) { - baseQuery += " SELECT " + columnNames + " FROM " + schema + "." + table - + " WHERE ProviderServiceMapID = ? "; - resultSetList = jdbcTemplate.queryForList(baseQuery,psmID); - } - } - } - logger.info("Select query central: " + baseQuery); - logger.info("Last Downloaded Date " + lastDownloadDate); - logger.info("Result set Details: " + resultSetList); - return resultSetList; - } - -public List> getBatchForBenDetails(String schema, String table, String columnNames, - String whereClause, int limit, int offset) { + @Autowired + private DataSource dataSource; + + private JdbcTemplate jdbcTemplate; + + // Lazily initialize jdbcTemplate to ensure DataSource is available + private JdbcTemplate getJdbcTemplate() { + if (this.jdbcTemplate == null) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + return this.jdbcTemplate; + } + + private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); + + // Data Upload Repository + public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, String vanSerialNo, String vanID, + String vanAutoIncColumnName, int syncFacilityID) { jdbcTemplate = getJdbcTemplate(); - String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; - return jdbcTemplate.queryForList(query, limit, offset); + + List params = new ArrayList<>(); + + StringBuilder queryBuilder = new StringBuilder("SELECT "); + queryBuilder.append(vanAutoIncColumnName); + queryBuilder.append(" FROM "); + queryBuilder.append(schemaName).append(".").append(tableName); + + StringBuilder whereClause = new StringBuilder(); + whereClause.append(" WHERE "); + whereClause.append("VanSerialNo = ?"); + params.add(vanSerialNo); + + if (Arrays.asList("t_patientissue", "t_physicalstockentry", "t_stockadjustment", "t_saitemmapping", + "t_stocktransfer", "t_patientreturn", "t_facilityconsumption", "t_indent", + "t_indentorder", "t_indentissue", "t_itemstockentry", "t_itemstockexit") + .contains(tableName.toLowerCase()) && syncFacilityID > 0) { + + whereClause.append(" AND "); + whereClause.append("SyncFacilityID = ?"); + params.add(syncFacilityID); + + } else { + whereClause.append(" AND "); + whereClause.append("VanID = ?"); + params.add(vanID); + } + + queryBuilder.append(whereClause); + String query = queryBuilder.toString(); + Object[] queryParams = params.toArray(); + + logger.debug("Checking record existence query: {} with params: {}", query, Arrays.toString(queryParams)); + + try { + List> resultSet = jdbcTemplate.queryForList(query, queryParams); + if (resultSet != null && !resultSet.isEmpty()) { + logger.debug("Record found for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); + return 1; + } else { + logger.debug("No record found for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); + return 0; + } + } catch (org.springframework.dao.EmptyResultDataAccessException e) { + logger.debug("No record found (EmptyResultDataAccessException) for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); + return 0; + } catch (Exception e) { + logger.error("Database error during checkRecordIsAlreadyPresentOrNot for table {}: VanSerialNo={}, VanID={}. Error: {}", tableName, vanSerialNo, vanID, e.getMessage(), e); + throw new RuntimeException("Failed to check record existence: " + e.getMessage(), e); // Re-throw or handle as appropriate + } + } + + // Method for synchronization of data to central DB + public int[] syncDataToCentralDB(String schema, String tableName, String serverColumns, String query, + List syncDataList) { + jdbcTemplate = getJdbcTemplate(); + logger.info("Executing batch operation for table: {}. Query type: {}. Number of records: {}", tableName, query.startsWith("INSERT") ? "INSERT" : "UPDATE", syncDataList.size()); + logger.debug("Query: {}", query); + + try { + // Start batch insert/update + int[] i = jdbcTemplate.batchUpdate(query, syncDataList); + logger.info("Batch operation completed for table {}. Results: {}", tableName, Arrays.toString(i)); + return i; + } catch (Exception e) { + logger.error("Exception during batch update for table {}: {}", tableName, e.getMessage(), e); + // Re-throw the exception to be handled by the service layer, so specific errors can be captured. + throw new RuntimeException("Batch sync failed for table " + tableName + ": " + e.getMessage(), e); + } } + // End of Data Upload Repository + + public List> getMasterDataFromTable(String schema, String table, String columnNames, + String masterType, Timestamp lastDownloadDate, Integer vanID, Integer psmID) throws Exception { + jdbcTemplate = getJdbcTemplate(); + List> resultSetList = new ArrayList<>(); + StringBuilder baseQueryBuilder = new StringBuilder(" SELECT ").append(columnNames).append(" FROM ").append(schema).append(".").append(table); + List params = new ArrayList<>(); + + if (masterType != null) { + if (lastDownloadDate != null) { + baseQueryBuilder.append(" WHERE LastModDate >= ? "); + params.add(lastDownloadDate); + + if (masterType.equalsIgnoreCase("V")) { + baseQueryBuilder.append(" AND VanID = ? "); + params.add(vanID); + } else if (masterType.equalsIgnoreCase("P")) { + baseQueryBuilder.append(" AND ProviderServiceMapID = ? "); + params.add(psmID); + } + } else { + if (masterType.equalsIgnoreCase("V")) { + baseQueryBuilder.append(" WHERE VanID = ? "); + params.add(vanID); + } else if (masterType.equalsIgnoreCase("P")) { + baseQueryBuilder.append(" WHERE ProviderServiceMapID = ? "); + params.add(psmID); + } + } + } + + String finalQuery = baseQueryBuilder.toString(); + logger.info("Select query central: {}", finalQuery); + logger.info("Last Downloaded Date: {}", lastDownloadDate); + logger.info("Query Params: {}", params); + + try { + if (params.isEmpty()) { + resultSetList = jdbcTemplate.queryForList(finalQuery); + } else { + resultSetList = jdbcTemplate.queryForList(finalQuery, params.toArray()); + } + } catch (Exception e) { + logger.error("Error fetching master data from table {}: {}", table, e.getMessage(), e); + throw new RuntimeException("Failed to fetch master data: " + e.getMessage(), e); + } + + logger.info("Result set Details size: {}", resultSetList.size()); + return resultSetList; + } + + public List> getBatchForBenDetails(String schema, String table, String columnNames, + String whereClause, int limit, int offset) { + jdbcTemplate = getJdbcTemplate(); + String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; + logger.debug("Fetching batch for beneficiary details. Query: {}, Limit: {}, Offset: {}", query, limit, offset); + try { + return jdbcTemplate.queryForList(query, limit, offset); + } catch (Exception e) { + logger.error("Error fetching batch for beneficiary details from table {}: {}", table, e.getMessage(), e); + throw new RuntimeException("Failed to fetch batch data: " + e.getMessage(), e); + } + } - // End of Data Download Repository -} + // End of Data Download Repository +} \ No newline at end of file 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 aab8e150..f2107d96 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -1,458 +1,529 @@ -/* -* AMRIT – Accessible Medical Records via Integrated Technology -* Integrated EHR (Electronic Health Records) Solution -* -* Copyright (C) "Piramal Swasthya Management and Research Institute" -* -* This file is part of AMRIT. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ package com.iemr.mmu.service.dataSyncLayerCentral; -import java.sql.Timestamp; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.HashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.fasterxml.jackson.databind.ObjectMapper; import com.iemr.mmu.data.syncActivity_syncLayer.SyncUploadDataDigester; -import com.iemr.mmu.utils.mapper.InputMapper; -/*** - * - * @author NE298657 - * - */ @Service public class GetDataFromVanAndSyncToDBImpl implements GetDataFromVanAndSyncToDB { - private static final String ServerColumnsNotRequired = null; - @Autowired - private DataSyncRepositoryCentral dataSyncRepositoryCentral; - - public String syncDataToServer(String requestOBJ, String Authorization, String token) throws Exception { -System.out.println("Test: token from sync data="+ requestOBJ); - // feed sync request - ObjectMapper mapper = new ObjectMapper(); - SyncUploadDataDigester syncUploadDataDigester = mapper.readValue(requestOBJ, SyncUploadDataDigester.class); - /* - * SyncUploadDataDigester syncUploadDataDigester = - * InputMapper.gson().fromJson(requestOBJ, SyncUploadDataDigester.class); - */ - String syncTableName = syncUploadDataDigester.getTableName(); - System.out.println("Test: syncTableName from sync data="+ syncTableName); - if (syncUploadDataDigester != null && syncTableName != null - && (syncTableName.equalsIgnoreCase("m_beneficiaryregidmapping"))) { - String s = update_M_BeneficiaryRegIdMapping_for_provisioned_benID(syncUploadDataDigester); - return s; - } - else if (syncUploadDataDigester != null && syncTableName != null - && (syncTableName.equalsIgnoreCase("i_beneficiarydetails"))) { - String s = update_I_BeneficiaryDetails_for_processed_in_batches(syncUploadDataDigester); - return s; - } - else { - - List> dataToBesync = syncUploadDataDigester.getSyncData(); - - Object[] objArr; - - // sync data 'list of object array' - List syncDataListInsert = new ArrayList<>(); - List syncDataListUpdate = new ArrayList<>(); - - int pointer; - String vanSerialNo; - String vanID; - int recordCheck; - int syncFacilityID = 0; - - for (Map map : dataToBesync) { - pointer = 0; - recordCheck = 0; - vanSerialNo = ""; - vanID = ""; - - vanSerialNo = String.valueOf(map.get(syncUploadDataDigester.getVanAutoIncColumnName())); - vanID = String.valueOf(map.get("VanID")); - - map.replace("SyncedBy", syncUploadDataDigester.getSyncedBy()); - - map.replace("date_format(SyncedDate,'%Y-%m-%d %H:%i:%s')", String.valueOf(LocalDateTime.now())); - - if (syncUploadDataDigester.getFacilityID() != null) { - Double changeDoubleToIntegerID = 0.0; - switch (syncTableName) { - case "t_indent": { - if (map.containsKey("FromFacilityID") && map.get("FromFacilityID") != null) { - changeDoubleToIntegerID = (Double) map.get("FromFacilityID"); - if (changeDoubleToIntegerID.intValue() == syncUploadDataDigester.getFacilityID()) - map.replace("Processed", "P"); - } - - } - case "t_indentorder": { - if (map.containsKey("FromFacilityID") && map.get("FromFacilityID") != null) - changeDoubleToIntegerID = (Double) map.get("FromFacilityID"); - if (changeDoubleToIntegerID.intValue() == syncUploadDataDigester.getFacilityID()) - map.replace("Processed", "P"); - } - case "t_indentissue": { - if (map.containsKey("ToFacilityID") && map.get("ToFacilityID") != null) { - changeDoubleToIntegerID = (Double) map.get("ToFacilityID"); - if (changeDoubleToIntegerID.intValue() == syncUploadDataDigester.getFacilityID()) - map.replace("Processed", "P"); - } - - } - // here a change in rule, will compare with toFacilityID - case "t_stocktransfer": { - if (map.containsKey("TransferToFacilityID") && map.get("TransferToFacilityID") != null) { - changeDoubleToIntegerID = (Double) map.get("TransferToFacilityID"); - if (changeDoubleToIntegerID.intValue() == syncUploadDataDigester.getFacilityID()) - map.replace("Processed", "P"); - } - - } - case "t_itemstockentry": { - - if (map.containsKey("FacilityID") && map.get("FacilityID") != null) { - changeDoubleToIntegerID = (Double) map.get("FacilityID"); - if (changeDoubleToIntegerID.intValue() == syncUploadDataDigester.getFacilityID()) - map.replace("Processed", "P"); - } - - } - default: - - } - - } - - if (map.containsKey("SyncFacilityID")) { - //double syncFaciltyID = (double) map.get("SyncFacilityID"); - syncFacilityID = (int) map.get("SyncFacilityID"); - } - - recordCheck = dataSyncRepositoryCentral.checkRecordIsAlreadyPresentOrNot( - syncUploadDataDigester.getSchemaName(), syncUploadDataDigester.getTableName(), vanSerialNo, - vanID, syncUploadDataDigester.getVanAutoIncColumnName(), syncFacilityID); - - if (recordCheck == 0) { - objArr = new Object[map.size()]; - } else { - objArr = new Object[map.size() + 2]; - } - - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() != null) { - if (String.valueOf(entry.getValue()).equalsIgnoreCase("false") - || String.valueOf(entry.getValue()).equalsIgnoreCase("true")) - objArr[pointer] = entry.getValue(); - else - objArr[pointer] = String.valueOf(entry.getValue()); - } else - objArr[pointer] = entry.getValue(); - - pointer++; - } - - if (recordCheck == 0) { - syncDataListInsert.add(objArr); - } else { - - - objArr[pointer] = String.valueOf(vanSerialNo); - - if ((syncTableName.equalsIgnoreCase("t_patientissue") - || syncTableName.equalsIgnoreCase("t_physicalstockentry") - || syncTableName.equalsIgnoreCase("t_stockadjustment") - || syncTableName.equalsIgnoreCase("t_saitemmapping") - || syncTableName.equalsIgnoreCase("t_stocktransfer") - || syncTableName.equalsIgnoreCase("t_patientreturn") - || syncTableName.equalsIgnoreCase("t_facilityconsumption") - || syncTableName.equalsIgnoreCase("t_indent") - || syncTableName.equalsIgnoreCase("t_indentorder") - || syncTableName.equalsIgnoreCase("t_indentissue") - || syncTableName.equalsIgnoreCase("t_itemstockentry") - || syncTableName.equalsIgnoreCase("t_itemstockexit")) - && map.containsKey("SyncFacilityID")) { - - objArr[pointer + 1] = String.valueOf(map.get("SyncFacilityID")); - } else - objArr[pointer + 1] = String.valueOf(vanID); - - syncDataListUpdate.add(objArr); - } - - } - - int[] i = null; - if (syncDataListInsert != null && syncDataListInsert.size() > 0) { - // schema name hard coded(Insert query builder) - String queryInsert = getQueryToInsertDataToServerDB(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName(),syncUploadDataDigester.getServerColumns()); - - // call repository to execute the query with given data list(Insert) - i = dataSyncRepositoryCentral.syncDataToCentralDB( - syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName(), syncUploadDataDigester.getServerColumns(), queryInsert, - syncDataListInsert); - } - - int[] j = null; - if (syncDataListUpdate != null && syncDataListUpdate.size() > 0) { - // schema name hard coded(Update query builder) - String queryUpdate = getQueryToUpdateDataToServerDB(syncUploadDataDigester.getSchemaName(), syncUploadDataDigester.getServerColumns(), - syncUploadDataDigester.getTableName()); - - // call repository to execute the query with given data list(Update) - j = dataSyncRepositoryCentral.syncDataToCentralDB(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName(), ServerColumnsNotRequired, queryUpdate, - syncDataListUpdate); - } - - // validating if data sync successfully - if ((i != null && syncDataListInsert.size() != i.length) - || (j != null && syncDataListUpdate.size() != j.length)) - return null; - else - return "data sync passed"; - - } - - } - - public String update_M_BeneficiaryRegIdMapping_for_provisioned_benID( - SyncUploadDataDigester syncUploadDataDigester) { - String returnOBJ = null; - List> dataToBesync = syncUploadDataDigester.getSyncData(); - - Object[] objArr; - // sync data 'list of object array' - List syncData = new ArrayList<>(); - - String query = getqueryFor_M_BeneficiaryRegIdMapping(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName()); - - for (Map map : dataToBesync) { - if (map.get("BenRegId") != null && map.get("BeneficiaryID") != null && map.get("VanID") != null) { - objArr = new Object[4]; - objArr[0] = String.valueOf(syncUploadDataDigester.getSyncedBy()); - objArr[1] = String.valueOf(map.get("BenRegId")); - objArr[2] = String.valueOf(map.get("BeneficiaryID")); - objArr[3] = String.valueOf(map.get("VanID")); - - syncData.add(objArr); - } - } - int[] i = null; - - if (syncData != null && syncData.size() > 0) { - i = dataSyncRepositoryCentral.syncDataToCentralDB(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName(), ServerColumnsNotRequired, query, syncData); - - if (i.length == syncData.size()) { - returnOBJ = "data sync passed"; - } - } else { - returnOBJ = "data sync passed"; - } - - return returnOBJ; - - } - - private String getqueryFor_M_BeneficiaryRegIdMapping(String schemaName, String tableName) { - - StringBuilder queryBuilder = new StringBuilder(" UPDATE "); - queryBuilder.append(schemaName+"."+tableName); - queryBuilder.append(" SET "); - queryBuilder.append("Provisioned = true, SyncedDate = now(), syncedBy = ?"); - queryBuilder.append(" WHERE "); - queryBuilder.append(" BenRegId = ? "); - queryBuilder.append(" AND "); - queryBuilder.append(" BeneficiaryID = ? "); - queryBuilder.append(" AND "); - queryBuilder.append(" VanID = ? "); - String query = queryBuilder.toString(); - return query; - } - - public String update_I_BeneficiaryDetails_for_processed_in_batches( - SyncUploadDataDigester syncUploadDataDigester) { - - String returnOBJ = null; - List syncData = new ArrayList<>(); - Object[] objArr; - - String query = getQueryFor_I_BeneficiaryDetails(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName()); - - int limit = 500; - int offset = 0; - - while (true) { - List> batch = dataSyncRepositoryCentral.getBatchForBenDetails( - syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName(), - syncUploadDataDigester.getServerColumns(), - " WHERE Processed != 'P' AND VanID IS NOT NULL ", - limit, - offset); - - if (batch == null || batch.isEmpty()) { - break; - } - - for (Map map : batch) { - if (map.get("BeneficiaryDetailsId") != null && map.get("VanID") != null) { - objArr = new Object[3]; - objArr[0] = String.valueOf(syncUploadDataDigester.getSyncedBy()); - objArr[1] = String.valueOf(map.get("BeneficiaryDetailsId")); - objArr[2] = String.valueOf(map.get("VanID")); - syncData.add(objArr); - } - } - - offset += limit; - } - - int[] i = null; - if (syncData != null && syncData.size() > 0) { - i = dataSyncRepositoryCentral.syncDataToCentralDB(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName(), ServerColumnsNotRequired, query, syncData); - - if (i.length == syncData.size()) { - returnOBJ = "data sync passed"; - } - } else { - returnOBJ = "data sync passed"; - } - - return returnOBJ; - } - - private String getQueryFor_I_BeneficiaryDetails(String schemaName, String tableName) { - StringBuilder queryBuilder = new StringBuilder(" UPDATE "); - queryBuilder.append(schemaName + "." + tableName); - queryBuilder.append(" SET "); - queryBuilder.append("Processed = 'P', SyncedDate = now(), SyncedBy = ? "); - queryBuilder.append(" WHERE "); - queryBuilder.append("BeneficiaryDetailsId = ? "); - queryBuilder.append(" AND "); - queryBuilder.append("VanID = ? "); - return queryBuilder.toString(); - } - - public String getQueryToInsertDataToServerDB(String schemaName, String tableName, String serverColumns) { - String[] columnsArr = null; - if (serverColumns != null) - columnsArr = serverColumns.split(","); - - StringBuilder preparedStatementSetter = new StringBuilder(); - /// StringBuilder updateStatement = new StringBuilder(); - - if (columnsArr != null && columnsArr.length > 0) { - int index = 0; - for (String column : columnsArr) { - if (index == columnsArr.length - 1) { - preparedStatementSetter.append(" ? "); - - } else { - preparedStatementSetter.append(" ?, "); - - } - index++; - } - } - /* - * String query = "INSERT INTO " + schemaName + "." + tableName + "( " + - * serverColumns + ") VALUES ( " + preparedStatementSetter + " ) "; - */ - - StringBuilder queryBuilder = new StringBuilder("INSERT INTO "); - queryBuilder.append(schemaName + "." + tableName); - queryBuilder.append("("); -// queryBuilder.append("?"); - queryBuilder.append(serverColumns); - queryBuilder.append(") VALUES ("); - queryBuilder.append(preparedStatementSetter); - queryBuilder.append(") "); - String query = queryBuilder.toString(); - - return query; - } - - public String getQueryToUpdateDataToServerDB(String schemaName, String serverColumns, String tableName) { - String[] columnsArr = null; - if (serverColumns != null) - columnsArr = serverColumns.split(","); - - StringBuilder preparedStatementSetter = new StringBuilder(); - - if (columnsArr != null && columnsArr.length > 0) { - int index = 0; - for (String column : columnsArr) { - if (index == columnsArr.length - 1) { - preparedStatementSetter.append(column); - preparedStatementSetter.append("= ?"); - } else { - preparedStatementSetter.append(column); - preparedStatementSetter.append("= ?, "); - } - index++; - } - } - - if (tableName.equalsIgnoreCase("t_patientissue") || tableName.equalsIgnoreCase("t_physicalstockentry") - || tableName.equalsIgnoreCase("t_stockadjustment") || tableName.equalsIgnoreCase("t_saitemmapping") - || tableName.equalsIgnoreCase("t_stocktransfer") || tableName.equalsIgnoreCase("t_patientreturn") - || tableName.equalsIgnoreCase("t_facilityconsumption") || tableName.equalsIgnoreCase("t_indent") - || tableName.equalsIgnoreCase("t_indentorder") || tableName.equalsIgnoreCase("t_indentissue") - || tableName.equalsIgnoreCase("t_itemstockentry") || tableName.equalsIgnoreCase("t_itemstockexit")) { - - StringBuilder queryBuilder = new StringBuilder(" UPDATE "); - queryBuilder.append(schemaName+"."+tableName); - queryBuilder.append(" SET "); - queryBuilder.append(preparedStatementSetter); - queryBuilder.append(" WHERE "); - queryBuilder.append(" VanSerialNo =? "); - queryBuilder.append(" AND "); - queryBuilder.append(" SyncFacilityID = ? "); - String query = queryBuilder.toString(); - return query; - } else { - StringBuilder queryBuilder = new StringBuilder(" UPDATE "); - queryBuilder.append(schemaName+"."+tableName); - queryBuilder.append(" SET "); - queryBuilder.append(preparedStatementSetter); - queryBuilder.append(" WHERE "); - queryBuilder.append(" VanSerialNo =? "); - queryBuilder.append(" AND "); - queryBuilder.append(" VanID = ? "); - String query = queryBuilder.toString(); - return query; - } - + private static final String SERVER_COLUMNS_NOT_REQUIRED = null; // Renamed for clarity + private static final Logger logger = LoggerFactory.getLogger(GetDataFromVanAndSyncToDBImpl.class); + + @Autowired + private DataSyncRepositoryCentral dataSyncRepositoryCentral; + + private static final Map> TABLE_GROUPS = new HashMap<>(); + static { + // Group 1: Master data or less frequently changing data + TABLE_GROUPS.put(1, Arrays.asList("m_beneficiaryregidmapping", "m_another_master_table")); + + // Group 2: Transactional data that might involve facility ID + TABLE_GROUPS.put(2, Arrays.asList("t_indent", "t_indentorder", "t_indentissue", "t_stocktransfer", "t_itemstockentry")); + + // Group 3: High volume transactional data + TABLE_GROUPS.put(3, Arrays.asList("i_beneficiarydetails", "t_patientissue", "t_physicalstockentry", + "t_stockadjustment", "t_saitemmapping", "t_patientreturn", + "t_facilityconsumption", "t_itemstockexit")); + // Add more groups as needed, up to 9 + // TABLE_GROUPS.put(4, Arrays.asList("table_in_group_4a", "table_in_group_4b")); + } + + public String syncDataToServer(String requestOBJ, String Authorization, String token) throws Exception { + logger.info("Starting syncDataToServer. Token: {}", token); + + ObjectMapper mapper = new ObjectMapper(); + SyncUploadDataDigester syncUploadDataDigester = mapper.readValue(requestOBJ, SyncUploadDataDigester.class); + + if (syncUploadDataDigester == null || syncUploadDataDigester.getTableName() == null) { + logger.error("Invalid SyncUploadDataDigester object or tableName is null."); + return "Error: Invalid sync request."; + } + + String syncTableName = syncUploadDataDigester.getTableName(); + + // Handle specific tables first, if their logic is distinct + if ("m_beneficiaryregidmapping".equalsIgnoreCase(syncTableName)) { + String result = update_M_BeneficiaryRegIdMapping_for_provisioned_benID(syncUploadDataDigester); + if ("data sync passed".equals(result)) { + return "Sync successful for m_beneficiaryregidmapping."; + } else { + logger.error("Sync failed for m_beneficiaryregidmapping: {}", result); + return "Sync failed for m_beneficiaryregidmapping."; + } + } else if ("i_beneficiarydetails".equalsIgnoreCase(syncTableName)) { + String result = update_I_BeneficiaryDetails_for_processed_in_batches(syncUploadDataDigester); + if ("data sync passed".equals(result)) { + return "Sync successful for i_beneficiarydetails."; + } else { + logger.error("Sync failed for i_beneficiarydetails: {}", result); + return "Sync failed for i_beneficiarydetails."; + } + } else { + // Determine the group for the current table or iterate through all if no specific table is given + boolean syncSuccess = true; + String errorMessage = ""; + + // If a specific table is provided in the request, try to find its group and sync only that table. + // Otherwise, iterate through all defined groups. + if (syncTableName != null && !syncTableName.isEmpty()) { + boolean foundInGroup = false; + for (Map.Entry> entry : TABLE_GROUPS.entrySet()) { + if (entry.getValue().contains(syncTableName.toLowerCase())) { + logger.info("Attempting to sync table '{}' from Group {}", syncTableName, entry.getKey()); + syncSuccess = syncTablesInGroup(syncUploadDataDigester.getSchemaName(), syncTableName, syncUploadDataDigester); + foundInGroup = true; + break; + } + } + if (!foundInGroup) { + logger.warn("Table '{}' not found in any predefined groups. Proceeding with generic sync logic.", syncTableName); + syncSuccess = performGenericTableSync(syncUploadDataDigester); + } + } else { + // If no specific table is in the request (e.g., a general sync trigger), iterate through groups + logger.info("No specific table provided. Attempting to sync all tables group by group."); + for (Map.Entry> entry : TABLE_GROUPS.entrySet()) { + Integer groupId = entry.getKey(); + List tablesInGroup = entry.getValue(); + logger.info("Starting sync for Group {}", groupId); + for (String table : tablesInGroup) { + try { + // Create a new digester for each table within the group, + // or adapt if the original digester contains data for multiple tables. + // For simplicity, assuming syncDataDigester needs to be tailored per table or group. + // If your requestOBJ contains data for only one table at a time, this loop might need adjustment + // to fetch data for each table in the group. + // For now, it will use the syncData from the original requestOBJ, which implies + // the original requestOBJ should represent data for a single table. + // A more robust solution would involve fetching data for each table dynamically. + boolean currentTableSyncResult = syncTablesInGroup(syncUploadDataDigester.getSchemaName(), table, syncUploadDataDigester); + if (!currentTableSyncResult) { + syncSuccess = false; + errorMessage += "Failed to sync table: " + table + " in Group " + groupId + ". "; + logger.error("Sync failed for table '{}' in Group {}. Error: {}", table, groupId, errorMessage); + // Optionally, you can choose to break here or continue to sync other tables in the group/next group + // For now, let's continue to attempt other tables within the group. + } else { + logger.info("Successfully synced table: {} in Group {}", table, groupId); + } + } catch (Exception e) { + syncSuccess = false; + errorMessage += "Exception during sync for table: " + table + " in Group " + groupId + ": " + e.getMessage() + ". "; + logger.error("Exception during sync for table '{}' in Group {}: {}", table, groupId, e.getMessage(), e); + // Continue to attempt other tables + } + } + } + } + + if (syncSuccess) { + return "Overall data sync passed."; + } else { + return "Overall data sync failed. Details: " + errorMessage; + } + } + } + + /** + * Helper method to sync tables belonging to a specific group. + * This method assumes that the `syncUploadDataDigester` will be populated + * with relevant data for the `currentTableName` before calling this. + * In a real-world scenario, you might fetch data for each table here. + */ + private boolean syncTablesInGroup(String schemaName, String currentTableName, SyncUploadDataDigester originalDigester) { + logger.info("Attempting generic sync for table: {}", currentTableName); + // This is a simplification. In a production system, you would likely need + // to retrieve the actual data for 'currentTableName' from the local DB + // based on the group sync approach. For this example, we'll assume the + // originalDigester's syncData is relevant or needs to be re-populated. + + // Create a new digester instance or modify the existing one for the current table + SyncUploadDataDigester tableSpecificDigester = new SyncUploadDataDigester(); + tableSpecificDigester.setSchemaName(schemaName); + tableSpecificDigester.setTableName(currentTableName); + tableSpecificDigester.setSyncedBy(originalDigester.getSyncedBy()); + tableSpecificDigester.setFacilityID(originalDigester.getFacilityID()); + tableSpecificDigester.setVanAutoIncColumnName(originalDigester.getVanAutoIncColumnName()); + tableSpecificDigester.setServerColumns(originalDigester.getServerColumns()); // Assuming serverColumns is generic or set per table + + // !!! IMPORTANT: You'll need to fetch the data for 'currentTableName' from your local DB here. + // The `originalDigester.getSyncData()` might not be correct for all tables in a group. + // For demonstration, I'm just using the original digester's data, which is likely incorrect + // if you're syncing multiple tables from a single request. + // You'll need a method like: dataSyncRepositoryLocal.getDataForTable(currentTableName, ...) + tableSpecificDigester.setSyncData(originalDigester.getSyncData()); // Placeholder: Replace with actual data fetching + + return performGenericTableSync(tableSpecificDigester); + } + + + private String update_M_BeneficiaryRegIdMapping_for_provisioned_benID(SyncUploadDataDigester syncUploadDataDigester) { + logger.info("Processing update_M_BeneficiaryRegIdMapping_for_provisioned_benID for table: {}", syncUploadDataDigester.getTableName()); + List> dataToBesync = syncUploadDataDigester.getSyncData(); + List syncData = new ArrayList<>(); + + String query = getqueryFor_M_BeneficiaryRegIdMapping(syncUploadDataDigester.getSchemaName(), + syncUploadDataDigester.getTableName()); + + for (Map map : dataToBesync) { + if (map.get("BenRegId") != null && map.get("BeneficiaryID") != null && map.get("VanID") != null) { + Object[] objArr = new Object[4]; + objArr[0] = syncUploadDataDigester.getSyncedBy(); // SyncedBy + objArr[1] = String.valueOf(map.get("BenRegId")); + objArr[2] = String.valueOf(map.get("BeneficiaryID")); + objArr[3] = String.valueOf(map.get("VanID")); + syncData.add(objArr); + } else { + logger.warn("Skipping record in m_beneficiaryregidmapping due to missing BenRegId, BeneficiaryID, or VanID: {}", map); + } + } + + if (!syncData.isEmpty()) { + try { + int[] i = dataSyncRepositoryCentral.syncDataToCentralDB(syncUploadDataDigester.getSchemaName(), + syncUploadDataDigester.getTableName(), SERVER_COLUMNS_NOT_REQUIRED, query, syncData); + + if (i.length == syncData.size()) { + logger.info("Successfully updated {} records for m_beneficiaryregidmapping.", i.length); + return "data sync passed"; + } else { + logger.error("Partial update for m_beneficiaryregidmapping. Expected {} updates, got {}. Failed records: {}", syncData.size(), i.length, getFailedRecords(i, syncData)); + return "Partial data sync for m_beneficiaryregidmapping."; + } + } catch (Exception e) { + logger.error("Exception during update for m_beneficiaryregidmapping: {}", e.getMessage(), e); + return "Error during sync for m_beneficiaryregidmapping: " + e.getMessage(); + } + } else { + logger.info("No data to sync for m_beneficiaryregidmapping."); + return "data sync passed"; + } + } + + private String getqueryFor_M_BeneficiaryRegIdMapping(String schemaName, String tableName) { + StringBuilder queryBuilder = new StringBuilder(" UPDATE "); + queryBuilder.append(schemaName).append(".").append(tableName); + queryBuilder.append(" SET "); + queryBuilder.append("Provisioned = true, SyncedDate = now(), syncedBy = ?"); + queryBuilder.append(" WHERE "); + queryBuilder.append(" BenRegId = ? "); + queryBuilder.append(" AND "); + queryBuilder.append(" BeneficiaryID = ? "); + queryBuilder.append(" AND "); + queryBuilder.append(" VanID = ? "); + return queryBuilder.toString(); + } + + public String update_I_BeneficiaryDetails_for_processed_in_batches(SyncUploadDataDigester syncUploadDataDigester) { + logger.info("Processing update_I_BeneficiaryDetails_for_processed_in_batches for table: {}", syncUploadDataDigester.getTableName()); + List syncData = new ArrayList<>(); + + String query = getQueryFor_I_BeneficiaryDetails(syncUploadDataDigester.getSchemaName(), + syncUploadDataDigester.getTableName()); + + int limit = 1000; + int offset = 0; + int totalProcessed = 0; + + String problematicWhereClause = " WHERE Processed <> 'P' AND VanID IS NOT NULL "; // Define it explicitly + + while (true) { + List> batch; + try { + // *** ADD THIS LINE *** + logger.info("DEBUG: Passing whereClause to getBatchForBenDetails: [{}]", problematicWhereClause); + + batch = dataSyncRepositoryCentral.getBatchForBenDetails( + syncUploadDataDigester.getSchemaName(), + syncUploadDataDigester.getTableName(), + syncUploadDataDigester.getServerColumns(), + problematicWhereClause, // Use the variable + limit, + offset); + } catch (Exception e) { + logger.error("Error fetching batch for i_beneficiarydetails: {}", e.getMessage(), e); + return "Error fetching data for i_beneficiarydetails: " + e.getMessage(); + } + + if (totalProcessed > 0 || syncData.isEmpty()) { // syncData.isEmpty() means no records to process, still a "success" + logger.info("Finished processing i_beneficiarydetails. Total records processed: {}", totalProcessed); + return "data sync passed"; + } else { + logger.error("No records were processed for i_beneficiarydetails or an unknown error occurred."); + return "No data processed or sync failed for i_beneficiarydetails."; + } + } } + private String getQueryFor_I_BeneficiaryDetails(String schemaName, String tableName) { + StringBuilder queryBuilder = new StringBuilder(" UPDATE "); + queryBuilder.append(schemaName).append(".").append(tableName); + queryBuilder.append(" SET "); + queryBuilder.append("Processed = 'P', SyncedDate = now(), SyncedBy = ? "); + queryBuilder.append(" WHERE "); + queryBuilder.append("BeneficiaryDetailsId = ? "); + queryBuilder.append(" AND "); + queryBuilder.append("VanID = ? "); + return queryBuilder.toString(); + } + + + /** + * Handles the generic synchronization logic for tables not covered by specific handlers. + */ + private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDigester) { + logger.info("Performing generic sync for table: {}", syncUploadDataDigester.getTableName()); + List> dataToBesync = syncUploadDataDigester.getSyncData(); + List syncDataListInsert = new ArrayList<>(); + List syncDataListUpdate = new ArrayList<>(); + + if (dataToBesync == null || dataToBesync.isEmpty()) { + logger.info("No data to sync for table: {}", syncUploadDataDigester.getTableName()); + return true; // Nothing to sync, consider it a success + } + + String syncTableName = syncUploadDataDigester.getTableName(); + String vanAutoIncColumnName = syncUploadDataDigester.getVanAutoIncColumnName(); + String schemaName = syncUploadDataDigester.getSchemaName(); + Integer facilityIDFromDigester = syncUploadDataDigester.getFacilityID(); + + for (Map map : dataToBesync) { + String vanSerialNo = String.valueOf(map.get(vanAutoIncColumnName)); + String vanID = String.valueOf(map.get("VanID")); + int syncFacilityID = 0; + + // Update SyncedBy and SyncedDate in the map itself before processing + map.put("SyncedBy", syncUploadDataDigester.getSyncedBy()); + map.put("SyncedDate", String.valueOf(LocalDateTime.now())); // Ensure column name matches DB + + // Facility ID processing + if (facilityIDFromDigester != null) { + // Determine the 'Processed' status based on facility ID for specific tables + switch (syncTableName.toLowerCase()) { + case "t_indent": + case "t_indentorder": { + if (map.containsKey("FromFacilityID") && map.get("FromFacilityID") instanceof Double) { + Double fromFacilityID = (Double) map.get("FromFacilityID"); + if (fromFacilityID.intValue() == facilityIDFromDigester) { + map.put("Processed", "P"); + } + } + break; + } + case "t_indentissue": { + if (map.containsKey("ToFacilityID") && map.get("ToFacilityID") instanceof Double) { + Double toFacilityID = (Double) map.get("ToFacilityID"); + if (toFacilityID.intValue() == facilityIDFromDigester) { + map.put("Processed", "P"); + } + } + break; + } + case "t_stocktransfer": { + if (map.containsKey("TransferToFacilityID") && map.get("TransferToFacilityID") instanceof Double) { + Double transferToFacilityID = (Double) map.get("TransferToFacilityID"); + if (transferToFacilityID.intValue() == facilityIDFromDigester) { + map.put("Processed", "P"); + } + } + break; + } + case "t_itemstockentry": { + if (map.containsKey("FacilityID") && map.get("FacilityID") instanceof Double) { + Double mapFacilityID = (Double) map.get("FacilityID"); + if (mapFacilityID.intValue() == facilityIDFromDigester) { + map.put("Processed", "P"); + } + } + break; + } + default: + // No specific facility ID logic for other tables, maintain existing 'Processed' status or default + break; + } + } + + // Extract SyncFacilityID for checkRecordIsAlreadyPresentOrNot + if (map.containsKey("SyncFacilityID") && map.get("SyncFacilityID") instanceof Integer) { + syncFacilityID = (Integer) map.get("SyncFacilityID"); + } else if (map.containsKey("SyncFacilityID") && map.get("SyncFacilityID") instanceof Double) { + syncFacilityID = ((Double) map.get("SyncFacilityID")).intValue(); + } + + + int recordCheck; + try { + recordCheck = dataSyncRepositoryCentral.checkRecordIsAlreadyPresentOrNot( + schemaName, syncTableName, vanSerialNo, vanID, vanAutoIncColumnName, syncFacilityID); + } catch (Exception e) { + logger.error("Error checking record existence for table {}: VanSerialNo={}, VanID={}. Error: {}", syncTableName, vanSerialNo, vanID, e.getMessage(), e); + return false; // Critical error, stop sync for this table + } + + // Prepare Object array for insert/update + Object[] objArr; + List serverColumnsList = Arrays.asList(syncUploadDataDigester.getServerColumns().split(",")); + List currentRecordValues = new ArrayList<>(); + + for (String column : serverColumnsList) { + Object value = map.get(column.trim()); + // Handle boolean conversion if necessary, though String.valueOf should generally work for prepared statements + if (value instanceof Boolean) { + currentRecordValues.add(value); + } else if (value != null) { + currentRecordValues.add(String.valueOf(value)); + } else { + currentRecordValues.add(null); + } + } + + objArr = currentRecordValues.toArray(); + + if (recordCheck == 0) { + syncDataListInsert.add(objArr); + } else { + // For update, append the WHERE clause parameters at the end of the array + List updateParams = new ArrayList<>(Arrays.asList(objArr)); + updateParams.add(String.valueOf(vanSerialNo)); + + if (Arrays.asList("t_patientissue", "t_physicalstockentry", "t_stockadjustment", "t_saitemmapping", + "t_stocktransfer", "t_patientreturn", "t_facilityconsumption", "t_indent", + "t_indentorder", "t_indentissue", "t_itemstockentry", "t_itemstockexit") + .contains(syncTableName.toLowerCase()) && map.containsKey("SyncFacilityID")) { + updateParams.add(String.valueOf(map.get("SyncFacilityID"))); + } else { + updateParams.add(String.valueOf(vanID)); + } + syncDataListUpdate.add(updateParams.toArray()); + } + } + + boolean insertSuccess = true; + boolean updateSuccess = true; + + if (!syncDataListInsert.isEmpty()) { + String queryInsert = getQueryToInsertDataToServerDB(schemaName, syncTableName, syncUploadDataDigester.getServerColumns()); + try { + int[] i = dataSyncRepositoryCentral.syncDataToCentralDB(schemaName, syncTableName, syncUploadDataDigester.getServerColumns(), queryInsert, syncDataListInsert); + if (i.length != syncDataListInsert.size()) { + insertSuccess = false; + logger.error("Partial insert for table {}. Expected {} inserts, got {}. Failed records: {}", syncTableName, syncDataListInsert.size(), i.length, getFailedRecords(i, syncDataListInsert)); + } else { + logger.info("Successfully inserted {} records into table {}.", i.length, syncTableName); + } + } catch (Exception e) { + insertSuccess = false; + logger.error("Exception during insert for table {}: {}", syncTableName, e.getMessage(), e); + } + } + + if (!syncDataListUpdate.isEmpty()) { + String queryUpdate = getQueryToUpdateDataToServerDB(schemaName, syncUploadDataDigester.getServerColumns(), syncTableName); + try { + int[] j = dataSyncRepositoryCentral.syncDataToCentralDB(schemaName, syncTableName, SERVER_COLUMNS_NOT_REQUIRED, queryUpdate, syncDataListUpdate); + if (j.length != syncDataListUpdate.size()) { + updateSuccess = false; + logger.error("Partial update for table {}. Expected {} updates, got {}. Failed records: {}", syncTableName, syncDataListUpdate.size(), j.length, getFailedRecords(j, syncDataListUpdate)); + } else { + logger.info("Successfully updated {} records in table {}.", j.length, syncTableName); + } + } catch (Exception e) { + updateSuccess = false; + logger.error("Exception during update for table {}: {}", syncTableName, e.getMessage(), e); + } + } + return insertSuccess && updateSuccess; + } + + private String getQueryToInsertDataToServerDB(String schemaName, String tableName, String serverColumns) { + String[] columnsArr = null; + if (serverColumns != null) + columnsArr = serverColumns.split(","); + + StringBuilder preparedStatementSetter = new StringBuilder(); + + if (columnsArr != null && columnsArr.length > 0) { + for (int i = 0; i < columnsArr.length; i++) { + preparedStatementSetter.append("?"); + if (i < columnsArr.length - 1) { + preparedStatementSetter.append(", "); + } + } + } + + StringBuilder queryBuilder = new StringBuilder("INSERT INTO "); + queryBuilder.append(schemaName).append(".").append(tableName); + queryBuilder.append("("); + queryBuilder.append(serverColumns); + queryBuilder.append(") VALUES ("); + queryBuilder.append(preparedStatementSetter); + queryBuilder.append(")"); + return queryBuilder.toString(); + } + + public String getQueryToUpdateDataToServerDB(String schemaName, String serverColumns, String tableName) { + String[] columnsArr = null; + if (serverColumns != null) + columnsArr = serverColumns.split(","); + + StringBuilder preparedStatementSetter = new StringBuilder(); + + if (columnsArr != null && columnsArr.length > 0) { + for (int i = 0; i < columnsArr.length; i++) { + preparedStatementSetter.append(columnsArr[i].trim()); + preparedStatementSetter.append(" = ?"); + if (i < columnsArr.length - 1) { + preparedStatementSetter.append(", "); + } + } + } + + StringBuilder queryBuilder = new StringBuilder(" UPDATE "); + queryBuilder.append(schemaName).append(".").append(tableName); + queryBuilder.append(" SET "); + queryBuilder.append(preparedStatementSetter); + queryBuilder.append(" WHERE VanSerialNo = ? "); + + if (Arrays.asList("t_patientissue", "t_physicalstockentry", "t_stockadjustment", "t_saitemmapping", + "t_stocktransfer", "t_patientreturn", "t_facilityconsumption", "t_indent", + "t_indentorder", "t_indentissue", "t_itemstockentry", "t_itemstockexit") + .contains(tableName.toLowerCase())) { + queryBuilder.append(" AND SyncFacilityID = ? "); + } else { + queryBuilder.append(" AND VanID = ? "); + } + return queryBuilder.toString(); + } + + // Helper to get information about failed records (for logging purposes) + private String getFailedRecords(int[] results, List data) { + List failedRecordsInfo = new ArrayList<>(); + for (int k = 0; k < results.length; k++) { + // In Spring JDBC batchUpdate, a value of Statement.EXECUTE_FAILED or Statement.SUCCESS_NO_INFO + // usually indicates a failure or success without specific row count. + // A common return value for success is 1 (for one row updated/inserted). + if (results[k] < 1) { // Assuming 1 means success, and anything else (0, -2, etc.) means failure + // Attempt to get some identifiable info from the failed record + if (data.get(k).length > 0) { + failedRecordsInfo.add("Record at index " + k + " (VanSerialNo/ID: " + data.get(k)[data.get(k).length - 2] + ")"); + } else { + failedRecordsInfo.add("Record at index " + k + " (No identifiable info)"); + } + } + } + return String.join("; ", failedRecordsInfo); + } } \ No newline at end of file From f2134ddfdba927f8f889f3dbdf6090015ee4ba58 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 15 Jul 2025 20:48:48 +0530 Subject: [PATCH 07/18] fix: enable logger in pom.xml --- pom.xml | 14 ++++++++++++-- .../DataSyncRepositoryCentral.java | 18 ++++++++++++++++-- .../GetDataFromVanAndSyncToDBImpl.java | 17 +++++++++++++++-- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 70859837..8733a6ca 100644 --- a/pom.xml +++ b/pom.xml @@ -47,12 +47,22 @@ org.springframework.boot spring-boot-starter - + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-simple + ${slf4j.version} co.elastic.logging 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 f583b357..b602af76 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -68,20 +68,25 @@ public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, Object[] queryParams = params.toArray(); logger.debug("Checking record existence query: {} with params: {}", query, Arrays.toString(queryParams)); + System.out.println("Checking record existence query: " + query + " with params: " + Arrays.toString(queryParams)); try { List> resultSet = jdbcTemplate.queryForList(query, queryParams); if (resultSet != null && !resultSet.isEmpty()) { + System.out.println("Record found for table " + tableName + ": VanSerialNo=" + vanSerialNo + ", VanID=" + vanID); logger.debug("Record found for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); return 1; } else { + System.out.println("No record found for table " + tableName + ": VanSerialNo=" + vanSerialNo + ", VanID=" + vanID); logger.debug("No record found for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); return 0; } } catch (org.springframework.dao.EmptyResultDataAccessException e) { + System.out.println("No record found (EmptyResultDataAccessException) for table " + tableName + ": VanSerialNo=" + vanSerialNo + ", VanID=" + vanID); logger.debug("No record found (EmptyResultDataAccessException) for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); return 0; } catch (Exception e) { + System.out.println("Database error during checkRecordIsAlreadyPresentOrNot for table " + tableName + ": VanSerialNo=" + vanSerialNo + ", VanID=" + vanID); logger.error("Database error during checkRecordIsAlreadyPresentOrNot for table {}: VanSerialNo={}, VanID={}. Error: {}", tableName, vanSerialNo, vanID, e.getMessage(), e); throw new RuntimeException("Failed to check record existence: " + e.getMessage(), e); // Re-throw or handle as appropriate } @@ -93,14 +98,17 @@ public int[] syncDataToCentralDB(String schema, String tableName, String serverC jdbcTemplate = getJdbcTemplate(); logger.info("Executing batch operation for table: {}. Query type: {}. Number of records: {}", tableName, query.startsWith("INSERT") ? "INSERT" : "UPDATE", syncDataList.size()); logger.debug("Query: {}", query); - +System.out.println("Executing batch operation for table: " + tableName + ". Query type: " + (query.startsWith("INSERT") ? "INSERT" : "UPDATE") + ". Number of records: " + syncDataList.size()); try { // Start batch insert/update int[] i = jdbcTemplate.batchUpdate(query, syncDataList); + System.out.println("Batch operation completed for table " + tableName + ". Results: " + Arrays.toString(i)); logger.info("Batch operation completed for table {}. Results: {}", tableName, Arrays.toString(i)); return i; } catch (Exception e) { logger.error("Exception during batch update for table {}: {}", tableName, e.getMessage(), e); + System.out.println("Exception during batch update for table " + tableName + ": " + e.getMessage()); + // Log the error with detailed information // Re-throw the exception to be handled by the service layer, so specific errors can be captured. throw new RuntimeException("Batch sync failed for table " + tableName + ": " + e.getMessage(), e); } @@ -142,6 +150,9 @@ public List> getMasterDataFromTable(String schema, String ta logger.info("Select query central: {}", finalQuery); logger.info("Last Downloaded Date: {}", lastDownloadDate); logger.info("Query Params: {}", params); + System.out.println("Select query central: " + finalQuery); + System.out.println("Last Downloaded Date: " + lastDownloadDate); + System.out.println("Query Params: " + params); try { if (params.isEmpty()) { @@ -150,10 +161,11 @@ public List> getMasterDataFromTable(String schema, String ta resultSetList = jdbcTemplate.queryForList(finalQuery, params.toArray()); } } catch (Exception e) { + System.out.println("Error fetching master data from table " + table + ": " + e.getMessage()); logger.error("Error fetching master data from table {}: {}", table, e.getMessage(), e); throw new RuntimeException("Failed to fetch master data: " + e.getMessage(), e); } - +System.out.println("Result set Details size: " + resultSetList.size()); logger.info("Result set Details size: {}", resultSetList.size()); return resultSetList; } @@ -162,11 +174,13 @@ public List> getBatchForBenDetails(String schema, String tab String whereClause, int limit, int offset) { jdbcTemplate = getJdbcTemplate(); String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; + System.out.println("Fetching batch for beneficiary details. Query: " + query + ", Limit: " + limit + ", Offset: " + offset); logger.debug("Fetching batch for beneficiary details. Query: {}, Limit: {}, Offset: {}", query, limit, offset); try { return jdbcTemplate.queryForList(query, limit, offset); } catch (Exception e) { logger.error("Error fetching batch for beneficiary details from table {}: {}", table, e.getMessage(), e); + System.out.println("Error fetching batch for beneficiary details from table " + table + ": " + e.getMessage()); throw new RuntimeException("Failed to fetch batch data: " + e.getMessage(), e); } } 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 f2107d96..33d5d75b 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -44,11 +44,12 @@ public class GetDataFromVanAndSyncToDBImpl implements GetDataFromVanAndSyncToDB public String syncDataToServer(String requestOBJ, String Authorization, String token) throws Exception { logger.info("Starting syncDataToServer. Token: {}", token); - +System.out.println("Starting syncDataToServer. Token: " + token); ObjectMapper mapper = new ObjectMapper(); SyncUploadDataDigester syncUploadDataDigester = mapper.readValue(requestOBJ, SyncUploadDataDigester.class); if (syncUploadDataDigester == null || syncUploadDataDigester.getTableName() == null) { + System.out.println("Invalid SyncUploadDataDigester object or tableName is null."); logger.error("Invalid SyncUploadDataDigester object or tableName is null."); return "Error: Invalid sync request."; } @@ -59,16 +60,21 @@ public String syncDataToServer(String requestOBJ, String Authorization, String t if ("m_beneficiaryregidmapping".equalsIgnoreCase(syncTableName)) { String result = update_M_BeneficiaryRegIdMapping_for_provisioned_benID(syncUploadDataDigester); if ("data sync passed".equals(result)) { + System.out.println("Sync successful for m_beneficiaryregidmapping."); return "Sync successful for m_beneficiaryregidmapping."; } else { + System.out.println("Sync failed for m_beneficiaryregidmapping: " + result); logger.error("Sync failed for m_beneficiaryregidmapping: {}", result); return "Sync failed for m_beneficiaryregidmapping."; } - } else if ("i_beneficiarydetails".equalsIgnoreCase(syncTableName)) { + } + if ("i_beneficiarydetails".equalsIgnoreCase(syncTableName)) { String result = update_I_BeneficiaryDetails_for_processed_in_batches(syncUploadDataDigester); if ("data sync passed".equals(result)) { + System.out.println("Sync successful for i_beneficiarydetails."); return "Sync successful for i_beneficiarydetails."; } else { + System.out.println("Sync failed for i_beneficiarydetails: " + result); logger.error("Sync failed for i_beneficiarydetails: {}", result); return "Sync failed for i_beneficiarydetails."; } @@ -83,6 +89,7 @@ public String syncDataToServer(String requestOBJ, String Authorization, String t boolean foundInGroup = false; for (Map.Entry> entry : TABLE_GROUPS.entrySet()) { if (entry.getValue().contains(syncTableName.toLowerCase())) { + System.out.println("Attempting sync for table '" + syncTableName + "' in Group " + entry.getKey()); logger.info("Attempting to sync table '{}' from Group {}", syncTableName, entry.getKey()); syncSuccess = syncTablesInGroup(syncUploadDataDigester.getSchemaName(), syncTableName, syncUploadDataDigester); foundInGroup = true; @@ -90,16 +97,19 @@ public String syncDataToServer(String requestOBJ, String Authorization, String t } } if (!foundInGroup) { + System.out.println("Table '" + syncTableName + "' not found in any predefined groups. Proceeding with generic sync logic."); logger.warn("Table '{}' not found in any predefined groups. Proceeding with generic sync logic.", syncTableName); syncSuccess = performGenericTableSync(syncUploadDataDigester); } } else { + System.out.println("No specific table provided in the request. Attempting to sync all tables group by group."); // If no specific table is in the request (e.g., a general sync trigger), iterate through groups logger.info("No specific table provided. Attempting to sync all tables group by group."); for (Map.Entry> entry : TABLE_GROUPS.entrySet()) { Integer groupId = entry.getKey(); List tablesInGroup = entry.getValue(); logger.info("Starting sync for Group {}", groupId); + System.out.println("Starting sync for Group " + groupId); for (String table : tablesInGroup) { try { // Create a new digester for each table within the group, @@ -114,15 +124,18 @@ public String syncDataToServer(String requestOBJ, String Authorization, String t if (!currentTableSyncResult) { syncSuccess = false; errorMessage += "Failed to sync table: " + table + " in Group " + groupId + ". "; + System.out.println("Sync failed for table '" + table + "' in Group " + groupId); logger.error("Sync failed for table '{}' in Group {}. Error: {}", table, groupId, errorMessage); // Optionally, you can choose to break here or continue to sync other tables in the group/next group // For now, let's continue to attempt other tables within the group. } else { + System.out.println("Successfully synced table '" + table + "' in Group " + groupId); logger.info("Successfully synced table: {} in Group {}", table, groupId); } } catch (Exception e) { syncSuccess = false; errorMessage += "Exception during sync for table: " + table + " in Group " + groupId + ": " + e.getMessage() + ". "; + System.out.println("Exception during sync for table '" + table + "' in Group " + groupId + ": " + e.getMessage()); logger.error("Exception during sync for table '{}' in Group {}: {}", table, groupId, e.getMessage(), e); // Continue to attempt other tables } From 77fec704ba943a65255c06d5c2c8c510b5e832ed Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 29 Jul 2025 12:50:03 +0530 Subject: [PATCH 08/18] fix: coderabbit comments --- .../DataSyncRepositoryCentral.java | 45 +- .../GetDataFromVanAndSyncToDBImpl.java | 418 +++++++++++------- .../com/iemr/mmu/utils/RestTemplateUtil.java | 16 - 3 files changed, 278 insertions(+), 201 deletions(-) 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 b602af76..70e946bf 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -8,7 +8,6 @@ import javax.sql.DataSource; import java.sql.Timestamp; -import java.sql.Statement; // Import Statement for batchUpdate result interpretation import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -38,6 +37,12 @@ public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, List params = new ArrayList<>(); + if (!isValidDatabaseIdentifier(schemaName) || !isValidDatabaseIdentifier(tableName) || !isValidDatabaseIdentifier(vanAutoIncColumnName)) { + logger.error("Invalid database identifier detected: schemaName={}, tableName={}, vanAutoIncColumnName={}", schemaName, tableName, vanAutoIncColumnName); + throw new IllegalArgumentException("Invalid database identifier provided."); + } + + StringBuilder queryBuilder = new StringBuilder("SELECT "); queryBuilder.append(vanAutoIncColumnName); queryBuilder.append(" FROM "); @@ -92,15 +97,18 @@ public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, } } + // Helper method to validate database identifiers + private boolean isValidDatabaseIdentifier(String identifier) { + return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); + } + // Method for synchronization of data to central DB public int[] syncDataToCentralDB(String schema, String tableName, String serverColumns, String query, List syncDataList) { jdbcTemplate = getJdbcTemplate(); logger.info("Executing batch operation for table: {}. Query type: {}. Number of records: {}", tableName, query.startsWith("INSERT") ? "INSERT" : "UPDATE", syncDataList.size()); logger.debug("Query: {}", query); -System.out.println("Executing batch operation for table: " + tableName + ". Query type: " + (query.startsWith("INSERT") ? "INSERT" : "UPDATE") + ". Number of records: " + syncDataList.size()); try { - // Start batch insert/update int[] i = jdbcTemplate.batchUpdate(query, syncDataList); System.out.println("Batch operation completed for table " + tableName + ". Results: " + Arrays.toString(i)); logger.info("Batch operation completed for table {}. Results: {}", tableName, Arrays.toString(i)); @@ -108,8 +116,6 @@ public int[] syncDataToCentralDB(String schema, String tableName, String serverC } catch (Exception e) { logger.error("Exception during batch update for table {}: {}", tableName, e.getMessage(), e); System.out.println("Exception during batch update for table " + tableName + ": " + e.getMessage()); - // Log the error with detailed information - // Re-throw the exception to be handled by the service layer, so specific errors can be captured. throw new RuntimeException("Batch sync failed for table " + tableName + ": " + e.getMessage(), e); } } @@ -120,9 +126,18 @@ public List> getMasterDataFromTable(String schema, String ta String masterType, Timestamp lastDownloadDate, Integer vanID, Integer psmID) throws Exception { jdbcTemplate = getJdbcTemplate(); List> resultSetList = new ArrayList<>(); - StringBuilder baseQueryBuilder = new StringBuilder(" SELECT ").append(columnNames).append(" FROM ").append(schema).append(".").append(table); List params = new ArrayList<>(); + if (!isValidDatabaseIdentifier(schema) || !isValidDatabaseIdentifier(table)) { + logger.error("Invalid database identifier detected in getMasterDataFromTable: schema={}, table={}", schema, table); + throw new IllegalArgumentException("Invalid database identifier provided."); + } + + StringBuilder baseQueryBuilder = new StringBuilder(" SELECT "); + baseQueryBuilder.append(columnNames); + baseQueryBuilder.append(" FROM "); + baseQueryBuilder.append(schema).append(".").append(table); + if (masterType != null) { if (lastDownloadDate != null) { baseQueryBuilder.append(" WHERE LastModDate >= ? "); @@ -147,13 +162,6 @@ public List> getMasterDataFromTable(String schema, String ta } String finalQuery = baseQueryBuilder.toString(); - logger.info("Select query central: {}", finalQuery); - logger.info("Last Downloaded Date: {}", lastDownloadDate); - logger.info("Query Params: {}", params); - System.out.println("Select query central: " + finalQuery); - System.out.println("Last Downloaded Date: " + lastDownloadDate); - System.out.println("Query Params: " + params); - try { if (params.isEmpty()) { resultSetList = jdbcTemplate.queryForList(finalQuery); @@ -161,11 +169,9 @@ public List> getMasterDataFromTable(String schema, String ta resultSetList = jdbcTemplate.queryForList(finalQuery, params.toArray()); } } catch (Exception e) { - System.out.println("Error fetching master data from table " + table + ": " + e.getMessage()); logger.error("Error fetching master data from table {}: {}", table, e.getMessage(), e); throw new RuntimeException("Failed to fetch master data: " + e.getMessage(), e); } -System.out.println("Result set Details size: " + resultSetList.size()); logger.info("Result set Details size: {}", resultSetList.size()); return resultSetList; } @@ -173,17 +179,20 @@ public List> getMasterDataFromTable(String schema, String ta public List> getBatchForBenDetails(String schema, String table, String columnNames, String whereClause, int limit, int offset) { jdbcTemplate = getJdbcTemplate(); + + if (!isValidDatabaseIdentifier(schema) || !isValidDatabaseIdentifier(table)) { + logger.error("Invalid database identifier detected in getBatchForBenDetails: schema={}, table={}", schema, table); + throw new IllegalArgumentException("Invalid database identifier provided."); + } + String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; - System.out.println("Fetching batch for beneficiary details. Query: " + query + ", Limit: " + limit + ", Offset: " + offset); logger.debug("Fetching batch for beneficiary details. Query: {}, Limit: {}, Offset: {}", query, limit, offset); try { return jdbcTemplate.queryForList(query, limit, offset); } catch (Exception e) { logger.error("Error fetching batch for beneficiary details from table {}: {}", table, e.getMessage(), e); - System.out.println("Error fetching batch for beneficiary details from table " + table + ": " + e.getMessage()); throw new RuntimeException("Failed to fetch batch data: " + e.getMessage(), e); } } - // End of Data Download Repository } \ No newline at end of file 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 33d5d75b..fce0935c 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -6,6 +6,8 @@ import java.util.List; import java.util.Map; import java.util.HashMap; +import java.util.Set; +import java.util.HashSet; import org.slf4j.Logger; @@ -27,43 +29,66 @@ public class GetDataFromVanAndSyncToDBImpl implements GetDataFromVanAndSyncToDB private DataSyncRepositoryCentral dataSyncRepositoryCentral; private static final Map> TABLE_GROUPS = new HashMap<>(); + private static final Set VALID_SCHEMAS = new HashSet<>(Arrays.asList("public", "db_iemr_mmu_sync")); // Add your actual schema names + private static final Set VALID_TABLES = new HashSet<>(Arrays.asList( + "m_beneficiaryregidmapping", "i_beneficiaryaccount","i_beneficiaryaddress","i_beneficiarycontacts","i_beneficiarydetails","i_beneficiaryfamilymapping","i_beneficiaryidentity","i_beneficiarymapping", + "t_benvisitdetail","t_phy_anthropometry","t_phy_vitals","t_benadherence","t_anccare","t_pnccare","t_ncdscreening","t_ncdcare","i_ben_flow_outreach","t_covid19","t_idrsdetails","t_physicalactivity", + "t_phy_generalexam","t_phy_headtotoe","t_sys_obstetric","t_sys_gastrointestinal","t_sys_cardiovascular","t_sys_respiratory","t_sys_centralnervous","t_sys_musculoskeletalsystem","t_sys_genitourinarysystem", + "t_ancdiagnosis","t_ncddiagnosis","t_pncdiagnosis","t_benchefcomplaint","t_benclinicalobservation","t_prescription","t_prescribeddrug","t_lab_testorder","t_benreferdetails", + "t_lab_testresult","t_physicalstockentry","t_patientissue","t_facilityconsumption","t_itemstockentry","t_itemstockexit", + "t_benmedhistory","t_femaleobstetrichistory","t_benmenstrualdetails","t_benpersonalhabit","t_childvaccinedetail1","t_childvaccinedetail2","t_childoptionalvaccinedetail","t_ancwomenvaccinedetail","t_childfeedinghistory","t_benallergyhistory","t_bencomorbiditycondition","t_benmedicationhistory","t_benfamilyhistory","t_perinatalhistory","t_developmenthistory", + "t_cancerfamilyhistory","t_cancerpersonalhistory","t_cancerdiethistory","t_cancerobstetrichistory","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" + )); + static { - // Group 1: Master data or less frequently changing data - TABLE_GROUPS.put(1, Arrays.asList("m_beneficiaryregidmapping", "m_another_master_table")); - - // Group 2: Transactional data that might involve facility ID - TABLE_GROUPS.put(2, Arrays.asList("t_indent", "t_indentorder", "t_indentissue", "t_stocktransfer", "t_itemstockentry")); - - // Group 3: High volume transactional data - TABLE_GROUPS.put(3, Arrays.asList("i_beneficiarydetails", "t_patientissue", "t_physicalstockentry", - "t_stockadjustment", "t_saitemmapping", "t_patientreturn", - "t_facilityconsumption", "t_itemstockexit")); - // Add more groups as needed, up to 9 - // TABLE_GROUPS.put(4, Arrays.asList("table_in_group_4a", "table_in_group_4b")); + + TABLE_GROUPS.put(1, Arrays.asList("m_beneficiaryregidmapping", "i_beneficiaryaccount","i_beneficiaryaddress","i_beneficiarycontacts","i_beneficiarydetails","i_beneficiaryfamilymapping","i_beneficiaryidentity","i_beneficiarymapping")); + + TABLE_GROUPS.put(2, Arrays.asList("t_benvisitdetail","t_phy_anthropometry","t_phy_vitals","t_benadherence","t_anccare","t_pnccare","t_ncdscreening","t_ncdcare","i_ben_flow_outreach","t_covid19","t_idrsdetails","t_physicalactivity")); + + TABLE_GROUPS.put(3, Arrays.asList("t_phy_generalexam","t_phy_headtotoe","t_sys_obstetric","t_sys_gastrointestinal","t_sys_cardiovascular","t_sys_respiratory","t_sys_centralnervous","t_sys_musculoskeletalsystem","t_sys_genitourinarysystem")); + + TABLE_GROUPS.put(4, Arrays.asList("t_ancdiagnosis","t_ncddiagnosis","t_pncdiagnosis","t_benchefcomplaint","t_benclinicalobservation","t_prescription","t_prescribeddrug","t_lab_testorder","t_benreferdetails")); + + TABLE_GROUPS.put(5, Arrays.asList("t_lab_testresult","t_physicalstockentry","t_patientissue","t_facilityconsumption","t_itemstockentry","t_itemstockexit")); + + TABLE_GROUPS.put(6, Arrays.asList("t_benmedhistory","t_femaleobstetrichistory","t_benmenstrualdetails","t_benpersonalhabit","t_childvaccinedetail1","t_childvaccinedetail2","t_childoptionalvaccinedetail","t_ancwomenvaccinedetail","t_childfeedinghistory","t_benallergyhistory","t_bencomorbiditycondition","t_benmedicationhistory","t_benfamilyhistory","t_perinatalhistory","t_developmenthistory")); + + TABLE_GROUPS.put(7, Arrays.asList("t_cancerfamilyhistory","t_cancerpersonalhistory","t_cancerdiethistory","t_cancerobstetrichistory","t_cancervitals","t_cancersignandsymptoms","t_cancerlymphnode","t_canceroralexamination","t_cancerbreastexamination","t_cancerabdominalexamination","t_cancergynecologicalexamination","t_cancerdiagnosis","t_cancerimageannotation")); + + TABLE_GROUPS.put(8, Arrays.asList("i_beneficiaryimage")); + + TABLE_GROUPS.put(9, Arrays.asList("t_itemstockentry","t_itemstockexit","t_patientissue","t_physicalstockentry","t_stockadjustment","t_stocktransfer","t_patientreturn","t_facilityconsumption","t_indent","t_indentissue","t_indentorder","t_saitemmapping")); + } public String syncDataToServer(String requestOBJ, String Authorization, String token) throws Exception { logger.info("Starting syncDataToServer. Token: {}", token); -System.out.println("Starting syncDataToServer. Token: " + token); ObjectMapper mapper = new ObjectMapper(); SyncUploadDataDigester syncUploadDataDigester = mapper.readValue(requestOBJ, SyncUploadDataDigester.class); if (syncUploadDataDigester == null || syncUploadDataDigester.getTableName() == null) { - System.out.println("Invalid SyncUploadDataDigester object or tableName is null."); logger.error("Invalid SyncUploadDataDigester object or tableName is null."); return "Error: Invalid sync request."; } String syncTableName = syncUploadDataDigester.getTableName(); + String schemaName = syncUploadDataDigester.getSchemaName(); + + if (!isValidSchemaName(schemaName) || !isValidTableName(syncTableName)) { + logger.error("Invalid schema or table name provided: Schema='{}', Table='{}'.", schemaName, syncTableName); + return "Error: Invalid schema or table name."; + } + // Handle specific tables first, if their logic is distinct if ("m_beneficiaryregidmapping".equalsIgnoreCase(syncTableName)) { String result = update_M_BeneficiaryRegIdMapping_for_provisioned_benID(syncUploadDataDigester); if ("data sync passed".equals(result)) { - System.out.println("Sync successful for m_beneficiaryregidmapping."); return "Sync successful for m_beneficiaryregidmapping."; } else { - System.out.println("Sync failed for m_beneficiaryregidmapping: " + result); logger.error("Sync failed for m_beneficiaryregidmapping: {}", result); return "Sync failed for m_beneficiaryregidmapping."; } @@ -71,10 +96,8 @@ public String syncDataToServer(String requestOBJ, String Authorization, String t if ("i_beneficiarydetails".equalsIgnoreCase(syncTableName)) { String result = update_I_BeneficiaryDetails_for_processed_in_batches(syncUploadDataDigester); if ("data sync passed".equals(result)) { - System.out.println("Sync successful for i_beneficiarydetails."); return "Sync successful for i_beneficiarydetails."; } else { - System.out.println("Sync failed for i_beneficiarydetails: " + result); logger.error("Sync failed for i_beneficiarydetails: {}", result); return "Sync failed for i_beneficiarydetails."; } @@ -89,7 +112,6 @@ public String syncDataToServer(String requestOBJ, String Authorization, String t boolean foundInGroup = false; for (Map.Entry> entry : TABLE_GROUPS.entrySet()) { if (entry.getValue().contains(syncTableName.toLowerCase())) { - System.out.println("Attempting sync for table '" + syncTableName + "' in Group " + entry.getKey()); logger.info("Attempting to sync table '{}' from Group {}", syncTableName, entry.getKey()); syncSuccess = syncTablesInGroup(syncUploadDataDigester.getSchemaName(), syncTableName, syncUploadDataDigester); foundInGroup = true; @@ -97,74 +119,63 @@ public String syncDataToServer(String requestOBJ, String Authorization, String t } } if (!foundInGroup) { - System.out.println("Table '" + syncTableName + "' not found in any predefined groups. Proceeding with generic sync logic."); logger.warn("Table '{}' not found in any predefined groups. Proceeding with generic sync logic.", syncTableName); syncSuccess = performGenericTableSync(syncUploadDataDigester); } } else { - System.out.println("No specific table provided in the request. Attempting to sync all tables group by group."); // If no specific table is in the request (e.g., a general sync trigger), iterate through groups logger.info("No specific table provided. Attempting to sync all tables group by group."); for (Map.Entry> entry : TABLE_GROUPS.entrySet()) { Integer groupId = entry.getKey(); List tablesInGroup = entry.getValue(); logger.info("Starting sync for Group {}", groupId); - System.out.println("Starting sync for Group " + groupId); for (String table : tablesInGroup) { + if (!isValidTableName(table)) { + logger.error("Invalid table name '{}' encountered in group {}. Skipping.", table, groupId); + syncSuccess = false; + errorMessage += "Invalid table name: " + table + " in Group " + groupId + ". "; + continue; // Skip this table + } + try { - // Create a new digester for each table within the group, - // or adapt if the original digester contains data for multiple tables. - // For simplicity, assuming syncDataDigester needs to be tailored per table or group. - // If your requestOBJ contains data for only one table at a time, this loop might need adjustment - // to fetch data for each table in the group. - // For now, it will use the syncData from the original requestOBJ, which implies - // the original requestOBJ should represent data for a single table. - // A more robust solution would involve fetching data for each table dynamically. + boolean currentTableSyncResult = syncTablesInGroup(syncUploadDataDigester.getSchemaName(), table, syncUploadDataDigester); if (!currentTableSyncResult) { syncSuccess = false; errorMessage += "Failed to sync table: " + table + " in Group " + groupId + ". "; - System.out.println("Sync failed for table '" + table + "' in Group " + groupId); logger.error("Sync failed for table '{}' in Group {}. Error: {}", table, groupId, errorMessage); - // Optionally, you can choose to break here or continue to sync other tables in the group/next group - // For now, let's continue to attempt other tables within the group. } else { - System.out.println("Successfully synced table '" + table + "' in Group " + groupId); logger.info("Successfully synced table: {} in Group {}", table, groupId); } } catch (Exception e) { syncSuccess = false; errorMessage += "Exception during sync for table: " + table + " in Group " + groupId + ": " + e.getMessage() + ". "; - System.out.println("Exception during sync for table '" + table + "' in Group " + groupId + ": " + e.getMessage()); logger.error("Exception during sync for table '{}' in Group {}: {}", table, groupId, e.getMessage(), e); - // Continue to attempt other tables } } } } if (syncSuccess) { + logger.info("Overall data sync passed."); return "Overall data sync passed."; } else { + logger.info("Overall data sync failed. Details: " + errorMessage); return "Overall data sync failed. Details: " + errorMessage; } } } - /** - * Helper method to sync tables belonging to a specific group. - * This method assumes that the `syncUploadDataDigester` will be populated - * with relevant data for the `currentTableName` before calling this. - * In a real-world scenario, you might fetch data for each table here. - */ + private boolean syncTablesInGroup(String schemaName, String currentTableName, SyncUploadDataDigester originalDigester) { logger.info("Attempting generic sync for table: {}", currentTableName); - // This is a simplification. In a production system, you would likely need - // to retrieve the actual data for 'currentTableName' from the local DB - // based on the group sync approach. For this example, we'll assume the - // originalDigester's syncData is relevant or needs to be re-populated. + + // Validate schemaName and currentTableName for safety before proceeding + if (!isValidSchemaName(schemaName) || !isValidTableName(currentTableName)) { + logger.error("Invalid schema or table name for group sync: Schema='{}', Table='{}'.", schemaName, currentTableName); + return false; // Fail fast if identifiers are invalid + } - // Create a new digester instance or modify the existing one for the current table SyncUploadDataDigester tableSpecificDigester = new SyncUploadDataDigester(); tableSpecificDigester.setSchemaName(schemaName); tableSpecificDigester.setTableName(currentTableName); @@ -173,12 +184,7 @@ private boolean syncTablesInGroup(String schemaName, String currentTableName, Sy tableSpecificDigester.setVanAutoIncColumnName(originalDigester.getVanAutoIncColumnName()); tableSpecificDigester.setServerColumns(originalDigester.getServerColumns()); // Assuming serverColumns is generic or set per table - // !!! IMPORTANT: You'll need to fetch the data for 'currentTableName' from your local DB here. - // The `originalDigester.getSyncData()` might not be correct for all tables in a group. - // For demonstration, I'm just using the original digester's data, which is likely incorrect - // if you're syncing multiple tables from a single request. - // You'll need a method like: dataSyncRepositoryLocal.getDataForTable(currentTableName, ...) - tableSpecificDigester.setSyncData(originalDigester.getSyncData()); // Placeholder: Replace with actual data fetching + tableSpecificDigester.setSyncData(originalDigester.getSyncData()); // Placeholder: Replace with actual data fetching return performGenericTableSync(tableSpecificDigester); } @@ -186,11 +192,19 @@ private boolean syncTablesInGroup(String schemaName, String currentTableName, Sy private String update_M_BeneficiaryRegIdMapping_for_provisioned_benID(SyncUploadDataDigester syncUploadDataDigester) { logger.info("Processing update_M_BeneficiaryRegIdMapping_for_provisioned_benID for table: {}", syncUploadDataDigester.getTableName()); + + String schemaName = syncUploadDataDigester.getSchemaName(); + String tableName = syncUploadDataDigester.getTableName(); + + if (!isValidSchemaName(schemaName) || !isValidTableName(tableName)) { + logger.error("Invalid schema or table name provided for m_beneficiaryregidmapping update: Schema='{}', Table='{}'.", schemaName, tableName); + return "Error: Invalid schema or table name."; + } + List> dataToBesync = syncUploadDataDigester.getSyncData(); List syncData = new ArrayList<>(); - String query = getqueryFor_M_BeneficiaryRegIdMapping(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName()); + String query = String.format("UPDATE %s.%s SET Provisioned = true, SyncedDate = now(), SyncedBy = ? WHERE BenRegId = ? AND BeneficiaryID = ? AND VanID = ?", schemaName, tableName); for (Map map : dataToBesync) { if (map.get("BenRegId") != null && map.get("BeneficiaryID") != null && map.get("VanID") != null) { @@ -207,8 +221,8 @@ private String update_M_BeneficiaryRegIdMapping_for_provisioned_benID(SyncUpload if (!syncData.isEmpty()) { try { - int[] i = dataSyncRepositoryCentral.syncDataToCentralDB(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName(), SERVER_COLUMNS_NOT_REQUIRED, query, syncData); + int[] i = dataSyncRepositoryCentral.syncDataToCentralDB(schemaName, + tableName, SERVER_COLUMNS_NOT_REQUIRED, query, syncData); if (i.length == syncData.size()) { logger.info("Successfully updated {} records for m_beneficiaryregidmapping.", i.length); @@ -227,78 +241,127 @@ private String update_M_BeneficiaryRegIdMapping_for_provisioned_benID(SyncUpload } } - private String getqueryFor_M_BeneficiaryRegIdMapping(String schemaName, String tableName) { - StringBuilder queryBuilder = new StringBuilder(" UPDATE "); - queryBuilder.append(schemaName).append(".").append(tableName); - queryBuilder.append(" SET "); - queryBuilder.append("Provisioned = true, SyncedDate = now(), syncedBy = ?"); - queryBuilder.append(" WHERE "); - queryBuilder.append(" BenRegId = ? "); - queryBuilder.append(" AND "); - queryBuilder.append(" BeneficiaryID = ? "); - queryBuilder.append(" AND "); - queryBuilder.append(" VanID = ? "); - return queryBuilder.toString(); - } - + public String update_I_BeneficiaryDetails_for_processed_in_batches(SyncUploadDataDigester syncUploadDataDigester) { logger.info("Processing update_I_BeneficiaryDetails_for_processed_in_batches for table: {}", syncUploadDataDigester.getTableName()); - List syncData = new ArrayList<>(); - - String query = getQueryFor_I_BeneficiaryDetails(syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName()); - - int limit = 1000; - int offset = 0; - int totalProcessed = 0; - - String problematicWhereClause = " WHERE Processed <> 'P' AND VanID IS NOT NULL "; // Define it explicitly - - while (true) { - List> batch; - try { - // *** ADD THIS LINE *** - logger.info("DEBUG: Passing whereClause to getBatchForBenDetails: [{}]", problematicWhereClause); - - batch = dataSyncRepositoryCentral.getBatchForBenDetails( - syncUploadDataDigester.getSchemaName(), - syncUploadDataDigester.getTableName(), - syncUploadDataDigester.getServerColumns(), - problematicWhereClause, // Use the variable - limit, - offset); - } catch (Exception e) { - logger.error("Error fetching batch for i_beneficiarydetails: {}", e.getMessage(), e); - return "Error fetching data for i_beneficiarydetails: " + e.getMessage(); + String schemaName = syncUploadDataDigester.getSchemaName(); + String tableName = syncUploadDataDigester.getTableName(); + + if (!isValidSchemaName(schemaName) || !isValidTableName(tableName)) { + logger.error("Invalid schema or table name provided for i_beneficiarydetails update: Schema='{}', Table='{}'.", schemaName, tableName); + return "Error: Invalid schema or table name."; } - - if (totalProcessed > 0 || syncData.isEmpty()) { // syncData.isEmpty() means no records to process, still a "success" + + List syncData = new ArrayList<>(); // This list will hold data for batch updates to 'Processed' + + String updateQuery = getQueryFor_I_BeneficiaryDetails(schemaName, tableName); + + int limit = 1000; + int offset = 0; + int totalProcessed = 0; + + String whereClauseForBatchFetch = " WHERE Processed <> 'P' AND VanID IS NOT NULL "; // This is for fetching, not for update + + while (true) { + List> batchToFetch; + try { + batchToFetch = dataSyncRepositoryCentral.getBatchForBenDetails( + schemaName, + tableName, + syncUploadDataDigester.getServerColumns(), + whereClauseForBatchFetch, + limit, + offset); + } catch (Exception e) { + logger.error("Error fetching batch for i_beneficiarydetails: {}", e.getMessage(), e); + return "Error fetching data for i_beneficiarydetails: " + e.getMessage(); + } + + if (batchToFetch.isEmpty()) { + break; + } + + for (Map map : batchToFetch) { + if (map.get("BeneficiaryDetailsId") != null && map.get("VanID") != null) { + Object[] params = new Object[3]; + params[0] = syncUploadDataDigester.getSyncedBy(); + params[1] = String.valueOf(map.get("BeneficiaryDetailsId")); + params[2] = String.valueOf(map.get("VanID")); + syncData.add(params); + } else { + logger.warn("Skipping record in i_beneficiarydetails due to missing BeneficiaryDetailsId or VanID: {}", map); + } + } + + if (!syncData.isEmpty()) { + try { + int[] batchUpdateResults = dataSyncRepositoryCentral.syncDataToCentralDB( + schemaName, + tableName, + SERVER_COLUMNS_NOT_REQUIRED, + updateQuery, + syncData); + + int successfulUpdates = 0; + for (int result : batchUpdateResults) { + if (result >= 1) { + successfulUpdates++; + } + } + totalProcessed += successfulUpdates; + logger.info("Batch update for i_beneficiarydetails: {} records processed, {} successfully updated.", syncData.size(), successfulUpdates); + + syncData.clear(); + offset += limit; + + } catch (Exception e) { + logger.error("Exception during batch update for i_beneficiarydetails: {}", e.getMessage(), e); + return "Error during sync for i_beneficiarydetails: " + e.getMessage(); + } + } else { + logger.info("No valid records in the current batch for i_beneficiarydetails to update."); + offset += limit; + } + } + + if (totalProcessed > 0) { logger.info("Finished processing i_beneficiarydetails. Total records processed: {}", totalProcessed); return "data sync passed"; } else { - logger.error("No records were processed for i_beneficiarydetails or an unknown error occurred."); - return "No data processed or sync failed for i_beneficiarydetails."; + logger.info("No records were processed for i_beneficiarydetails."); + return "No data processed for i_beneficiarydetails."; } } - } + private String getQueryFor_I_BeneficiaryDetails(String schemaName, String tableName) { - StringBuilder queryBuilder = new StringBuilder(" UPDATE "); - queryBuilder.append(schemaName).append(".").append(tableName); - queryBuilder.append(" SET "); - queryBuilder.append("Processed = 'P', SyncedDate = now(), SyncedBy = ? "); - queryBuilder.append(" WHERE "); - queryBuilder.append("BeneficiaryDetailsId = ? "); - queryBuilder.append(" AND "); - queryBuilder.append("VanID = ? "); - return queryBuilder.toString(); + if (!isValidSchemaName(schemaName) || !isValidTableName(tableName)) { + logger.error("Invalid schema or table name for getQueryFor_I_BeneficiaryDetails: Schema='{}', Table='{}'.", schemaName, tableName); + throw new IllegalArgumentException("Invalid schema or table name provided."); + } + return String.format("UPDATE %s.%s SET Processed = 'P', SyncedDate = now(), SyncedBy = ? WHERE BeneficiaryDetailsId = ? AND VanID = ?", schemaName, tableName); } - /** - * Handles the generic synchronization logic for tables not covered by specific handlers. - */ + private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDigester) { logger.info("Performing generic sync for table: {}", syncUploadDataDigester.getTableName()); + + String schemaName = syncUploadDataDigester.getSchemaName(); + String syncTableName = syncUploadDataDigester.getTableName(); + String vanAutoIncColumnName = syncUploadDataDigester.getVanAutoIncColumnName(); + String serverColumns = syncUploadDataDigester.getServerColumns(); + + if (!isValidSchemaName(schemaName) || !isValidTableName(syncTableName)) { + logger.error("Invalid schema or table name for generic sync: Schema='{}', Table='{}'.", schemaName, syncTableName); + return false; + } + + if (!isValidColumnNames(serverColumns)) { + logger.error("Invalid server columns provided for generic sync: {}", serverColumns); + return false; + } + + List> dataToBesync = syncUploadDataDigester.getSyncData(); List syncDataListInsert = new ArrayList<>(); List syncDataListUpdate = new ArrayList<>(); @@ -308,9 +371,6 @@ private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDig return true; // Nothing to sync, consider it a success } - String syncTableName = syncUploadDataDigester.getTableName(); - String vanAutoIncColumnName = syncUploadDataDigester.getVanAutoIncColumnName(); - String schemaName = syncUploadDataDigester.getSchemaName(); Integer facilityIDFromDigester = syncUploadDataDigester.getFacilityID(); for (Map map : dataToBesync) { @@ -318,13 +378,10 @@ private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDig String vanID = String.valueOf(map.get("VanID")); int syncFacilityID = 0; - // Update SyncedBy and SyncedDate in the map itself before processing map.put("SyncedBy", syncUploadDataDigester.getSyncedBy()); map.put("SyncedDate", String.valueOf(LocalDateTime.now())); // Ensure column name matches DB - // Facility ID processing if (facilityIDFromDigester != null) { - // Determine the 'Processed' status based on facility ID for specific tables switch (syncTableName.toLowerCase()) { case "t_indent": case "t_indentorder": { @@ -388,7 +445,7 @@ private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDig // Prepare Object array for insert/update Object[] objArr; - List serverColumnsList = Arrays.asList(syncUploadDataDigester.getServerColumns().split(",")); + List serverColumnsList = Arrays.asList(serverColumns.split(",")); List currentRecordValues = new ArrayList<>(); for (String column : serverColumnsList) { @@ -428,9 +485,9 @@ private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDig boolean updateSuccess = true; if (!syncDataListInsert.isEmpty()) { - String queryInsert = getQueryToInsertDataToServerDB(schemaName, syncTableName, syncUploadDataDigester.getServerColumns()); + String queryInsert = getQueryToInsertDataToServerDB(schemaName, syncTableName, serverColumns); try { - int[] i = dataSyncRepositoryCentral.syncDataToCentralDB(schemaName, syncTableName, syncUploadDataDigester.getServerColumns(), queryInsert, syncDataListInsert); + int[] i = dataSyncRepositoryCentral.syncDataToCentralDB(schemaName, syncTableName, serverColumns, queryInsert, syncDataListInsert); if (i.length != syncDataListInsert.size()) { insertSuccess = false; logger.error("Partial insert for table {}. Expected {} inserts, got {}. Failed records: {}", syncTableName, syncDataListInsert.size(), i.length, getFailedRecords(i, syncDataListInsert)); @@ -444,7 +501,7 @@ private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDig } if (!syncDataListUpdate.isEmpty()) { - String queryUpdate = getQueryToUpdateDataToServerDB(schemaName, syncUploadDataDigester.getServerColumns(), syncTableName); + String queryUpdate = getQueryToUpdateDataToServerDB(schemaName, serverColumns, syncTableName); try { int[] j = dataSyncRepositoryCentral.syncDataToCentralDB(schemaName, syncTableName, SERVER_COLUMNS_NOT_REQUIRED, queryUpdate, syncDataListUpdate); if (j.length != syncDataListUpdate.size()) { @@ -462,53 +519,59 @@ private boolean performGenericTableSync(SyncUploadDataDigester syncUploadDataDig } private String getQueryToInsertDataToServerDB(String schemaName, String tableName, String serverColumns) { - String[] columnsArr = null; - if (serverColumns != null) - columnsArr = serverColumns.split(","); + if (!isValidSchemaName(schemaName) || !isValidTableName(tableName)) { + logger.error("Invalid schema or table name for getQueryToInsertDataToServerDB: Schema='{}', Table='{}'.", schemaName, tableName); + throw new IllegalArgumentException("Invalid schema or table name provided."); + } + if (!isValidColumnNames(serverColumns)) { + logger.error("Invalid server columns provided for getQueryToInsertDataToServerDB: {}", serverColumns); + throw new IllegalArgumentException("Invalid column names provided."); + } + + String[] columnsArr = serverColumns.split(","); StringBuilder preparedStatementSetter = new StringBuilder(); - if (columnsArr != null && columnsArr.length > 0) { - for (int i = 0; i < columnsArr.length; i++) { - preparedStatementSetter.append("?"); - if (i < columnsArr.length - 1) { - preparedStatementSetter.append(", "); - } + for (int i = 0; i < columnsArr.length; i++) { + preparedStatementSetter.append("?"); + if (i < columnsArr.length - 1) { + preparedStatementSetter.append(", "); } } - StringBuilder queryBuilder = new StringBuilder("INSERT INTO "); - queryBuilder.append(schemaName).append(".").append(tableName); - queryBuilder.append("("); - queryBuilder.append(serverColumns); - queryBuilder.append(") VALUES ("); - queryBuilder.append(preparedStatementSetter); - queryBuilder.append(")"); - return queryBuilder.toString(); + return String.format("INSERT INTO %s.%s(%s) VALUES (%s)", schemaName, tableName, serverColumns, preparedStatementSetter.toString()); } public String getQueryToUpdateDataToServerDB(String schemaName, String serverColumns, String tableName) { - String[] columnsArr = null; - if (serverColumns != null) - columnsArr = serverColumns.split(","); + if (!isValidSchemaName(schemaName) || !isValidTableName(tableName)) { + logger.error("Invalid schema or table name for getQueryToUpdateDataToServerDB: Schema='{}', Table='{}'.", schemaName, tableName); + throw new IllegalArgumentException("Invalid schema or table name provided."); + } + if (!isValidColumnNames(serverColumns)) { + logger.error("Invalid server columns provided for getQueryToUpdateDataToServerDB: {}", serverColumns); + throw new IllegalArgumentException("Invalid column names provided."); + } + String[] columnsArr = serverColumns.split(","); StringBuilder preparedStatementSetter = new StringBuilder(); - if (columnsArr != null && columnsArr.length > 0) { - for (int i = 0; i < columnsArr.length; i++) { - preparedStatementSetter.append(columnsArr[i].trim()); - preparedStatementSetter.append(" = ?"); - if (i < columnsArr.length - 1) { - preparedStatementSetter.append(", "); - } + for (int i = 0; i < columnsArr.length; i++) { + String column = columnsArr[i].trim(); + if (!isValidColumnName(column)) { + logger.error("Invalid individual column name encountered: {}", column); + throw new IllegalArgumentException("Invalid individual column name provided: " + column); + } + + preparedStatementSetter.append(column); + preparedStatementSetter.append(" = ?"); + if (i < columnsArr.length - 1) { + preparedStatementSetter.append(", "); } } - StringBuilder queryBuilder = new StringBuilder(" UPDATE "); - queryBuilder.append(schemaName).append(".").append(tableName); - queryBuilder.append(" SET "); - queryBuilder.append(preparedStatementSetter); - queryBuilder.append(" WHERE VanSerialNo = ? "); + StringBuilder queryBuilder = new StringBuilder(); + queryBuilder.append(String.format("UPDATE %s.%s SET %s WHERE VanSerialNo = ?", schemaName, tableName, preparedStatementSetter.toString())); + if (Arrays.asList("t_patientissue", "t_physicalstockentry", "t_stockadjustment", "t_saitemmapping", "t_stocktransfer", "t_patientreturn", "t_facilityconsumption", "t_indent", @@ -521,20 +584,41 @@ public String getQueryToUpdateDataToServerDB(String schemaName, String serverCol return queryBuilder.toString(); } - // Helper to get information about failed records (for logging purposes) + private boolean isValidSchemaName(String schemaName) { + return VALID_SCHEMAS.contains(schemaName.toLowerCase()); + } + + private boolean isValidTableName(String tableName) { + return VALID_TABLES.contains(tableName.toLowerCase()); + } + + private boolean isValidColumnName(String columnName) { + return columnName != null && columnName.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); + } + + private boolean isValidColumnNames(String columnNames) { + if (columnNames == null || columnNames.trim().isEmpty()) { + return false; + } + String[] cols = columnNames.split(","); + for (String col : cols) { + if (!isValidColumnName(col.trim())) { + return false; + } + } + return true; + } + + private String getFailedRecords(int[] results, List data) { List failedRecordsInfo = new ArrayList<>(); for (int k = 0; k < results.length; k++) { - // In Spring JDBC batchUpdate, a value of Statement.EXECUTE_FAILED or Statement.SUCCESS_NO_INFO - // usually indicates a failure or success without specific row count. - // A common return value for success is 1 (for one row updated/inserted). - if (results[k] < 1) { // Assuming 1 means success, and anything else (0, -2, etc.) means failure - // Attempt to get some identifiable info from the failed record - if (data.get(k).length > 0) { - failedRecordsInfo.add("Record at index " + k + " (VanSerialNo/ID: " + data.get(k)[data.get(k).length - 2] + ")"); - } else { - failedRecordsInfo.add("Record at index " + k + " (No identifiable info)"); + if (results[k] < 1) { + String idInfo = "N/A"; + if (data.get(k) != null && data.get(k).length > 0) { + idInfo = "Record data size: " + data.get(k).length; } + failedRecordsInfo.add("Record at index " + k + " (Info: " + idInfo + ")"); } } return String.join("; ", failedRecordsInfo); diff --git a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java index 0c61681f..05fb4ace 100644 --- a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java +++ b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java @@ -23,19 +23,6 @@ public static HttpEntity createRequestEntity(Object body, String authori headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + authorization); } - // if (jwtToken == null || jwtToken.isEmpty()) { - // ServletRequestAttributes attrs = - // (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - // if (attrs != null) { - // HttpServletRequest request = attrs.getRequest(); - // try { - // jwtToken = CookieUtil.getJwtTokenFromCookie(request); - // } catch (Exception e) { - // logger.error("Error while getting JWT token from cookie: {}", e.getMessage()); - // } - // } - // } - ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if ((jwtToken == null || jwtToken.isEmpty()) && attrs != null) { @@ -48,7 +35,6 @@ public static HttpEntity createRequestEntity(Object body, String authori String jwtTokenHeader = request.getHeader("JwtToken"); if (jwtTokenHeader != null && !jwtTokenHeader.isEmpty()) { - // headers.add("JwtToken", jwtTokenHeader); jwtToken = jwtTokenHeader; } } @@ -58,8 +44,6 @@ public static HttpEntity createRequestEntity(Object body, String authori headers.add(HttpHeaders.COOKIE, "Jwttoken=" + jwtToken); } - logger.info("Test header token="+headers); - return new HttpEntity<>(body, headers); } } \ No newline at end of file From f0d39e95f0b89872e3f1572b314ac72823518ad2 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 29 Jul 2025 12:54:25 +0530 Subject: [PATCH 09/18] fix: remove logger and replace the license --- .../DataSyncRepositoryCentral.java | 22 ++++++++++++++++++- .../GetDataFromVanAndSyncToDBImpl.java | 21 ++++++++++++++++++ .../com/iemr/mmu/utils/RestTemplateUtil.java | 21 ++++++++++++++++++ 3 files changed, 63 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 70e946bf..b2918b74 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -1,3 +1,24 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ package com.iemr.mmu.service.dataSyncLayerCentral; import org.slf4j.Logger; @@ -129,7 +150,6 @@ public List> getMasterDataFromTable(String schema, String ta List params = new ArrayList<>(); if (!isValidDatabaseIdentifier(schema) || !isValidDatabaseIdentifier(table)) { - logger.error("Invalid database identifier detected in getMasterDataFromTable: schema={}, table={}", schema, table); throw new IllegalArgumentException("Invalid database identifier provided."); } 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 fce0935c..4b8588d9 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -1,3 +1,24 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ package com.iemr.mmu.service.dataSyncLayerCentral; import java.time.LocalDateTime; diff --git a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java index 05fb4ace..2cbab41d 100644 --- a/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java +++ b/src/main/java/com/iemr/mmu/utils/RestTemplateUtil.java @@ -1,3 +1,24 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +*/ package com.iemr.mmu.utils; import org.slf4j.Logger; From 0e73b47525ab4768f0c86a1d9220a03d234f6f0d Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 29 Jul 2025 13:17:57 +0530 Subject: [PATCH 10/18] fix: remove the logs --- .../DataSyncRepositoryCentral.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) 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 b2918b74..89e339c0 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -50,7 +50,7 @@ private JdbcTemplate getJdbcTemplate() { } private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); - + // Data Upload Repository public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, String vanSerialNo, String vanID, String vanAutoIncColumnName, int syncFacilityID) { @@ -94,29 +94,25 @@ public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, Object[] queryParams = params.toArray(); logger.debug("Checking record existence query: {} with params: {}", query, Arrays.toString(queryParams)); - System.out.println("Checking record existence query: " + query + " with params: " + Arrays.toString(queryParams)); try { List> resultSet = jdbcTemplate.queryForList(query, queryParams); if (resultSet != null && !resultSet.isEmpty()) { - System.out.println("Record found for table " + tableName + ": VanSerialNo=" + vanSerialNo + ", VanID=" + vanID); logger.debug("Record found for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); return 1; } else { - System.out.println("No record found for table " + tableName + ": VanSerialNo=" + vanSerialNo + ", VanID=" + vanID); logger.debug("No record found for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); return 0; } } catch (org.springframework.dao.EmptyResultDataAccessException e) { - System.out.println("No record found (EmptyResultDataAccessException) for table " + tableName + ": VanSerialNo=" + vanSerialNo + ", VanID=" + vanID); logger.debug("No record found (EmptyResultDataAccessException) for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); return 0; } catch (Exception e) { - System.out.println("Database error during checkRecordIsAlreadyPresentOrNot for table " + tableName + ": VanSerialNo=" + vanSerialNo + ", VanID=" + vanID); logger.error("Database error during checkRecordIsAlreadyPresentOrNot for table {}: VanSerialNo={}, VanID={}. Error: {}", tableName, vanSerialNo, vanID, e.getMessage(), e); throw new RuntimeException("Failed to check record existence: " + e.getMessage(), e); // Re-throw or handle as appropriate } } + // Helper method to validate database identifiers private boolean isValidDatabaseIdentifier(String identifier) { @@ -127,16 +123,12 @@ private boolean isValidDatabaseIdentifier(String identifier) { public int[] syncDataToCentralDB(String schema, String tableName, String serverColumns, String query, List syncDataList) { jdbcTemplate = getJdbcTemplate(); - logger.info("Executing batch operation for table: {}. Query type: {}. Number of records: {}", tableName, query.startsWith("INSERT") ? "INSERT" : "UPDATE", syncDataList.size()); - logger.debug("Query: {}", query); try { int[] i = jdbcTemplate.batchUpdate(query, syncDataList); - System.out.println("Batch operation completed for table " + tableName + ". Results: " + Arrays.toString(i)); logger.info("Batch operation completed for table {}. Results: {}", tableName, Arrays.toString(i)); return i; } catch (Exception e) { logger.error("Exception during batch update for table {}: {}", tableName, e.getMessage(), e); - System.out.println("Exception during batch update for table " + tableName + ": " + e.getMessage()); throw new RuntimeException("Batch sync failed for table " + tableName + ": " + e.getMessage(), e); } } From e0846c2a2af49ca211892bba3a88664a426bac1c Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 29 Jul 2025 13:27:46 +0530 Subject: [PATCH 11/18] fix: resolve code scanning alert --- .../DataSyncRepositoryCentral.java | 118 ++++++++++++++---- 1 file changed, 92 insertions(+), 26 deletions(-) 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 89e339c0..0165fdf9 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -33,6 +33,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.HashSet; @Service public class DataSyncRepositoryCentral { @@ -41,7 +43,6 @@ public class DataSyncRepositoryCentral { private JdbcTemplate jdbcTemplate; - // Lazily initialize jdbcTemplate to ensure DataSource is available private JdbcTemplate getJdbcTemplate() { if (this.jdbcTemplate == null) { this.jdbcTemplate = new JdbcTemplate(dataSource); @@ -50,24 +51,78 @@ private JdbcTemplate getJdbcTemplate() { } private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); - - // Data Upload Repository + + private static final Set VALID_SCHEMAS = new HashSet<>(Arrays.asList("public", "db_iemr_mmu_sync")); + + private static final Set VALID_TABLES = new HashSet<>(Arrays.asList( + "m_beneficiaryregidmapping", "i_beneficiaryaccount", "i_beneficiaryaddress", "i_beneficiarycontacts", + "i_beneficiarydetails", "i_beneficiaryfamilymapping", "i_beneficiaryidentity", "i_beneficiarymapping", + "t_benvisitdetail", "t_phy_anthropometry", "t_phy_vitals", "t_benadherence", "t_anccare", "t_pnccare", + "t_ncdscreening", "t_ncdcare", "i_ben_flow_outreach", "t_covid19", "t_idrsdetails", "t_physicalactivity", + "t_phy_generalexam", "t_phy_headtotoe", "t_sys_obstetric", "t_sys_gastrointestinal", "t_sys_cardiovascular", + "t_sys_respiratory", "t_sys_centralnervous", "t_sys_musculoskeletalsystem", "t_sys_genitourinarysystem", + "t_ancdiagnosis", "t_ncddiagnosis", "t_pncdiagnosis", "t_benchefcomplaint", "t_benclinicalobservation", + "t_prescription", "t_prescribeddrug", "t_lab_testorder", "t_benreferdetails", + "t_lab_testresult", "t_physicalstockentry", "t_patientissue", "t_facilityconsumption", "t_itemstockentry", + "t_itemstockexit", "t_benmedhistory", "t_femaleobstetrichistory", "t_benmenstrualdetails", + "t_benpersonalhabit", "t_childvaccinedetail1", "t_childvaccinedetail2", "t_childoptionalvaccinedetail", + "t_ancwomenvaccinedetail", "t_childfeedinghistory", "t_benallergyhistory", "t_bencomorbiditycondition", + "t_benmedicationhistory", "t_benfamilyhistory", "t_perinatalhistory", "t_developmenthistory", + "t_cancerfamilyhistory", "t_cancerpersonalhistory", "t_cancerdiethistory", "t_cancerobstetrichistory", + "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" + )); + + private boolean isValidDatabaseIdentifierCharacter(String identifier) { + return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); + } + + private boolean isValidSchemaName(String schemaName) { + return VALID_SCHEMAS.contains(schemaName.toLowerCase()); + } + + private boolean isValidTableName(String tableName) { + return VALID_TABLES.contains(tableName.toLowerCase()); + } + + private boolean isValidColumnNamesList(String columnNames) { + if (columnNames == null || columnNames.trim().isEmpty()) { + return false; + } + String[] individualColumns = columnNames.split(","); + for (String col : individualColumns) { + if (!isValidDatabaseIdentifierCharacter(col.trim())) { + return false; + } + } + return true; + } + public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, String vanSerialNo, String vanID, String vanAutoIncColumnName, int syncFacilityID) { jdbcTemplate = getJdbcTemplate(); List params = new ArrayList<>(); - if (!isValidDatabaseIdentifier(schemaName) || !isValidDatabaseIdentifier(tableName) || !isValidDatabaseIdentifier(vanAutoIncColumnName)) { - logger.error("Invalid database identifier detected: schemaName={}, tableName={}, vanAutoIncColumnName={}", schemaName, tableName, vanAutoIncColumnName); - throw new IllegalArgumentException("Invalid database identifier provided."); + if (!isValidSchemaName(schemaName)) { + logger.error("Invalid schema name detected: {}", schemaName); + throw new IllegalArgumentException("Invalid schema name provided."); + } + if (!isValidTableName(tableName)) { + logger.error("Invalid table name detected: {}", tableName); + throw new IllegalArgumentException("Invalid table name provided."); + } + if (!isValidDatabaseIdentifierCharacter(vanAutoIncColumnName)) { // vanAutoIncColumnName is a single column identifier + logger.error("Invalid auto increment column name detected: {}", vanAutoIncColumnName); + throw new IllegalArgumentException("Invalid auto increment column name provided."); } - StringBuilder queryBuilder = new StringBuilder("SELECT "); - queryBuilder.append(vanAutoIncColumnName); + queryBuilder.append(vanAutoIncColumnName); // Appending validated column name queryBuilder.append(" FROM "); - queryBuilder.append(schemaName).append(".").append(tableName); + queryBuilder.append(schemaName).append(".").append(tableName); // Appending validated schema and table names StringBuilder whereClause = new StringBuilder(); whereClause.append(" WHERE "); @@ -112,14 +167,7 @@ public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, throw new RuntimeException("Failed to check record existence: " + e.getMessage(), e); // Re-throw or handle as appropriate } } - - // Helper method to validate database identifiers - private boolean isValidDatabaseIdentifier(String identifier) { - return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); - } - - // Method for synchronization of data to central DB public int[] syncDataToCentralDB(String schema, String tableName, String serverColumns, String query, List syncDataList) { jdbcTemplate = getJdbcTemplate(); @@ -141,14 +189,23 @@ public List> getMasterDataFromTable(String schema, String ta List> resultSetList = new ArrayList<>(); List params = new ArrayList<>(); - if (!isValidDatabaseIdentifier(schema) || !isValidDatabaseIdentifier(table)) { - throw new IllegalArgumentException("Invalid database identifier provided."); + if (!isValidSchemaName(schema)) { + logger.error("Invalid schema name: {}", schema); + throw new IllegalArgumentException("Invalid schema name provided."); + } + if (!isValidTableName(table)) { + logger.error("Invalid table name: {}", table); + throw new IllegalArgumentException("Invalid table name provided."); + } + if (!isValidColumnNamesList(columnNames)) { + logger.error("Invalid column names list: {}", columnNames); + throw new IllegalArgumentException("Invalid column names provided."); } StringBuilder baseQueryBuilder = new StringBuilder(" SELECT "); - baseQueryBuilder.append(columnNames); + baseQueryBuilder.append(columnNames); baseQueryBuilder.append(" FROM "); - baseQueryBuilder.append(schema).append(".").append(table); + baseQueryBuilder.append(schema).append(".").append(table); if (masterType != null) { if (lastDownloadDate != null) { @@ -181,7 +238,7 @@ public List> getMasterDataFromTable(String schema, String ta resultSetList = jdbcTemplate.queryForList(finalQuery, params.toArray()); } } catch (Exception e) { - logger.error("Error fetching master data from table {}: {}", table, e.getMessage(), e); + logger.error("Error fetching master data from table {}.{}: {}", schema, table, e.getMessage(), e); throw new RuntimeException("Failed to fetch master data: " + e.getMessage(), e); } logger.info("Result set Details size: {}", resultSetList.size()); @@ -192,19 +249,28 @@ public List> getBatchForBenDetails(String schema, String tab String whereClause, int limit, int offset) { jdbcTemplate = getJdbcTemplate(); - if (!isValidDatabaseIdentifier(schema) || !isValidDatabaseIdentifier(table)) { - logger.error("Invalid database identifier detected in getBatchForBenDetails: schema={}, table={}", schema, table); - throw new IllegalArgumentException("Invalid database identifier provided."); + if (!isValidSchemaName(schema)) { + logger.error("Invalid schema name detected in getBatchForBenDetails: {}", schema); + throw new IllegalArgumentException("Invalid schema name provided."); } - + if (!isValidTableName(table)) { + logger.error("Invalid table name detected in getBatchForBenDetails: {}", table); + throw new IllegalArgumentException("Invalid table name provided."); + } + if (!isValidColumnNamesList(columnNames)) { + logger.error("Invalid column names list in getBatchForBenDetails: {}", columnNames); + throw new IllegalArgumentException("Invalid column names provided."); + } + String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; logger.debug("Fetching batch for beneficiary details. Query: {}, Limit: {}, Offset: {}", query, limit, offset); try { return jdbcTemplate.queryForList(query, limit, offset); } catch (Exception e) { - logger.error("Error fetching batch for beneficiary details from table {}: {}", table, e.getMessage(), e); + logger.error("Error fetching batch for beneficiary details from table {}.{}: {}", schema, table, e.getMessage(), e); throw new RuntimeException("Failed to fetch batch data: " + e.getMessage(), e); } } + // End of Data Download Repository } \ No newline at end of file From 12e4480d3fb99e0a3820a1951072e89c668c0e32 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 29 Jul 2025 14:15:28 +0530 Subject: [PATCH 12/18] fix: resolve code scanning alert --- .../dataSyncLayerCentral/DataSyncRepositoryCentral.java | 4 ---- 1 file changed, 4 deletions(-) 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 0165fdf9..d6af9e8b 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -232,11 +232,7 @@ public List> getMasterDataFromTable(String schema, String ta String finalQuery = baseQueryBuilder.toString(); try { - if (params.isEmpty()) { - resultSetList = jdbcTemplate.queryForList(finalQuery); - } else { resultSetList = jdbcTemplate.queryForList(finalQuery, params.toArray()); - } } catch (Exception e) { logger.error("Error fetching master data from table {}.{}: {}", schema, table, e.getMessage(), e); throw new RuntimeException("Failed to fetch master data: " + e.getMessage(), e); From 57fa8e5e7aaa7470d58e70fc33c8c8468abb3189 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 29 Jul 2025 14:29:28 +0530 Subject: [PATCH 13/18] fix: resolve code scanning alert --- .../DataSyncRepositoryCentral.java | 165 ++++++------------ 1 file changed, 49 insertions(+), 116 deletions(-) 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 d6af9e8b..26dc2157 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -29,12 +29,7 @@ import javax.sql.DataSource; import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.HashSet; +import java.util.*; @Service public class DataSyncRepositoryCentral { @@ -50,11 +45,11 @@ private JdbcTemplate getJdbcTemplate() { return this.jdbcTemplate; } - private Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); + private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); - private static final Set VALID_SCHEMAS = new HashSet<>(Arrays.asList("public", "db_iemr_mmu_sync")); + private static final Set VALID_SCHEMAS = Set.of("public", "db_iemr_mmu_sync"); - private static final Set VALID_TABLES = new HashSet<>(Arrays.asList( + private static final Set VALID_TABLES = Set.of( "m_beneficiaryregidmapping", "i_beneficiaryaccount", "i_beneficiaryaddress", "i_beneficiarycontacts", "i_beneficiarydetails", "i_beneficiaryfamilymapping", "i_beneficiaryidentity", "i_beneficiarymapping", "t_benvisitdetail", "t_phy_anthropometry", "t_phy_vitals", "t_benadherence", "t_anccare", "t_pnccare", @@ -73,9 +68,9 @@ 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" - )); + ); - private boolean isValidDatabaseIdentifierCharacter(String identifier) { + private boolean isValidDatabaseIdentifierCharacter(String identifier) { return identifier != null && identifier.matches("^[a-zA-Z_][a-zA-Z0-9_]*$"); } @@ -91,8 +86,7 @@ private boolean isValidColumnNamesList(String columnNames) { if (columnNames == null || columnNames.trim().isEmpty()) { return false; } - String[] individualColumns = columnNames.split(","); - for (String col : individualColumns) { + for (String col : columnNames.split(",")) { if (!isValidDatabaseIdentifierCharacter(col.trim())) { return false; } @@ -103,68 +97,36 @@ private boolean isValidColumnNamesList(String columnNames) { public int checkRecordIsAlreadyPresentOrNot(String schemaName, String tableName, String vanSerialNo, String vanID, String vanAutoIncColumnName, int syncFacilityID) { jdbcTemplate = getJdbcTemplate(); - List params = new ArrayList<>(); - if (!isValidSchemaName(schemaName)) { - logger.error("Invalid schema name detected: {}", schemaName); - throw new IllegalArgumentException("Invalid schema name provided."); - } - if (!isValidTableName(tableName)) { - logger.error("Invalid table name detected: {}", tableName); - throw new IllegalArgumentException("Invalid table name provided."); - } - if (!isValidDatabaseIdentifierCharacter(vanAutoIncColumnName)) { // vanAutoIncColumnName is a single column identifier - logger.error("Invalid auto increment column name detected: {}", vanAutoIncColumnName); - throw new IllegalArgumentException("Invalid auto increment column name provided."); + if (!isValidSchemaName(schemaName) || !isValidTableName(tableName) || + !isValidDatabaseIdentifierCharacter(vanAutoIncColumnName)) { + logger.error("Invalid identifiers: schema={}, table={}, column={}", schemaName, tableName, vanAutoIncColumnName); + throw new IllegalArgumentException("Invalid identifiers provided."); } - StringBuilder queryBuilder = new StringBuilder("SELECT "); - queryBuilder.append(vanAutoIncColumnName); // Appending validated column name - queryBuilder.append(" FROM "); - queryBuilder.append(schemaName).append(".").append(tableName); // Appending validated schema and table names + StringBuilder queryBuilder = new StringBuilder("SELECT ") + .append(vanAutoIncColumnName).append(" FROM ") + .append(schemaName).append(".").append(tableName).append(" WHERE VanSerialNo = ?"); - StringBuilder whereClause = new StringBuilder(); - whereClause.append(" WHERE "); - whereClause.append("VanSerialNo = ?"); params.add(vanSerialNo); - if (Arrays.asList("t_patientissue", "t_physicalstockentry", "t_stockadjustment", "t_saitemmapping", + if (List.of("t_patientissue", "t_physicalstockentry", "t_stockadjustment", "t_saitemmapping", "t_stocktransfer", "t_patientreturn", "t_facilityconsumption", "t_indent", - "t_indentorder", "t_indentissue", "t_itemstockentry", "t_itemstockexit") - .contains(tableName.toLowerCase()) && syncFacilityID > 0) { - - whereClause.append(" AND "); - whereClause.append("SyncFacilityID = ?"); + "t_indentorder", "t_indentissue", "t_itemstockentry", "t_itemstockexit").contains(tableName.toLowerCase()) && syncFacilityID > 0) { + queryBuilder.append(" AND SyncFacilityID = ?"); params.add(syncFacilityID); - } else { - whereClause.append(" AND "); - whereClause.append("VanID = ?"); + queryBuilder.append(" AND VanID = ?"); params.add(vanID); } - queryBuilder.append(whereClause); - String query = queryBuilder.toString(); - Object[] queryParams = params.toArray(); - - logger.debug("Checking record existence query: {} with params: {}", query, Arrays.toString(queryParams)); - try { - List> resultSet = jdbcTemplate.queryForList(query, queryParams); - if (resultSet != null && !resultSet.isEmpty()) { - logger.debug("Record found for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); - return 1; - } else { - logger.debug("No record found for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); - return 0; - } - } catch (org.springframework.dao.EmptyResultDataAccessException e) { - logger.debug("No record found (EmptyResultDataAccessException) for table {}: VanSerialNo={}, VanID={}", tableName, vanSerialNo, vanID); - return 0; + List> resultSet = jdbcTemplate.queryForList(queryBuilder.toString(), params.toArray()); + return (resultSet != null && !resultSet.isEmpty()) ? 1 : 0; } catch (Exception e) { - logger.error("Database error during checkRecordIsAlreadyPresentOrNot for table {}: VanSerialNo={}, VanID={}. Error: {}", tableName, vanSerialNo, vanID, e.getMessage(), e); - throw new RuntimeException("Failed to check record existence: " + e.getMessage(), e); // Re-throw or handle as appropriate + logger.error("Error checking record presence: {}", e.getMessage(), e); + throw new RuntimeException("Failed to check record existence: " + e.getMessage(), e); } } @@ -172,101 +134,72 @@ public int[] syncDataToCentralDB(String schema, String tableName, String serverC List syncDataList) { jdbcTemplate = getJdbcTemplate(); try { - int[] i = jdbcTemplate.batchUpdate(query, syncDataList); - logger.info("Batch operation completed for table {}. Results: {}", tableName, Arrays.toString(i)); - return i; + return jdbcTemplate.batchUpdate(query, syncDataList); } catch (Exception e) { - logger.error("Exception during batch update for table {}: {}", tableName, e.getMessage(), e); - throw new RuntimeException("Batch sync failed for table " + tableName + ": " + e.getMessage(), e); + logger.error("Batch sync failed for table {}: {}", tableName, e.getMessage(), e); + throw new RuntimeException("Batch sync failed: " + e.getMessage(), e); } } - // End of Data Upload Repository - public List> getMasterDataFromTable(String schema, String table, String columnNames, - String masterType, Timestamp lastDownloadDate, Integer vanID, Integer psmID) throws Exception { + String masterType, Timestamp lastDownloadDate, Integer vanID, Integer psmID) { jdbcTemplate = getJdbcTemplate(); - List> resultSetList = new ArrayList<>(); List params = new ArrayList<>(); - if (!isValidSchemaName(schema)) { - logger.error("Invalid schema name: {}", schema); - throw new IllegalArgumentException("Invalid schema name provided."); - } - if (!isValidTableName(table)) { - logger.error("Invalid table name: {}", table); - throw new IllegalArgumentException("Invalid table name provided."); - } - if (!isValidColumnNamesList(columnNames)) { - logger.error("Invalid column names list: {}", columnNames); - throw new IllegalArgumentException("Invalid column names provided."); + if (!isValidSchemaName(schema) || !isValidTableName(table) || !isValidColumnNamesList(columnNames)) { + throw new IllegalArgumentException("Invalid schema, table, or column names."); } - StringBuilder baseQueryBuilder = new StringBuilder(" SELECT "); - baseQueryBuilder.append(columnNames); - baseQueryBuilder.append(" FROM "); - baseQueryBuilder.append(schema).append(".").append(table); + StringBuilder queryBuilder = new StringBuilder("SELECT ").append(columnNames) + .append(" FROM ").append(schema).append(".").append(table); if (masterType != null) { if (lastDownloadDate != null) { - baseQueryBuilder.append(" WHERE LastModDate >= ? "); + queryBuilder.append(" WHERE LastModDate >= ?"); params.add(lastDownloadDate); - if (masterType.equalsIgnoreCase("V")) { - baseQueryBuilder.append(" AND VanID = ? "); + if ("V".equalsIgnoreCase(masterType)) { + queryBuilder.append(" AND VanID = ?"); params.add(vanID); - } else if (masterType.equalsIgnoreCase("P")) { - baseQueryBuilder.append(" AND ProviderServiceMapID = ? "); + } else if ("P".equalsIgnoreCase(masterType)) { + queryBuilder.append(" AND ProviderServiceMapID = ?"); params.add(psmID); } } else { - if (masterType.equalsIgnoreCase("V")) { - baseQueryBuilder.append(" WHERE VanID = ? "); + queryBuilder.append(" WHERE "); + if ("V".equalsIgnoreCase(masterType)) { + queryBuilder.append("VanID = ?"); params.add(vanID); - } else if (masterType.equalsIgnoreCase("P")) { - baseQueryBuilder.append(" WHERE ProviderServiceMapID = ? "); + } else if ("P".equalsIgnoreCase(masterType)) { + queryBuilder.append("ProviderServiceMapID = ?"); params.add(psmID); } } } - String finalQuery = baseQueryBuilder.toString(); try { - resultSetList = jdbcTemplate.queryForList(finalQuery, params.toArray()); + return jdbcTemplate.queryForList(queryBuilder.toString(), params.toArray()); } catch (Exception e) { - logger.error("Error fetching master data from table {}.{}: {}", schema, table, e.getMessage(), e); + logger.error("Error fetching master data: {}", e.getMessage(), e); throw new RuntimeException("Failed to fetch master data: " + e.getMessage(), e); } - logger.info("Result set Details size: {}", resultSetList.size()); - return resultSetList; } public List> getBatchForBenDetails(String schema, String table, String columnNames, - String whereClause, int limit, int offset) { + String whereClause, int limit, int offset) { jdbcTemplate = getJdbcTemplate(); - if (!isValidSchemaName(schema)) { - logger.error("Invalid schema name detected in getBatchForBenDetails: {}", schema); - throw new IllegalArgumentException("Invalid schema name provided."); - } - if (!isValidTableName(table)) { - logger.error("Invalid table name detected in getBatchForBenDetails: {}", table); - throw new IllegalArgumentException("Invalid table name provided."); - } - if (!isValidColumnNamesList(columnNames)) { - logger.error("Invalid column names list in getBatchForBenDetails: {}", columnNames); - throw new IllegalArgumentException("Invalid column names provided."); + if (!isValidSchemaName(schema) || !isValidTableName(table) || !isValidColumnNamesList(columnNames)) { + throw new IllegalArgumentException("Invalid schema, table, or column names."); } - String query = "SELECT " + columnNames + " FROM " + schema + "." + table + whereClause + " LIMIT ? OFFSET ?"; - logger.debug("Fetching batch for beneficiary details. Query: {}, Limit: {}, Offset: {}", query, limit, offset); + String query = String.format("SELECT %s FROM %s.%s %s LIMIT ? OFFSET ?", columnNames, schema, table, whereClause); + try { return jdbcTemplate.queryForList(query, limit, offset); } catch (Exception e) { - logger.error("Error fetching batch for beneficiary details from table {}.{}: {}", schema, table, e.getMessage(), e); + logger.error("Error fetching batch details: {}", e.getMessage(), e); throw new RuntimeException("Failed to fetch batch data: " + e.getMessage(), e); } } - - // End of Data Download Repository -} \ No newline at end of file +} From 24648e3520a64287a1f224c89e0a1489189f698f Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 29 Jul 2025 15:52:16 +0530 Subject: [PATCH 14/18] fix: resolve code scanning alert --- .../DataSyncRepositoryCentral.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) 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 26dc2157..36c0cda3 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -21,16 +21,20 @@ */ package com.iemr.mmu.service.dataSyncLayerCentral; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.sql.DataSource; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; -import javax.sql.DataSource; -import java.sql.Timestamp; -import java.util.*; - @Service public class DataSyncRepositoryCentral { @Autowired @@ -192,6 +196,9 @@ public List> getBatchForBenDetails(String schema, String tab if (!isValidSchemaName(schema) || !isValidTableName(table) || !isValidColumnNamesList(columnNames)) { throw new IllegalArgumentException("Invalid schema, table, or column names."); } + // Safe dynamic SQL: Schema, table, and column names are validated against predefined whitelists. + // Only trusted values are used in the query string. + // limit and offset are passed as parameters to prevent SQL injection. String query = String.format("SELECT %s FROM %s.%s %s LIMIT ? OFFSET ?", columnNames, schema, table, whereClause); From afe5ed2736c2c178cd7371f80a9707b4ccd0753c Mon Sep 17 00:00:00 2001 From: Vanitha Date: Tue, 29 Jul 2025 15:58:05 +0530 Subject: [PATCH 15/18] fix: add comment for code violation --- .../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 36c0cda3..b84692be 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -182,6 +182,8 @@ public List> getMasterDataFromTable(String schema, String ta } try { + // Safe dynamic SQL: All dynamic parts (table names, columns, etc.) are validated or hardcoded. + // Parameter values are bound safely using prepared statement placeholders (?). return jdbcTemplate.queryForList(queryBuilder.toString(), params.toArray()); } catch (Exception e) { logger.error("Error fetching master data: {}", e.getMessage(), e); @@ -199,7 +201,6 @@ public List> getBatchForBenDetails(String schema, String tab // Safe dynamic SQL: Schema, table, and column names are validated against predefined whitelists. // Only trusted values are used in the query string. // limit and offset are passed as parameters to prevent SQL injection. - String query = String.format("SELECT %s FROM %s.%s %s LIMIT ? OFFSET ?", columnNames, schema, table, whereClause); try { From 78ceb258ee74ea31a9dfd8a60a52d93aeb7bf8a7 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Wed, 30 Jul 2025 10:28:59 +0530 Subject: [PATCH 16/18] fix: use syncuploaddataDigester class to load the deatils --- .../DataSyncRepositoryCentral.java | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) 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 b84692be..5c3dfc52 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -191,23 +191,28 @@ public List> getMasterDataFromTable(String schema, String ta } } - public List> getBatchForBenDetails(String schema, String table, String columnNames, - String whereClause, int limit, int offset) { - jdbcTemplate = getJdbcTemplate(); + public List> getBatchForBenDetails(SyncUploadDataDigester digester, + String whereClause, int limit, int offset) { + jdbcTemplate = getJdbcTemplate(); - if (!isValidSchemaName(schema) || !isValidTableName(table) || !isValidColumnNamesList(columnNames)) { - throw new IllegalArgumentException("Invalid schema, table, or column names."); - } - // Safe dynamic SQL: Schema, table, and column names are validated against predefined whitelists. - // Only trusted values are used in the query string. - // limit and offset are passed as parameters to prevent SQL injection. - String query = String.format("SELECT %s FROM %s.%s %s LIMIT ? OFFSET ?", columnNames, schema, table, whereClause); +String schema = digester.getSchemaName(); + String table = digester.getTableName(); + String columnNames = digester.getServerColumns(); - try { - return jdbcTemplate.queryForList(query, limit, offset); - } catch (Exception e) { - logger.error("Error fetching batch details: {}", e.getMessage(), e); - throw new RuntimeException("Failed to fetch batch data: " + e.getMessage(), e); + + if (!isValidSchemaName(schema) || !isValidTableName(table) || !isValidColumnNamesList(columnNames)) { + throw new IllegalArgumentException("Invalid schema, table, or column names."); + } + // Safe dynamic SQL: Schema, table, and column names are validated against predefined whitelists. + // Only trusted values are used in the query string. + // limit and offset are passed as parameters to prevent SQL injection. + String query = String.format("SELECT %s FROM %s.%s %s LIMIT ? OFFSET ?", columnNames, schema, table, whereClause); + + try { + return jdbcTemplate.queryForList(query, limit, offset); + } catch (Exception e) { + logger.error("Error fetching batch details: {}", e.getMessage(), e); + throw new RuntimeException("Failed to fetch batch data: " + e.getMessage(), e); + } } - } } From bad043d53c372eecfeee61062723a38689d1e56c Mon Sep 17 00:00:00 2001 From: Vanitha Date: Wed, 30 Jul 2025 10:51:15 +0530 Subject: [PATCH 17/18] fix: add syncuploaddigestor in implementation file too --- .../dataSyncLayerCentral/DataSyncRepositoryCentral.java | 2 ++ .../dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) 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 5c3dfc52..bdb1b6fe 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -35,6 +35,8 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; +import com.iemr.mmu.data.syncActivity_syncLayer.SyncUploadDataDigester; + @Service public class DataSyncRepositoryCentral { @Autowired 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 4b8588d9..2b16d7e5 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -287,9 +287,7 @@ public String update_I_BeneficiaryDetails_for_processed_in_batches(SyncUploadDat List> batchToFetch; try { batchToFetch = dataSyncRepositoryCentral.getBatchForBenDetails( - schemaName, - tableName, - syncUploadDataDigester.getServerColumns(), + syncUploadDataDigester, whereClauseForBatchFetch, limit, offset); From 6b700396f6fc1db019a01902a3542fe84a44f6d1 Mon Sep 17 00:00:00 2001 From: Vanitha Date: Wed, 30 Jul 2025 10:59:05 +0530 Subject: [PATCH 18/18] fix: sonarcube comments --- .../dataSyncLayerCentral/DataSyncRepositoryCentral.java | 4 ++-- .../dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 bdb1b6fe..175de980 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/DataSyncRepositoryCentral.java @@ -53,7 +53,7 @@ private JdbcTemplate getJdbcTemplate() { private final Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); - private static final Set VALID_SCHEMAS = Set.of("public", "db_iemr_mmu_sync"); + private static final Set VALID_SCHEMAS = Set.of("public", "db_iemr"); private static final Set VALID_TABLES = Set.of( "m_beneficiaryregidmapping", "i_beneficiaryaccount", "i_beneficiaryaddress", "i_beneficiarycontacts", @@ -208,7 +208,7 @@ public List> getBatchForBenDetails(SyncUploadDataDigester di // Safe dynamic SQL: Schema, table, and column names are validated against predefined whitelists. // Only trusted values are used in the query string. // limit and offset are passed as parameters to prevent SQL injection. - String query = String.format("SELECT %s FROM %s.%s %s LIMIT ? OFFSET ?", columnNames, schema, table, whereClause); + String query = String.format("SELECT %s FROM %s.%s %s LIMIT ? OFFSET ?", columnNames, schema, table, whereClause); //NOSONAR try { return jdbcTemplate.queryForList(query, limit, offset); 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 2b16d7e5..2d88e6f6 100644 --- a/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java +++ b/src/main/java/com/iemr/mmu/service/dataSyncLayerCentral/GetDataFromVanAndSyncToDBImpl.java @@ -50,7 +50,7 @@ public class GetDataFromVanAndSyncToDBImpl implements GetDataFromVanAndSyncToDB private DataSyncRepositoryCentral dataSyncRepositoryCentral; private static final Map> TABLE_GROUPS = new HashMap<>(); - private static final Set VALID_SCHEMAS = new HashSet<>(Arrays.asList("public", "db_iemr_mmu_sync")); // Add your actual schema names + private static final Set VALID_SCHEMAS = new HashSet<>(Arrays.asList("public", "db_iemr")); // Add your actual schema names private static final Set VALID_TABLES = new HashSet<>(Arrays.asList( "m_beneficiaryregidmapping", "i_beneficiaryaccount","i_beneficiaryaddress","i_beneficiarycontacts","i_beneficiarydetails","i_beneficiaryfamilymapping","i_beneficiaryidentity","i_beneficiarymapping", "t_benvisitdetail","t_phy_anthropometry","t_phy_vitals","t_benadherence","t_anccare","t_pnccare","t_ncdscreening","t_ncdcare","i_ben_flow_outreach","t_covid19","t_idrsdetails","t_physicalactivity",