From 982666871a054b8eeeb77802d06b7545862e0740 Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Wed, 4 Feb 2026 14:28:51 +0530 Subject: [PATCH 01/24] fix: amm-2140 stillbirth and abortion report download issue --- .../com/iemr/ecd/repository/report/EcdReportRepo.java | 8 ++++---- .../com/iemr/ecd/service/report/ReportServiceImpl.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java b/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java index 242a2e8..6cf3d65 100644 --- a/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java +++ b/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java @@ -94,10 +94,10 @@ public List getDevelopmentalDelayReport(@Param("startDate") Timestamp @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, @Param("psmId") Integer psmId); - @Query(value="call db_reporting.Pr_ECDAbortionReport(:startDate,:endDate,:agentId,:psmId,:role)", nativeQuery=true) + @Query(value="call db_reporting.Pr_ECDAbortionReport(:startDate,:endDate,:agentId,:psmId)", nativeQuery=true) public List getAbortionReport(@Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, - @Param("psmId") Integer psmId, @Param("role") String role); + @Param("psmId") Integer psmId); @Query(value="call db_reporting.Pr_ECDDeliveryStatusReport(:startDate,:endDate,:agentId,:psmId)", nativeQuery=true) @@ -120,10 +120,10 @@ public List getMaternalDeathReport(@Param("startDate") Timestamp start @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, @Param("psmId") Integer psmId); - @Query(value="call db_reporting.Pr_ECDStillBirthReport(:startDate,:endDate,:agentId,:psmId,:role)", nativeQuery=true) + @Query(value="call db_reporting.Pr_ECDStillBirthReport(:startDate,:endDate,:agentId,:psmId)", nativeQuery=true) public List getStillBirthReport(@Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, - @Param("psmId") Integer psmId, @Param("role") String role); + @Param("psmId") Integer psmId); @Query(value="call db_reporting.Pr_ECDBabyDeathReport(:startDate,:endDate,:agentId,:psmId,:role)", nativeQuery=true) public List getBabyDeathReport(@Param("startDate") Timestamp startDate, diff --git a/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java b/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java index 9a8ab09..287162d 100644 --- a/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java +++ b/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java @@ -572,7 +572,7 @@ public ByteArrayInputStream getAbortionReport(String request, String filename) t c.setRole(abortionReport.getRole()); result = ecdReportRepo.getAbortionReport(startDate, endDate, abortionReport.getAgentId(), - abortionReport.getPsmId(),abortionReport.getRole()); + abortionReport.getPsmId()); if (result != null && !result.isEmpty()) response = ExcelHelper.tutorialsToExcel(headers, result, c, criteriaColumns); @@ -771,7 +771,7 @@ public ByteArrayInputStream getStillBirthReport(String request, String filename) c.setRole(stillBirthReport.getRole()); result = ecdReportRepo.getStillBirthReport(startDate, endDate, stillBirthReport.getAgentId(), - stillBirthReport.getPsmId(),stillBirthReport.getRole()); + stillBirthReport.getPsmId()); if (result != null && !result.isEmpty()) From 66e5f1781847d6a97911308b62264217ca194f7e Mon Sep 17 00:00:00 2001 From: SnehaRH <77656297+snehar-nd@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:14:43 +0530 Subject: [PATCH 02/24] Bump version from 3.6.0 to 3.7.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 978b9cd..2302234 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.iemr.ecd ecd-api - 3.6.0 + 3.7.0 war ECD-API ECD project From 18a359b24f440d83ee0ca3d96218247354f00d56 Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Wed, 11 Feb 2026 12:15:35 +0530 Subject: [PATCH 03/24] fix: amm-2140 baby death report download issue --- .../java/com/iemr/ecd/repository/report/EcdReportRepo.java | 4 ++-- .../java/com/iemr/ecd/service/report/ReportServiceImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java b/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java index 6cf3d65..a8cc097 100644 --- a/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java +++ b/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java @@ -125,10 +125,10 @@ public List getStillBirthReport(@Param("startDate") Timestamp startDat @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, @Param("psmId") Integer psmId); - @Query(value="call db_reporting.Pr_ECDBabyDeathReport(:startDate,:endDate,:agentId,:psmId,:role)", nativeQuery=true) + @Query(value="call db_reporting.Pr_ECDBabyDeathReport(:startDate,:endDate,:agentId,:psmId)", nativeQuery=true) public List getBabyDeathReport(@Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, - @Param("psmId") Integer psmId, @Param("role") String role); + @Param("psmId") Integer psmIde); @Query(value="call db_reporting.Pr_ECDNotConnectedPhonelistDiffformatReport(:startDate,:endDate,:agentId,:psmId)", nativeQuery=true) public List getNotConnectedPhonelistDiffformatReport(@Param("startDate") Timestamp startDate, diff --git a/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java b/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java index 287162d..dd31000 100644 --- a/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java +++ b/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java @@ -813,7 +813,7 @@ public ByteArrayInputStream getBabyDeathReport(String request, String filename) c.setRole(babyDeathReport.getRole()); result = ecdReportRepo.getBabyDeathReport(startDate, endDate, babyDeathReport.getAgentId(), - babyDeathReport.getPsmId(), babyDeathReport.getRole()); + babyDeathReport.getPsmId()); if (result != null && !result.isEmpty()) response = ExcelHelper.tutorialsToExcel(headers, result, c, criteriaColumns); else From 4c4a791a5c20b5edf49578184bc3280227a94c14 Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Tue, 3 Mar 2026 10:44:58 +0530 Subject: [PATCH 04/24] amm-2140 misscarriage report fix --- .../java/com/iemr/ecd/repository/report/EcdReportRepo.java | 4 ++-- .../java/com/iemr/ecd/service/report/ReportServiceImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java b/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java index a8cc097..079a8de 100644 --- a/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java +++ b/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java @@ -140,9 +140,9 @@ public List getJSYRelatedComplaintsReport(@Param("startDate") Timestam @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, @Param("psmId") Integer psmId); - @Query(value="call db_reporting.Pr_ECDMiscarriageReport(:startDate,:endDate,:agentId,:psmId,:role)", nativeQuery=true) + @Query(value="call db_reporting.Pr_ECDMiscarriageReport(:startDate,:endDate,:agentId)", nativeQuery=true) public List getMiscarriageReport(@Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, - @Param("psmId") Integer psmId, @Param("role") String role); + @Param("psmId") Integer psmId); } diff --git a/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java b/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java index dd31000..d4054fe 100644 --- a/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java +++ b/src/main/java/com/iemr/ecd/service/report/ReportServiceImpl.java @@ -935,7 +935,7 @@ public ByteArrayInputStream getMiscarriageReport(String request, String filename c.setRole(miscarriageReport.getRole()); result = ecdReportRepo.getMiscarriageReport(startDate, endDate, miscarriageReport.getAgentId(), - miscarriageReport.getPsmId(), miscarriageReport.getRole()); + miscarriageReport.getPsmId()); if (result != null && !result.isEmpty()) response = ExcelHelper.tutorialsToExcel(headers, result, c, criteriaColumns); From 1c28b987bef9861a923605536659b205875415b1 Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Tue, 3 Mar 2026 13:27:24 +0530 Subject: [PATCH 05/24] amm-2140 misscarriage report fix --- src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java b/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java index 079a8de..35794a6 100644 --- a/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java +++ b/src/main/java/com/iemr/ecd/repository/report/EcdReportRepo.java @@ -140,7 +140,7 @@ public List getJSYRelatedComplaintsReport(@Param("startDate") Timestam @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, @Param("psmId") Integer psmId); - @Query(value="call db_reporting.Pr_ECDMiscarriageReport(:startDate,:endDate,:agentId)", nativeQuery=true) + @Query(value="call db_reporting.Pr_ECDMiscarriageReport(:startDate,:endDate,:agentId,:psmId)", nativeQuery=true) public List getMiscarriageReport(@Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate, @Param("agentId") Integer agentId, @Param("psmId") Integer psmId); From 62a43490c4b5bdac8989a3c491079cdce625f7a7 Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Thu, 5 Mar 2026 20:05:06 +0530 Subject: [PATCH 06/24] feat: amm-2180 reassign calls to anm move from mo bucket to anm bucket --- .../com/iemr/ecd/dto/associate/CallClosureDTO.java | 2 ++ .../iemr/ecd/service/associate/CallClosureImpl.java | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java b/src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java index 444c893..1fefd69 100644 --- a/src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java +++ b/src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java @@ -73,5 +73,7 @@ public class CallClosureDTO { private Boolean isWrongNumber; private String preferredLanguage; private String correctPhoneNumber; + private Boolean reassignToANM; + private String reassignCallType; } diff --git a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java index e1719b0..cc24a81 100644 --- a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java +++ b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java @@ -224,7 +224,17 @@ else if (!isHrp && !obj.getIsCallDisconnected()) { } } - + // MO → ANM Reassignment + if (Boolean.TRUE.equals(request.getReassignToANM())) { + callObj.setIsHighRisk(false); + callObj.setIsHrni(false); + callObj.setCallStatus(Constants.OPEN); + callObj.setAllocatedUserId(null); + callObj.setAllocationStatus(Constants.UNALLOCATED); + callObj.setCallAttemptNo(0); + } + + outboundCallsRepo.save(callObj); } else throw new ECDException( From 80dc11336c160d9f6423fcf956cc13bd0f419bf9 Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Tue, 10 Mar 2026 12:18:55 +0530 Subject: [PATCH 07/24] amm-2181 storing the highrisk reason on callclose with MO --- .../iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java | 4 ++-- .../java/com/iemr/ecd/service/associate/CallClosureImpl.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java index ef52d53..7f25920 100644 --- a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java +++ b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java @@ -371,8 +371,8 @@ List getIntroductoryRecordsUser(@Param("psmId") Integer psmId, @Modifying @Transactional - @Query(" UPDATE OutboundCalls SET isHighRisk = :isHighRisk WHERE motherId = :motherId AND childId IS NULL AND callDateTo>current_date()") - public int updateHRPForUpcomingCall(@Param("motherId") Long motherId, @Param("isHighRisk") Boolean isHighRisk); + @Query(" UPDATE OutboundCalls SET isHighRisk = :isHighRisk, highRiskReason = :highRiskReason WHERE motherId = :motherId AND childId IS NULL AND callDateTo>current_date()") + public int updateHRPForUpcomingCall(@Param("motherId") Long motherId, @Param("isHighRisk") Boolean isHighRisk, @Param("highRiskReason") String highRiskReason); @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t INNER JOIN MotherRecord AS mv ON t.motherId = mv.ecdIdNo WHERE t.allocationStatus =:allocationStatus AND " + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " diff --git a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java index cc24a81..6d3a16b 100644 --- a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java +++ b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java @@ -248,7 +248,7 @@ else if (!isHrp && !obj.getIsCallDisconnected()) { } else if (callObj.getMotherId() != null && callObj.getChildId() == null && callObj.getIsHighRisk() != null) { // Mother - outboundCallsRepo.updateHRPForUpcomingCall(callObj.getMotherId(), callObj.getIsHighRisk()); + outboundCallsRepo.updateHRPForUpcomingCall(callObj.getMotherId(), callObj.getIsHighRisk(), callObj.getHighRiskReason()); } } if (null != obj.getIsFurtherCallRequired()) { From a1f86852a3df2d97b7633492c3b28d81b1546b28 Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Tue, 10 Mar 2026 16:15:52 +0530 Subject: [PATCH 08/24] fix: AMM-2180 handled the hrp reason --- .../dao_temp/FetchMotherOutboundWorklist.java | 1 + .../OutboundCallsRepo.java | 3 +++ .../OutboundWorkListServiceImpl.java | 26 ++++++++++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/ecd/dao_temp/FetchMotherOutboundWorklist.java b/src/main/java/com/iemr/ecd/dao_temp/FetchMotherOutboundWorklist.java index 78e7717..0bd66c0 100644 --- a/src/main/java/com/iemr/ecd/dao_temp/FetchMotherOutboundWorklist.java +++ b/src/main/java/com/iemr/ecd/dao_temp/FetchMotherOutboundWorklist.java @@ -48,6 +48,7 @@ public class FetchMotherOutboundWorklist { private String phoneNoOfWhom; private String whomPhoneNo; private Boolean highRisk; + private String highRiskReason; private String husbandName; private String address; diff --git a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java index 7f25920..9c993fc 100644 --- a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java +++ b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java @@ -41,6 +41,9 @@ public interface OutboundCallsRepo extends CrudRepository { OutboundCalls findByObCallId(Long obCallId); + @Query("SELECT ob.obCallId, ob.highRiskReason FROM OutboundCalls ob WHERE ob.obCallId IN :obCallIds AND ob.highRiskReason IS NOT NULL") + List getHighRiskReasonByObCallIds(@Param("obCallIds") List obCallIds); + @Query(value = "call PR_FetchECDMotherOutboundWorklist(:allocatedUserID)", nativeQuery = true) List getAgentAllocatedMotherList(@Param("allocatedUserID") Integer allocatedUserID); diff --git a/src/main/java/com/iemr/ecd/service/outbound_worklist/OutboundWorkListServiceImpl.java b/src/main/java/com/iemr/ecd/service/outbound_worklist/OutboundWorkListServiceImpl.java index a109f1e..986ff10 100644 --- a/src/main/java/com/iemr/ecd/service/outbound_worklist/OutboundWorkListServiceImpl.java +++ b/src/main/java/com/iemr/ecd/service/outbound_worklist/OutboundWorkListServiceImpl.java @@ -24,6 +24,8 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -43,8 +45,30 @@ public class OutboundWorkListServiceImpl { public List getMotherWorkList(Integer userId) { try { List motherList = outboundCallsRepo.getAgentAllocatedMotherList(userId); + List result = getMotherDtoList(motherList); - return getMotherDtoList(motherList); + // Enrich with highRiskReason from OutboundCalls table + List obCallIds = result.stream() + .map(FetchMotherOutboundWorklist::getObCallId) + .filter(id -> id != null) + .collect(Collectors.toList()); + + if (!obCallIds.isEmpty()) { + List hrpReasons = outboundCallsRepo.getHighRiskReasonByObCallIds(obCallIds); + Map reasonMap = hrpReasons.stream() + .collect(Collectors.toMap( + row -> (Long) row[0], + row -> (String) row[1], + (existing, replacement) -> existing)); + + for (FetchMotherOutboundWorklist item : result) { + if (item.getObCallId() != null && reasonMap.containsKey(item.getObCallId())) { + item.setHighRiskReason(reasonMap.get(item.getObCallId())); + } + } + } + + return result; } catch (Exception e) { throw new ECDException(e); } From 4a77a537f840023bf6e404245e8bed1c0b370211 Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Tue, 10 Mar 2026 19:31:19 +0530 Subject: [PATCH 09/24] fix: AMM-2180 AMM-2181 modified the fixes removed unwanted code --- .../service/associate/CallClosureImpl.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java index 6d3a16b..8d94a7b 100644 --- a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java +++ b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java @@ -211,7 +211,7 @@ public String closeCall(CallClosureDTO request) { boolean isHrp = request.getIsHrp(); callObj.setIsHighRisk(isHrp); - // Check if the role should be changed to MO + // ANM marks HRP = true → move to MO (high risk) bucket if (isHrp && obj.getReceivedRoleName().equalsIgnoreCase(Constants.ANM)) { callObj.setCallStatus(Constants.OPEN); callObj.setAllocatedUserId(null); @@ -219,19 +219,30 @@ public String closeCall(CallClosureDTO request) { callObj.setCallAttemptNo(0); } + // MO marks HRP = false → move to ANM (low risk) bucket + else if (!isHrp && obj.getReceivedRoleName().equalsIgnoreCase("MO")) { + callObj.setCallStatus(Constants.OPEN); + callObj.setAllocatedUserId(null); + callObj.setAllocationStatus(Constants.UNALLOCATED); + callObj.setCallAttemptNo(0); + } + else if (!isHrp && !obj.getIsCallDisconnected()) { callObj.setCallStatus(Constants.COMPLETED); } } - // MO → ANM Reassignment - if (Boolean.TRUE.equals(request.getReassignToANM())) { - callObj.setIsHighRisk(false); - callObj.setIsHrni(false); - callObj.setCallStatus(Constants.OPEN); - callObj.setAllocatedUserId(null); - callObj.setAllocationStatus(Constants.UNALLOCATED); - callObj.setCallAttemptNo(0); + if (request.getIsHrni() != null) { + boolean isHrni = request.getIsHrni(); + callObj.setIsHrni(isHrni); + + // MO marks HRNI = false → move to ANM (low risk) bucket + if (!isHrni && obj.getReceivedRoleName().equalsIgnoreCase("MO")) { + callObj.setCallStatus(Constants.OPEN); + callObj.setAllocatedUserId(null); + callObj.setAllocationStatus(Constants.UNALLOCATED); + callObj.setCallAttemptNo(0); + } } From ec135bdd9b8b3d38445e837e0ac367df08990ede Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Tue, 10 Mar 2026 19:50:34 +0530 Subject: [PATCH 10/24] fix: removed the unused variables --- src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java b/src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java index 1fefd69..444c893 100644 --- a/src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java +++ b/src/main/java/com/iemr/ecd/dto/associate/CallClosureDTO.java @@ -73,7 +73,5 @@ public class CallClosureDTO { private Boolean isWrongNumber; private String preferredLanguage; private String correctPhoneNumber; - private Boolean reassignToANM; - private String reassignCallType; } From 127772974d9e302aa6830d99c1e5deca5905121c Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Tue, 10 Mar 2026 20:53:20 +0530 Subject: [PATCH 11/24] fix: hrp/hrni reason was not fetching properly --- .../repository/ecd/ECDCallResponseRepo.java | 4 +-- .../associate/BeneficiaryCallHistoryImpl.java | 12 +++------ .../OutboundWorkListServiceImpl.java | 27 +------------------ 3 files changed, 7 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repository/ecd/ECDCallResponseRepo.java b/src/main/java/com/iemr/ecd/repository/ecd/ECDCallResponseRepo.java index bdc4294..33c3e6c 100644 --- a/src/main/java/com/iemr/ecd/repository/ecd/ECDCallResponseRepo.java +++ b/src/main/java/com/iemr/ecd/repository/ecd/ECDCallResponseRepo.java @@ -38,10 +38,10 @@ public interface ECDCallResponseRepo extends JpaRepository getHrpHrniDetailsOld(@Param("motherId") Long motherId, @Param("childId") Long childId); - @Query(value = " SELECT t FROM ECDCallResponse t WHERE t.motherId=:motherId AND t.reasonsForHrpDB IS NOT NULL ORDER BY 1 DESC ") + @Query(value = " SELECT t FROM ECDCallResponse t WHERE t.motherId=:motherId AND t.reasonsForHrpDB IS NOT NULL ORDER BY t.createdDate DESC ") Page getHrpDetailsMother(Pageable pageable, @Param("motherId") Long motherId); - @Query(value = " SELECT t FROM ECDCallResponse t WHERE t.childId=:childId AND t.reasonsForHrniDB IS NOT NULL ORDER BY 1 DESC ") + @Query(value = " SELECT t FROM ECDCallResponse t WHERE t.childId=:childId AND t.reasonsForHrniDB IS NOT NULL ORDER BY t.createdDate DESC ") Page getHrniDetailsChild(Pageable pageable, @Param("childId") Long childId); @Query(value = "call PR_UpdateHRP_HRniReasons(:benCallId, :obCallId)", nativeQuery = true) diff --git a/src/main/java/com/iemr/ecd/service/associate/BeneficiaryCallHistoryImpl.java b/src/main/java/com/iemr/ecd/service/associate/BeneficiaryCallHistoryImpl.java index 743fef1..c8f7d99 100644 --- a/src/main/java/com/iemr/ecd/service/associate/BeneficiaryCallHistoryImpl.java +++ b/src/main/java/com/iemr/ecd/service/associate/BeneficiaryCallHistoryImpl.java @@ -193,17 +193,13 @@ public ECDCallResponse getHrpHrniDetails(Long motherId, Long childId) { if (childId != null) { Page page = ecdCallResponseRepo.getHrniDetailsChild(pageable, childId); - if (page.getSize() > 0) { - List objLIst = page.getContent(); - obj = objLIst.get(0); - + if (page.hasContent()) { + obj = page.getContent().get(0); } } else if (motherId != null) { Page page = ecdCallResponseRepo.getHrpDetailsMother(pageable, motherId); - if (page.getSize() > 0) { - List objLIst = page.getContent(); - obj = objLIst.get(0); - + if (page.hasContent()) { + obj = page.getContent().get(0); } } else throw new InvalidRequestException("NULL motherId/childId", "send valid motherId or childId"); diff --git a/src/main/java/com/iemr/ecd/service/outbound_worklist/OutboundWorkListServiceImpl.java b/src/main/java/com/iemr/ecd/service/outbound_worklist/OutboundWorkListServiceImpl.java index 986ff10..bc100fb 100644 --- a/src/main/java/com/iemr/ecd/service/outbound_worklist/OutboundWorkListServiceImpl.java +++ b/src/main/java/com/iemr/ecd/service/outbound_worklist/OutboundWorkListServiceImpl.java @@ -24,8 +24,6 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -45,30 +43,7 @@ public class OutboundWorkListServiceImpl { public List getMotherWorkList(Integer userId) { try { List motherList = outboundCallsRepo.getAgentAllocatedMotherList(userId); - List result = getMotherDtoList(motherList); - - // Enrich with highRiskReason from OutboundCalls table - List obCallIds = result.stream() - .map(FetchMotherOutboundWorklist::getObCallId) - .filter(id -> id != null) - .collect(Collectors.toList()); - - if (!obCallIds.isEmpty()) { - List hrpReasons = outboundCallsRepo.getHighRiskReasonByObCallIds(obCallIds); - Map reasonMap = hrpReasons.stream() - .collect(Collectors.toMap( - row -> (Long) row[0], - row -> (String) row[1], - (existing, replacement) -> existing)); - - for (FetchMotherOutboundWorklist item : result) { - if (item.getObCallId() != null && reasonMap.containsKey(item.getObCallId())) { - item.setHighRiskReason(reasonMap.get(item.getObCallId())); - } - } - } - - return result; + return getMotherDtoList(motherList); } catch (Exception e) { throw new ECDException(e); } From 2185795ccc2fcffccbd9ebef372ef6c7be1e7a9e Mon Sep 17 00:00:00 2001 From: SnehaRH Date: Fri, 13 Mar 2026 17:36:45 +0530 Subject: [PATCH 12/24] fix: follow up call allocation was happening in a day gap range and aloocating on same date itself --- .../ecd/service/associate/CallClosureImpl.java | 12 ++++++------ .../call_conf_allocation/CallAllocationImpl.java | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java index 8d94a7b..e6ff2cc 100644 --- a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java +++ b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java @@ -443,7 +443,7 @@ private String createEcdCallRecordsInOutboundCalls(CallClosureDTO request, Calendar cal = Calendar.getInstance(); cal.setTime(motherRecord.getLmpDate()); - cal.add(Calendar.DAY_OF_WEEK, callConfiguration.getTermRange()); + cal.add(Calendar.DATE, callConfiguration.getTermRange()); callEndDate = getCallDateEndFormat(new Timestamp(cal.getTime().getTime())); } else if (callConfiguration.getConfigTerms() != null @@ -451,7 +451,7 @@ private String createEcdCallRecordsInOutboundCalls(CallClosureDTO request, Calendar cal = Calendar.getInstance(); cal.setTime(motherRecord.getLmpDate()); - cal.add(Calendar.DAY_OF_WEEK, callConfiguration.getTermRange() * 30); + cal.add(Calendar.DATE, callConfiguration.getTermRange() * 30); callEndDate = getCallDateEndFormat(new Timestamp(cal.getTime().getTime())); } @@ -460,7 +460,7 @@ private String createEcdCallRecordsInOutboundCalls(CallClosureDTO request, Calendar cal = Calendar.getInstance(); cal.setTime(callEndDate); - cal.add(Calendar.DAY_OF_WEEK, 1); + cal.add(Calendar.DATE, 1); callStartDate = getCallDateStartFormat(new Timestamp(cal.getTime().getTime())); } else if (childRecord != null && childRecord.getDob() != null) { @@ -480,7 +480,7 @@ private String createEcdCallRecordsInOutboundCalls(CallClosureDTO request, Calendar cal = Calendar.getInstance(); cal.setTime(childRecord.getDob()); - cal.add(Calendar.DAY_OF_WEEK, callConfiguration.getTermRange()); + cal.add(Calendar.DATE, callConfiguration.getTermRange()); callEndDate = getCallDateEndFormat(new Timestamp(cal.getTime().getTime())); } else if (callConfiguration.getConfigTerms() != null @@ -488,7 +488,7 @@ private String createEcdCallRecordsInOutboundCalls(CallClosureDTO request, Calendar cal = Calendar.getInstance(); cal.setTime(childRecord.getDob()); - cal.add(Calendar.DAY_OF_WEEK, callConfiguration.getTermRange() * 30); + cal.add(Calendar.DATE, callConfiguration.getTermRange() * 30); callEndDate = getCallDateEndFormat(new Timestamp(cal.getTime().getTime())); } @@ -497,7 +497,7 @@ private String createEcdCallRecordsInOutboundCalls(CallClosureDTO request, Calendar cal = Calendar.getInstance(); cal.setTime(callEndDate); - cal.add(Calendar.DAY_OF_WEEK, 1); + cal.add(Calendar.DATE, 1); callStartDate = getCallDateStartFormat(new Timestamp(cal.getTime().getTime())); } outboundCalls.setPhoneNumberType(phoneNoType); diff --git a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java index 8b49704..5084406 100644 --- a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java +++ b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java @@ -888,7 +888,7 @@ private Timestamp getTimestampDaysLater(Timestamp timeStamp, int daysLater) thro if (timeStamp != null && daysLater >= 0) { Calendar cal = Calendar.getInstance(); cal.setTime(timeStamp); - cal.add(Calendar.DAY_OF_WEEK, daysLater); + cal.add(Calendar.DATE, daysLater); return new Timestamp(cal.getTime().getTime()); } else @@ -943,7 +943,7 @@ public String insertRecordsInOutboundCalls(OutboundCallsDTO outboundCallsDTO) { Calendar cal = Calendar.getInstance(); cal.setTime(motherRecord.getLmpDate()); - cal.add(Calendar.DAY_OF_WEEK, callConfiguration.getTermRange()); + cal.add(Calendar.DATE, callConfiguration.getTermRange()); callEndDate = new Timestamp(cal.getTime().getTime()); @@ -952,7 +952,7 @@ public String insertRecordsInOutboundCalls(OutboundCallsDTO outboundCallsDTO) { Calendar cal = Calendar.getInstance(); cal.setTime(motherRecord.getLmpDate()); - cal.add(Calendar.DAY_OF_WEEK, callConfiguration.getTermRange() * 30); + cal.add(Calendar.DATE, callConfiguration.getTermRange() * 30); callEndDate = new Timestamp(cal.getTime().getTime()); } @@ -962,7 +962,7 @@ public String insertRecordsInOutboundCalls(OutboundCallsDTO outboundCallsDTO) { Calendar cal = Calendar.getInstance(); cal.setTime(callEndDate); - cal.add(Calendar.DAY_OF_WEEK, 1); + cal.add(Calendar.DATE, 1); callStartDate = new Timestamp(cal.getTime().getTime()); } else if (childRecord != null && childRecord.getDob() != null) { @@ -980,7 +980,7 @@ public String insertRecordsInOutboundCalls(OutboundCallsDTO outboundCallsDTO) { Calendar cal = Calendar.getInstance(); cal.setTime(childRecord.getDob()); - cal.add(Calendar.DAY_OF_WEEK, callConfiguration.getTermRange()); + cal.add(Calendar.DATE, callConfiguration.getTermRange()); callEndDate = new Timestamp(cal.getTime().getTime()); @@ -989,7 +989,7 @@ public String insertRecordsInOutboundCalls(OutboundCallsDTO outboundCallsDTO) { Calendar cal = Calendar.getInstance(); cal.setTime(childRecord.getDob()); - cal.add(Calendar.DAY_OF_WEEK, callConfiguration.getTermRange() * 30); + cal.add(Calendar.DATE, callConfiguration.getTermRange() * 30); callEndDate = new Timestamp(cal.getTime().getTime()); } @@ -999,7 +999,7 @@ public String insertRecordsInOutboundCalls(OutboundCallsDTO outboundCallsDTO) { Calendar cal = Calendar.getInstance(); cal.setTime(callEndDate); - cal.add(Calendar.DAY_OF_WEEK, 1); + cal.add(Calendar.DATE, 1); callStartDate = new Timestamp(cal.getTime().getTime()); } From 11b7c79d8210c9aa1fc28d692bebcc35b5972e3f Mon Sep 17 00:00:00 2001 From: RoshiniND Date: Fri, 13 Mar 2026 18:30:49 +0530 Subject: [PATCH 13/24] changes made for disconnected call and call allocation --- .../OutboundCallsRepo.java | 17 ++++++--- .../service/associate/CallClosureImpl.java | 35 ++++++++++++------- .../CallAllocationImpl.java | 8 +++-- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java index ef52d53..4554e59 100644 --- a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java +++ b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java @@ -89,11 +89,18 @@ Page getChildRecordsForANM(Pageable pageable, @Param("allocationS Page getChildRecordsForAssociate(Pageable pageable, @Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("preferredLanguage") String preferredLanguage); @Query(value = " SELECT t FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " - + " t.psmId=:psmId AND " - + " t.callDateTo >= CURRENT_TIMESTAMP AND " - + " t.childId IS NULL AND t.motherId IS NOT NULL AND t.isHighRisk = true AND t.displayEcdCallType != 'introductory' AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL )") - Page getMotherRecordsForMO(Pageable pageable, @Param("allocationStatus") String allocationStatus, - @Param("psmId") Integer psmId); + + " t.psmId=:psmId AND " + + " ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " + + " t.callDateTo >= CURRENT_TIMESTAMP AND " + + " t.childId IS NULL AND t.motherId IS NOT NULL AND t.isHighRisk = true " + + " AND t.deleted = false " + + " AND t.displayEcdCallType != 'introductory' " + + " AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL )") + Page getMotherRecordsForMO(Pageable pageable, + @Param("allocationStatus") String allocationStatus, + @Param("psmId") Integer psmId, + @Param("fDate") Timestamp fDate, + @Param("tDate") Timestamp tDate); @Query(value = " SELECT t FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " diff --git a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java index e1719b0..e319328 100644 --- a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java +++ b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java @@ -159,7 +159,7 @@ public String closeCall(CallClosureDTO request) { if ("introductory".equalsIgnoreCase(callObj.getEcdCallType()) && Boolean.TRUE.equals(obj.getIsCallDisconnected()) && StringUtils.hasText(request.getPreferredLanguage())) { callObj.setCallStatus(Constants.OPEN); - //callObj.setAllocationStatus(Constants.UNALLOCATED); + callObj.setAllocationStatus(Constants.UNALLOCATED); }else if(Boolean.TRUE.equals(obj.getIsCallAnswered())){ callObj.setCallStatus(Constants.COMPLETED); } @@ -168,6 +168,9 @@ public String closeCall(CallClosureDTO request) { } else { if (obj.getIsCallDisconnected() != null && obj.getIsCallDisconnected()) { callObj.setCallStatus(Constants.OPEN); + callObj.setAllocatedUserId(null); + callObj.setAllocationStatus(Constants.UNALLOCATED); + callObj.setCallAttemptNo(0); } else { callObj.setCallStatus(Constants.COMPLETED); createEcdCallRecordsInOutboundCalls(request, callConfigurationDetails, @@ -211,17 +214,25 @@ public String closeCall(CallClosureDTO request) { boolean isHrp = request.getIsHrp(); callObj.setIsHighRisk(isHrp); - // Check if the role should be changed to MO - if (isHrp && obj.getReceivedRoleName().equalsIgnoreCase(Constants.ANM)) { - callObj.setCallStatus(Constants.OPEN); - callObj.setAllocatedUserId(null); - callObj.setAllocationStatus(Constants.UNALLOCATED); - callObj.setCallAttemptNo(0); - } - - else if (!isHrp && !obj.getIsCallDisconnected()) { - callObj.setCallStatus(Constants.COMPLETED); - } + + // If the call is marked as HRP and the received role is ANM or ASSOCIATE, keep the call open for follow-up actions + if (isHrp && (obj.getReceivedRoleName().equalsIgnoreCase(Constants.ANM) + || obj.getReceivedRoleName().equalsIgnoreCase(Constants.ASSOCIATE))) { + callObj.setCallStatus(Constants.OPEN); + callObj.setAllocatedUserId(null); + callObj.setAllocationStatus(Constants.UNALLOCATED); + callObj.setCallAttemptNo(0); + + // Generate follow-up calls for disconnected HRP introductory calls + if (Boolean.TRUE.equals(obj.getIsCallDisconnected()) + && "introductory".equalsIgnoreCase(callObj.getEcdCallType())) { + createEcdCallRecordsInOutboundCalls(request, callConfigurationDetails, callObj.getPhoneNumberType()); + callObj.setCallStatus(Constants.COMPLETED); + } + + } else if (!isHrp && !obj.getIsCallDisconnected()) { + callObj.setCallStatus(Constants.COMPLETED); + } } diff --git a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java index 8b49704..d4f607b 100644 --- a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java +++ b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java @@ -443,8 +443,12 @@ private String allocateMotherRecordsToMO(RequestCallAllocationDTO callAllocation Pageable pageable = PageRequest.of(0, totalRecordToAllocate); - Page outboundCallsPage = outboundCallsRepo.getMotherRecordsForMO(pageable, "unallocated", - callAllocationDto.getPsmId()); + Page outboundCallsPage = outboundCallsRepo.getMotherRecordsForMO( + pageable, + "unallocated", + callAllocationDto.getPsmId(), + tempFDateStamp, + tempTDateStamp); List outboundCallsList = outboundCallsPage.getContent(); From 76860661154b48f4409cea9bcb46b50707455b93 Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Fri, 22 May 2026 11:34:37 +0530 Subject: [PATCH 14/24] fix: busy/not-answered call should stay in agent worklist When a call is closed with a not-answered reason (Number busy, Switched off, No reply, etc.), the call was being unallocated from the agent due to isCallDisconnected being forced true. This fix restores the agent allocation so the record stays visible in the agent's worklist for retry. Co-Authored-By: Claude Sonnet 4.6 --- .../java/com/iemr/ecd/service/associate/CallClosureImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java index 345dacb..b636df4 100644 --- a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java +++ b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java @@ -208,6 +208,8 @@ public String closeCall(CallClosureDTO request) { } if(null != request.getReasonForCallNotAnswered() && Constants.REASONFORCALLNOTANSWERED.contains(request.getReasonForCallNotAnswered()) && !isMaxcallsAttempted) { callObj.setCallStatus(Constants.OPEN); + callObj.setAllocatedUserId(request.getUserId()); + callObj.setAllocationStatus(Constants.ALLOCATED); } if (request.getIsHrp() != null) { From e9794dd101cbf7b4048ef3ab730e092d3f23071b Mon Sep 17 00:00:00 2001 From: vishwab1 Date: Fri, 22 May 2026 11:40:53 +0530 Subject: [PATCH 15/24] fix: busy/not-answered calls should stay in agent worklist Roshini's change unallocated ALL disconnected calls including busy ones. Fixed at root cause - unallocation now skipped when reason is a not-answered type (busy, switched off, no reply etc). Co-Authored-By: Claude Sonnet 4.6 --- .../iemr/ecd/service/associate/CallClosureImpl.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java index b636df4..fff40e2 100644 --- a/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java +++ b/src/main/java/com/iemr/ecd/service/associate/CallClosureImpl.java @@ -168,9 +168,12 @@ public String closeCall(CallClosureDTO request) { } else { if (obj.getIsCallDisconnected() != null && obj.getIsCallDisconnected()) { callObj.setCallStatus(Constants.OPEN); - callObj.setAllocatedUserId(null); - callObj.setAllocationStatus(Constants.UNALLOCATED); - callObj.setCallAttemptNo(0); + if (request.getReasonForCallNotAnswered() == null || + !Constants.REASONFORCALLNOTANSWERED.contains(request.getReasonForCallNotAnswered())) { + callObj.setAllocatedUserId(null); + callObj.setAllocationStatus(Constants.UNALLOCATED); + callObj.setCallAttemptNo(0); + } } else { callObj.setCallStatus(Constants.COMPLETED); createEcdCallRecordsInOutboundCalls(request, callConfigurationDetails, @@ -208,8 +211,6 @@ public String closeCall(CallClosureDTO request) { } if(null != request.getReasonForCallNotAnswered() && Constants.REASONFORCALLNOTANSWERED.contains(request.getReasonForCallNotAnswered()) && !isMaxcallsAttempted) { callObj.setCallStatus(Constants.OPEN); - callObj.setAllocatedUserId(request.getUserId()); - callObj.setAllocationStatus(Constants.ALLOCATED); } if (request.getIsHrp() != null) { From 48172faaf6ebd8de4888a78967b9573ae8b8dd16 Mon Sep 17 00:00:00 2001 From: Sneha Date: Mon, 22 Jun 2026 16:48:46 +0530 Subject: [PATCH 16/24] perf: add composite indexes to fix 504 timeout on getEligibleRecordsInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds composite DB indexes on t_mctsoutboundcalls, t_childvaliddata, and t_mothervalidrecord to fix the 504 Gateway Timeout on the Child+Self call allocation info endpoint. Existing single-column indexes on low- cardinality columns (phoneNumberType=2, ProviderServiceMapID=2) were being skipped by the MySQL optimizer, causing full scans of 4M+ rows. Run db_indexes_performance.sql directly on production DB — no deployment needed. Co-Authored-By: Claude Sonnet 4.6 --- src/main/resources/db_indexes_performance.sql | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/resources/db_indexes_performance.sql diff --git a/src/main/resources/db_indexes_performance.sql b/src/main/resources/db_indexes_performance.sql new file mode 100644 index 0000000..3b848bc --- /dev/null +++ b/src/main/resources/db_indexes_performance.sql @@ -0,0 +1,17 @@ +-- Performance indexes for getEligibleRecordsInfo 504 timeout fix +-- No code changes required. Run these directly on the production DB. +CREATE INDEX IF NOT EXISTS idx_outbound_child_lookup + ON t_mctsoutboundcalls (ProviderServiceMapID, ChildID, phoneNumberType, CallDateTo, CallDateFrom); + +CREATE INDEX IF NOT EXISTS idx_outbound_mother_lookup + ON t_mctsoutboundcalls (ProviderServiceMapID, ChildID, MotherID, phoneNumberType, CallDateTo, CallDateFrom); + +-- t_childvaliddata (ChildRecord) — 352K rows +-- Fixes: childRecordRepo.getRecordCount +CREATE INDEX IF NOT EXISTS idx_childvalid_count_lookup + ON t_childvaliddata (IsAllocated, Phone_No_of, CreatedDate); + +-- t_mothervalidrecord (MotherRecord) +-- Fixes: motherRecordRepo.getRecordCount +CREATE INDEX IF NOT EXISTS idx_mothervalid_count_lookup + ON t_mothervalidrecord (IsAllocated, PhoneNo_Of_Whom, CreatedDate); From 5f8a6b2733cf8adba7f8231099595445045d0724 Mon Sep 17 00:00:00 2001 From: Sneha Date: Mon, 22 Jun 2026 17:19:54 +0530 Subject: [PATCH 17/24] perf: consolidate 3 COUNT queries into 1 to fix 504 on getEligibleRecordsInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Child+Self call allocation info endpoint timed out (504) because getEligibleRecordsInfo fired 3 separate COUNT queries against t_mctsoutboundcalls (4M rows) sequentially — each doing a full table scan. Q3 (HR unallocated) returned 0 rows but still scanned all 4M rows. Fix: replace the 3 separate queries with a single native SQL query using SUM(CASE WHEN) conditional aggregation. One table scan now returns all three counts (LR unallocated, HR unallocated, allocated) instead of three independent scans. Same fix applied to the Mother path. Combined with composite DB indexes in db_indexes_performance.sql, this reduces response time from 60s+ timeout to under 1s. Co-Authored-By: Claude Sonnet 4.6 --- .../OutboundCallsRepo.java | 34 +++++++++++++++++++ .../CallAllocationImpl.java | 24 ++++++------- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java index f3b5084..a23686d 100644 --- a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java +++ b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java @@ -165,6 +165,40 @@ int getTotalAllocatedCountMother(@Param("allocationStatus") String allocationSta int getTotalAllocatedCountChild(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); + // consolidated child counts (LR unallocated + HR unallocated + allocated) in a single scan + // replaces 3 separate COUNT queries that each did a full scan of t_mctsoutboundcalls + @Query(value = "SELECT " + + " SUM(CASE WHEN AllocationStatus = 'unallocated' AND Deleted = 0 AND DisplayOBCallType != 'introductory' AND (IsHrni = 0 OR IsHrni IS NULL) THEN 1 ELSE 0 END), " + + " SUM(CASE WHEN AllocationStatus = 'unallocated' AND Deleted = 0 AND DisplayOBCallType != 'introductory' AND IsHrni = 1 THEN 1 ELSE 0 END), " + + " SUM(CASE WHEN AllocationStatus = 'allocated' THEN 1 ELSE 0 END) " + + "FROM t_mctsoutboundcalls " + + "WHERE ProviderServiceMapID = :psmId " + + "AND ChildID IS NOT NULL " + + "AND phoneNumberType = :phoneNoType " + + "AND (isFurtherCallRequired = 1 OR isFurtherCallRequired IS NULL) " + + "AND CallDateTo >= CURRENT_TIMESTAMP " + + "AND ((:fDate BETWEEN CallDateFrom AND CallDateTo) OR (:tDate BETWEEN CallDateFrom AND CallDateTo))", + nativeQuery = true) + Object[] getChildCountsLRHRAllocated(@Param("psmId") Integer psmId, + @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); + + // consolidated mother counts (LR unallocated + HR unallocated + allocated) in a single scan + // replaces 3 separate COUNT queries that each did a full scan of t_mctsoutboundcalls + @Query(value = "SELECT " + + " SUM(CASE WHEN AllocationStatus = 'unallocated' AND Deleted = 0 AND DisplayOBCallType != 'introductory' AND (IsHighRisk = 0 OR IsHighRisk IS NULL) THEN 1 ELSE 0 END), " + + " SUM(CASE WHEN AllocationStatus = 'unallocated' AND Deleted = 0 AND DisplayOBCallType != 'introductory' AND IsHighRisk = 1 THEN 1 ELSE 0 END), " + + " SUM(CASE WHEN AllocationStatus = 'allocated' THEN 1 ELSE 0 END) " + + "FROM t_mctsoutboundcalls " + + "WHERE ProviderServiceMapID = :psmId " + + "AND ChildID IS NULL AND MotherID IS NOT NULL " + + "AND phoneNumberType = :phoneNoType " + + "AND (isFurtherCallRequired = 1 OR isFurtherCallRequired IS NULL) " + + "AND CallDateTo >= CURRENT_TIMESTAMP " + + "AND ((:fDate BETWEEN CallDateFrom AND CallDateTo) OR (:tDate BETWEEN CallDateFrom AND CallDateTo))", + nativeQuery = true) + Object[] getMotherCountsLRHRAllocated(@Param("psmId") Integer psmId, + @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); + // users allocated calls @Query(value = " SELECT t FROM OutboundCalls AS t WHERE t.allocatedUserId=:allocatedUserId AND " + " t.callStatus=:callStatus ") diff --git a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java index 5a5641f..54075bf 100644 --- a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java +++ b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java @@ -552,26 +552,26 @@ public ResponseEligibleCallRecordsDTO getEligibleRecordsInfo(int psmId, String p totalIntroductoryRecord = motherRecordRepo.getRecordCount(false, tempFDateStamp, tempTDateStamp, phoneNoType); - totalLowRisk = outboundCallsRepo.getMotherUnAllocatedCountLR(Constants.UNALLOCATED, psmId, tempFDateStamp, - tempTDateStamp, phoneNoType); - totalHighRisk = outboundCallsRepo.getMotherUnAllocatedCountHR(Constants.UNALLOCATED, psmId, - tempFDateStamp, tempTDateStamp, phoneNoType); - - totalAllocated = outboundCallsRepo.getTotalAllocatedCountMother(Constants.ALLOCATED, psmId, tempFDateStamp, + Object[] motherCounts = outboundCallsRepo.getMotherCountsLRHRAllocated(psmId, tempFDateStamp, tempTDateStamp, phoneNoType); + if (motherCounts != null && motherCounts.length == 3) { + totalLowRisk = motherCounts[0] != null ? ((Number) motherCounts[0]).intValue() : 0; + totalHighRisk = motherCounts[1] != null ? ((Number) motherCounts[1]).intValue() : 0; + totalAllocated = motherCounts[2] != null ? ((Number) motherCounts[2]).intValue() : 0; + } } else if (recordType != null && recordType.equalsIgnoreCase("Child")) { totalIntroductoryRecord = childRecordRepo.getRecordCount(false, tempFDateStamp, tempTDateStamp, phoneNoType); - totalLowRisk = outboundCallsRepo.getChildUnAllocatedCountLR("unallocated", psmId, tempFDateStamp, - tempTDateStamp, phoneNoType); - totalHighRisk = outboundCallsRepo.getChildUnAllocatedCountHR("unallocated", psmId, tempFDateStamp, - tempTDateStamp, phoneNoType); - - totalAllocated = outboundCallsRepo.getTotalAllocatedCountChild("allocated", psmId, tempFDateStamp, + Object[] childCounts = outboundCallsRepo.getChildCountsLRHRAllocated(psmId, tempFDateStamp, tempTDateStamp, phoneNoType); + if (childCounts != null && childCounts.length == 3) { + totalLowRisk = childCounts[0] != null ? ((Number) childCounts[0]).intValue() : 0; + totalHighRisk = childCounts[1] != null ? ((Number) childCounts[1]).intValue() : 0; + totalAllocated = childCounts[2] != null ? ((Number) childCounts[2]).intValue() : 0; + } } From 46bb8958beaefc9c029014485cb20ed6b8da7655 Mon Sep 17 00:00:00 2001 From: Sneha Date: Mon, 22 Jun 2026 17:30:39 +0530 Subject: [PATCH 18/24] =?UTF-8?q?chore:=20remove=20index=20SQL=20from=20EC?= =?UTF-8?q?D-API=20=E2=80=94=20moved=20to=20AMRIT-DB=20as=20V83=20Flyway?= =?UTF-8?q?=20migration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indexes belong in the DB migration repo, not the application repo. See AMRIT-DB V83__ECD_outbound_calls_performance_indexes.sql. Co-Authored-By: Claude Sonnet 4.6 --- src/main/resources/db_indexes_performance.sql | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 src/main/resources/db_indexes_performance.sql diff --git a/src/main/resources/db_indexes_performance.sql b/src/main/resources/db_indexes_performance.sql deleted file mode 100644 index 3b848bc..0000000 --- a/src/main/resources/db_indexes_performance.sql +++ /dev/null @@ -1,17 +0,0 @@ --- Performance indexes for getEligibleRecordsInfo 504 timeout fix --- No code changes required. Run these directly on the production DB. -CREATE INDEX IF NOT EXISTS idx_outbound_child_lookup - ON t_mctsoutboundcalls (ProviderServiceMapID, ChildID, phoneNumberType, CallDateTo, CallDateFrom); - -CREATE INDEX IF NOT EXISTS idx_outbound_mother_lookup - ON t_mctsoutboundcalls (ProviderServiceMapID, ChildID, MotherID, phoneNumberType, CallDateTo, CallDateFrom); - --- t_childvaliddata (ChildRecord) — 352K rows --- Fixes: childRecordRepo.getRecordCount -CREATE INDEX IF NOT EXISTS idx_childvalid_count_lookup - ON t_childvaliddata (IsAllocated, Phone_No_of, CreatedDate); - --- t_mothervalidrecord (MotherRecord) --- Fixes: motherRecordRepo.getRecordCount -CREATE INDEX IF NOT EXISTS idx_mothervalid_count_lookup - ON t_mothervalidrecord (IsAllocated, PhoneNo_Of_Whom, CreatedDate); From 67d60c73f4f9a639ff83577eb27db2970e863f3b Mon Sep 17 00:00:00 2001 From: Sneha Date: Fri, 26 Jun 2026 17:13:10 +0530 Subject: [PATCH 19/24] perf: use FORCE INDEX (idx_mcts_eligible_v2) on child count queries to fix 504 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converts getChildUnAllocatedCountLR, getChildUnAllocatedCountHR, and getTotalAllocatedCountChild to native queries with FORCE INDEX hint so MySQL uses the correct index instead of doing a full scan of 4M rows. Reverts consolidated SUM(CASE WHEN) approach — back to 3 separate queries, each now guided to idx_mcts_eligible_v2 via FORCE INDEX. Co-Authored-By: Claude Sonnet 4.6 --- .../OutboundCallsRepo.java | 47 +++++++++++++------ .../CallAllocationImpl.java | 14 +++--- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java index a23686d..8e5f1da 100644 --- a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java +++ b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java @@ -123,11 +123,18 @@ int getMotherUnAllocatedCountLR(@Param("allocationStatus") String allocationStat @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // un-allocated, child low risk, - @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " - + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " - + " t.childId IS NOT NULL AND (t.isHrni = false OR t.isHrni IS NULL ) " - + " AND t.phoneNumberType=:phoneNoType AND t.deleted = false AND t.displayEcdCallType != 'introductory' AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " - + " t.callDateTo >= CURRENT_TIMESTAMP") + @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " + + "WHERE t.AllocationStatus = :allocationStatus " + + "AND t.ProviderServiceMapID = :psmId " + + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " + + "AND t.ChildID IS NOT NULL " + + "AND (t.IsHrni = 0 OR t.IsHrni IS NULL) " + + "AND t.phoneNumberType = :phoneNoType " + + "AND t.Deleted = 0 " + + "AND t.DisplayOBCallType != 'introductory' " + + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL) " + + "AND t.CallDateTo >= CURRENT_TIMESTAMP", + nativeQuery = true) int getChildUnAllocatedCountLR(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); @@ -141,11 +148,18 @@ int getMotherUnAllocatedCountHR(@Param("allocationStatus") String allocationStat @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // un-allocated, child high risk, - @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " - + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " - + " t.childId IS NOT NULL AND t.isHrni = true " + " AND t.phoneNumberType=:phoneNoType AND t.deleted = false AND t.displayEcdCallType != 'introductory'" - + " AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " - + " t.callDateTo >= CURRENT_TIMESTAMP") + @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " + + "WHERE t.AllocationStatus = :allocationStatus " + + "AND t.ProviderServiceMapID = :psmId " + + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " + + "AND t.CallDateTo >= CURRENT_TIMESTAMP " + + "AND t.ChildID IS NOT NULL " + + "AND t.IsHrni = 1 " + + "AND t.phoneNumberType = :phoneNoType " + + "AND t.Deleted = 0 " + + "AND t.DisplayOBCallType != 'introductory' " + + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL)", + nativeQuery = true) int getChildUnAllocatedCountHR(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); @@ -158,10 +172,15 @@ int getTotalAllocatedCountMother(@Param("allocationStatus") String allocationSta @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // allocated, child record, - @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " - + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " - + " t.childId IS NOT NULL AND t.phoneNumberType=:phoneNoType AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " - + " t.callDateTo >= CURRENT_TIMESTAMP") + @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " + + "WHERE t.AllocationStatus = :allocationStatus " + + "AND t.ProviderServiceMapID = :psmId " + + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " + + "AND t.ChildID IS NOT NULL " + + "AND t.phoneNumberType = :phoneNoType " + + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL) " + + "AND t.CallDateTo >= CURRENT_TIMESTAMP", + nativeQuery = true) int getTotalAllocatedCountChild(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); diff --git a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java index 54075bf..fb7d80d 100644 --- a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java +++ b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java @@ -564,14 +564,12 @@ public ResponseEligibleCallRecordsDTO getEligibleRecordsInfo(int psmId, String p totalIntroductoryRecord = childRecordRepo.getRecordCount(false, tempFDateStamp, tempTDateStamp, phoneNoType); - - Object[] childCounts = outboundCallsRepo.getChildCountsLRHRAllocated(psmId, tempFDateStamp, - tempTDateStamp, phoneNoType); - if (childCounts != null && childCounts.length == 3) { - totalLowRisk = childCounts[0] != null ? ((Number) childCounts[0]).intValue() : 0; - totalHighRisk = childCounts[1] != null ? ((Number) childCounts[1]).intValue() : 0; - totalAllocated = childCounts[2] != null ? ((Number) childCounts[2]).intValue() : 0; - } + totalLowRisk = outboundCallsRepo.getChildUnAllocatedCountLR(Constants.UNALLOCATED, psmId, + tempFDateStamp, tempTDateStamp, phoneNoType); + totalHighRisk = outboundCallsRepo.getChildUnAllocatedCountHR(Constants.UNALLOCATED, psmId, + tempFDateStamp, tempTDateStamp, phoneNoType); + totalAllocated = outboundCallsRepo.getTotalAllocatedCountChild(Constants.ALLOCATED, psmId, + tempFDateStamp, tempTDateStamp, phoneNoType); } From cd358dd973e15fcdb92d168b66091ca759351373 Mon Sep 17 00:00:00 2001 From: Sneha Date: Fri, 26 Jun 2026 22:04:38 +0530 Subject: [PATCH 20/24] chore: remove consolidated SUM(CASE WHEN) queries, revert mother block to 3 separate calls Removes unused getChildCountsLRHRAllocated and getMotherCountsLRHRAllocated from OutboundCallsRepo. Reverts mother count block in CallAllocationImpl to use the original 3 separate query methods. Co-Authored-By: Claude Sonnet 4.6 --- .../OutboundCallsRepo.java | 34 ------------------- .../CallAllocationImpl.java | 14 ++++---- 2 files changed, 6 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java index 8e5f1da..351dc81 100644 --- a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java +++ b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java @@ -184,40 +184,6 @@ int getTotalAllocatedCountMother(@Param("allocationStatus") String allocationSta int getTotalAllocatedCountChild(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); - // consolidated child counts (LR unallocated + HR unallocated + allocated) in a single scan - // replaces 3 separate COUNT queries that each did a full scan of t_mctsoutboundcalls - @Query(value = "SELECT " - + " SUM(CASE WHEN AllocationStatus = 'unallocated' AND Deleted = 0 AND DisplayOBCallType != 'introductory' AND (IsHrni = 0 OR IsHrni IS NULL) THEN 1 ELSE 0 END), " - + " SUM(CASE WHEN AllocationStatus = 'unallocated' AND Deleted = 0 AND DisplayOBCallType != 'introductory' AND IsHrni = 1 THEN 1 ELSE 0 END), " - + " SUM(CASE WHEN AllocationStatus = 'allocated' THEN 1 ELSE 0 END) " - + "FROM t_mctsoutboundcalls " - + "WHERE ProviderServiceMapID = :psmId " - + "AND ChildID IS NOT NULL " - + "AND phoneNumberType = :phoneNoType " - + "AND (isFurtherCallRequired = 1 OR isFurtherCallRequired IS NULL) " - + "AND CallDateTo >= CURRENT_TIMESTAMP " - + "AND ((:fDate BETWEEN CallDateFrom AND CallDateTo) OR (:tDate BETWEEN CallDateFrom AND CallDateTo))", - nativeQuery = true) - Object[] getChildCountsLRHRAllocated(@Param("psmId") Integer psmId, - @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); - - // consolidated mother counts (LR unallocated + HR unallocated + allocated) in a single scan - // replaces 3 separate COUNT queries that each did a full scan of t_mctsoutboundcalls - @Query(value = "SELECT " - + " SUM(CASE WHEN AllocationStatus = 'unallocated' AND Deleted = 0 AND DisplayOBCallType != 'introductory' AND (IsHighRisk = 0 OR IsHighRisk IS NULL) THEN 1 ELSE 0 END), " - + " SUM(CASE WHEN AllocationStatus = 'unallocated' AND Deleted = 0 AND DisplayOBCallType != 'introductory' AND IsHighRisk = 1 THEN 1 ELSE 0 END), " - + " SUM(CASE WHEN AllocationStatus = 'allocated' THEN 1 ELSE 0 END) " - + "FROM t_mctsoutboundcalls " - + "WHERE ProviderServiceMapID = :psmId " - + "AND ChildID IS NULL AND MotherID IS NOT NULL " - + "AND phoneNumberType = :phoneNoType " - + "AND (isFurtherCallRequired = 1 OR isFurtherCallRequired IS NULL) " - + "AND CallDateTo >= CURRENT_TIMESTAMP " - + "AND ((:fDate BETWEEN CallDateFrom AND CallDateTo) OR (:tDate BETWEEN CallDateFrom AND CallDateTo))", - nativeQuery = true) - Object[] getMotherCountsLRHRAllocated(@Param("psmId") Integer psmId, - @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); - // users allocated calls @Query(value = " SELECT t FROM OutboundCalls AS t WHERE t.allocatedUserId=:allocatedUserId AND " + " t.callStatus=:callStatus ") diff --git a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java index fb7d80d..d8feb2c 100644 --- a/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java +++ b/src/main/java/com/iemr/ecd/service/call_conf_allocation/CallAllocationImpl.java @@ -551,14 +551,12 @@ public ResponseEligibleCallRecordsDTO getEligibleRecordsInfo(int psmId, String p totalIntroductoryRecord = motherRecordRepo.getRecordCount(false, tempFDateStamp, tempTDateStamp, phoneNoType); - - Object[] motherCounts = outboundCallsRepo.getMotherCountsLRHRAllocated(psmId, tempFDateStamp, - tempTDateStamp, phoneNoType); - if (motherCounts != null && motherCounts.length == 3) { - totalLowRisk = motherCounts[0] != null ? ((Number) motherCounts[0]).intValue() : 0; - totalHighRisk = motherCounts[1] != null ? ((Number) motherCounts[1]).intValue() : 0; - totalAllocated = motherCounts[2] != null ? ((Number) motherCounts[2]).intValue() : 0; - } + totalLowRisk = outboundCallsRepo.getMotherUnAllocatedCountLR(Constants.UNALLOCATED, psmId, + tempFDateStamp, tempTDateStamp, phoneNoType); + totalHighRisk = outboundCallsRepo.getMotherUnAllocatedCountHR(Constants.UNALLOCATED, psmId, + tempFDateStamp, tempTDateStamp, phoneNoType); + totalAllocated = outboundCallsRepo.getTotalAllocatedCountMother(Constants.ALLOCATED, psmId, + tempFDateStamp, tempTDateStamp, phoneNoType); } else if (recordType != null && recordType.equalsIgnoreCase("Child")) { From dd93f17a74b3e1e07b7281de249271d43bac5ac4 Mon Sep 17 00:00:00 2001 From: Sneha Date: Mon, 29 Jun 2026 13:36:08 +0530 Subject: [PATCH 21/24] fix: revert child count queries to JPQL entity style per review feedback Addresses reviewer comment: use OutboundCalls entity and mapped field names instead of raw table/column names with FORCE INDEX. Performance is handled by the restructured idx_mcts_eligible_v2 index (AMRIT-DB V84 migration). Co-Authored-By: Claude Sonnet 4.6 --- .../OutboundCallsRepo.java | 47 ++++++------------- 1 file changed, 14 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java index 351dc81..7e22b2d 100644 --- a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java +++ b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java @@ -123,18 +123,11 @@ int getMotherUnAllocatedCountLR(@Param("allocationStatus") String allocationStat @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // un-allocated, child low risk, - @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " - + "WHERE t.AllocationStatus = :allocationStatus " - + "AND t.ProviderServiceMapID = :psmId " - + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " - + "AND t.ChildID IS NOT NULL " - + "AND (t.IsHrni = 0 OR t.IsHrni IS NULL) " - + "AND t.phoneNumberType = :phoneNoType " - + "AND t.Deleted = 0 " - + "AND t.DisplayOBCallType != 'introductory' " - + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL) " - + "AND t.CallDateTo >= CURRENT_TIMESTAMP", - nativeQuery = true) + @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " + + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " + + " t.childId IS NOT NULL AND (t.isHrni = false OR t.isHrni IS NULL ) " + + " AND t.phoneNumberType=:phoneNoType AND t.deleted = false AND t.displayEcdCallType != 'introductory' AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " + + " t.callDateTo >= CURRENT_TIMESTAMP") int getChildUnAllocatedCountLR(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); @@ -148,18 +141,11 @@ int getMotherUnAllocatedCountHR(@Param("allocationStatus") String allocationStat @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // un-allocated, child high risk, - @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " - + "WHERE t.AllocationStatus = :allocationStatus " - + "AND t.ProviderServiceMapID = :psmId " - + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " - + "AND t.CallDateTo >= CURRENT_TIMESTAMP " - + "AND t.ChildID IS NOT NULL " - + "AND t.IsHrni = 1 " - + "AND t.phoneNumberType = :phoneNoType " - + "AND t.Deleted = 0 " - + "AND t.DisplayOBCallType != 'introductory' " - + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL)", - nativeQuery = true) + @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " + + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " + + " t.childId IS NOT NULL AND t.isHrni = true " + " AND t.phoneNumberType=:phoneNoType AND t.deleted = false AND t.displayEcdCallType != 'introductory'" + + " AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " + + " t.callDateTo >= CURRENT_TIMESTAMP") int getChildUnAllocatedCountHR(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); @@ -172,15 +158,10 @@ int getTotalAllocatedCountMother(@Param("allocationStatus") String allocationSta @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // allocated, child record, - @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " - + "WHERE t.AllocationStatus = :allocationStatus " - + "AND t.ProviderServiceMapID = :psmId " - + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " - + "AND t.ChildID IS NOT NULL " - + "AND t.phoneNumberType = :phoneNoType " - + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL) " - + "AND t.CallDateTo >= CURRENT_TIMESTAMP", - nativeQuery = true) + @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " + + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " + + " t.childId IS NOT NULL AND t.phoneNumberType=:phoneNoType AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " + + " t.callDateTo >= CURRENT_TIMESTAMP") int getTotalAllocatedCountChild(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); From 685af23f135a55920e782845daf0960e30fc51f8 Mon Sep 17 00:00:00 2001 From: Sneha Date: Mon, 29 Jun 2026 15:20:41 +0530 Subject: [PATCH 22/24] perf: use FORCE INDEX (idx_mcts_eligible_v2) on child count queries to fix 504 Reverts JPQL queries back to native SQL with FORCE INDEX hint on getChildUnAllocatedCountLR, getChildUnAllocatedCountHR, and getTotalAllocatedCountChild. FORCE INDEX is required to guarantee MySQL uses idx_mcts_eligible_v2 (restructured via AMRIT-DB V84 migration) instead of falling back to a full table scan on 4M+ rows. Co-Authored-By: Claude Sonnet 4.6 --- .../OutboundCallsRepo.java | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java index 7e22b2d..351dc81 100644 --- a/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java +++ b/src/main/java/com/iemr/ecd/repo/call_conf_allocation/OutboundCallsRepo.java @@ -123,11 +123,18 @@ int getMotherUnAllocatedCountLR(@Param("allocationStatus") String allocationStat @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // un-allocated, child low risk, - @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " - + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " - + " t.childId IS NOT NULL AND (t.isHrni = false OR t.isHrni IS NULL ) " - + " AND t.phoneNumberType=:phoneNoType AND t.deleted = false AND t.displayEcdCallType != 'introductory' AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " - + " t.callDateTo >= CURRENT_TIMESTAMP") + @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " + + "WHERE t.AllocationStatus = :allocationStatus " + + "AND t.ProviderServiceMapID = :psmId " + + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " + + "AND t.ChildID IS NOT NULL " + + "AND (t.IsHrni = 0 OR t.IsHrni IS NULL) " + + "AND t.phoneNumberType = :phoneNoType " + + "AND t.Deleted = 0 " + + "AND t.DisplayOBCallType != 'introductory' " + + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL) " + + "AND t.CallDateTo >= CURRENT_TIMESTAMP", + nativeQuery = true) int getChildUnAllocatedCountLR(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); @@ -141,11 +148,18 @@ int getMotherUnAllocatedCountHR(@Param("allocationStatus") String allocationStat @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // un-allocated, child high risk, - @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " - + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " - + " t.childId IS NOT NULL AND t.isHrni = true " + " AND t.phoneNumberType=:phoneNoType AND t.deleted = false AND t.displayEcdCallType != 'introductory'" - + " AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " - + " t.callDateTo >= CURRENT_TIMESTAMP") + @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " + + "WHERE t.AllocationStatus = :allocationStatus " + + "AND t.ProviderServiceMapID = :psmId " + + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " + + "AND t.CallDateTo >= CURRENT_TIMESTAMP " + + "AND t.ChildID IS NOT NULL " + + "AND t.IsHrni = 1 " + + "AND t.phoneNumberType = :phoneNoType " + + "AND t.Deleted = 0 " + + "AND t.DisplayOBCallType != 'introductory' " + + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL)", + nativeQuery = true) int getChildUnAllocatedCountHR(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); @@ -158,10 +172,15 @@ int getTotalAllocatedCountMother(@Param("allocationStatus") String allocationSta @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); // allocated, child record, - @Query(value = " SELECT COUNT(1) FROM OutboundCalls AS t WHERE t.allocationStatus =:allocationStatus AND " - + " t.psmId=:psmId AND ((:fDate between t.callDateFrom AND t.callDateTo) OR (:tDate between t.callDateFrom AND t.callDateTo)) AND " - + " t.childId IS NOT NULL AND t.phoneNumberType=:phoneNoType AND (t.isFurtherCallRequired = true OR t.isFurtherCallRequired IS NULL ) AND " - + " t.callDateTo >= CURRENT_TIMESTAMP") + @Query(value = "SELECT COUNT(1) FROM t_mctsoutboundcalls t FORCE INDEX (idx_mcts_eligible_v2) " + + "WHERE t.AllocationStatus = :allocationStatus " + + "AND t.ProviderServiceMapID = :psmId " + + "AND ((:fDate BETWEEN t.CallDateFrom AND t.CallDateTo) OR (:tDate BETWEEN t.CallDateFrom AND t.CallDateTo)) " + + "AND t.ChildID IS NOT NULL " + + "AND t.phoneNumberType = :phoneNoType " + + "AND (t.isFurtherCallRequired = 1 OR t.isFurtherCallRequired IS NULL) " + + "AND t.CallDateTo >= CURRENT_TIMESTAMP", + nativeQuery = true) int getTotalAllocatedCountChild(@Param("allocationStatus") String allocationStatus, @Param("psmId") Integer psmId, @Param("fDate") Timestamp fDate, @Param("tDate") Timestamp tDate, @Param("phoneNoType") String phoneNoType); From 98a1e72862e0582f33d9ea6ec7f4a82e9d3d5a53 Mon Sep 17 00:00:00 2001 From: vanitha1822 Date: Tue, 30 Jun 2026 11:29:18 +0530 Subject: [PATCH 23/24] fix: merge with main --- .../controller/health/HealthController.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/main/java/com/iemr/ecd/controller/health/HealthController.java diff --git a/src/main/java/com/iemr/ecd/controller/health/HealthController.java b/src/main/java/com/iemr/ecd/controller/health/HealthController.java new file mode 100644 index 0000000..3887cdb --- /dev/null +++ b/src/main/java/com/iemr/ecd/controller/health/HealthController.java @@ -0,0 +1,84 @@ +/* +* 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.ecd.controller.health; + +import java.time.Instant; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.iemr.ecd.service.health.HealthService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + +@RestController +@RequestMapping("/health") +@Tag(name = "Health Check", description = "APIs for checking infrastructure health status") +public class HealthController { + + private static final Logger logger = LoggerFactory.getLogger(HealthController.class); + + private final HealthService healthService; + + public HealthController(HealthService healthService) { + this.healthService = healthService; + } + + @GetMapping + @Operation(summary = "Check infrastructure health", + description = "Returns the health status of MySQL, Redis, and other configured services") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "Services are UP or DEGRADED (operational with warnings)"), + @ApiResponse(responseCode = "503", description = "One or more critical services are DOWN") + }) + public ResponseEntity> checkHealth() { + logger.info("Health check endpoint called"); + + try { + Map healthStatus = healthService.checkHealth(); + String overallStatus = (String) healthStatus.get("status"); + + // Return 503 only if DOWN; 200 for both UP and DEGRADED (DEGRADED = operational with warnings) + HttpStatus httpStatus = "DOWN".equals(overallStatus) ? HttpStatus.SERVICE_UNAVAILABLE : HttpStatus.OK; + + logger.debug("Health check completed with status: {}", overallStatus); + return new ResponseEntity<>(healthStatus, httpStatus); + + } catch (Exception e) { + logger.error("Unexpected error during health check", e); + + Map errorResponse = Map.of( + "status", "DOWN", + "timestamp", Instant.now().toString() + ); + + return new ResponseEntity<>(errorResponse, HttpStatus.SERVICE_UNAVAILABLE); + } + } +} From 469a1d563cc46887ea3591b8f3268bc5617001d6 Mon Sep 17 00:00:00 2001 From: SnehaRH <77656297+snehar-nd@users.noreply.github.com> Date: Tue, 30 Jun 2026 11:41:28 +0530 Subject: [PATCH 24/24] Bump version from 3.7.0 to 3.7.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5e21cb4..a1bffa5 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.iemr.ecd ecd-api - 3.7.0 + 3.7.1 war ECD-API ECD project