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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions src/main/environment/common_example.properties
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ cron-scheduler-ctidatasync=0 30 01 * * ? *

##-------------------------------###cti data check with call detail report Scheduler------------------------------------------------------

#Runs at everyday 3:00AM - after the NHM data pull and CTI data sync complete
#Runs at everyday 12:10AM
start-ctidatacheck-scheduler=false
cron-scheduler-ctidatacheck=0 00 03 * * *
cron-scheduler-ctidatacheck=0 00 02 * * *

##---------------------------------#### Registration schedular for Avni------------------------------------------------------------------------------

Expand All @@ -93,13 +93,7 @@ cron-scheduler-everwelldatasync=0 0/5 * * * ? *
##-----------------------------------------------#NHM data dashboard schedular----------------------------------------------------------------
# run at everyday 12:01AM
start-nhmdashboard-scheduler=true
cron-scheduler-nhmdashboard=0 1 0 * * ? *
nhm-detailedcallreport-backfill-days=7
# one-off recovery of older / partly imported days (yyyy-MM-dd, both inclusive,
# max 60 days per run). Leave empty during normal operation - while these are set
# the job pulls this range instead of only the missing days.
nhm-detailedcallreport-backfill-start-date=
nhm-detailedcallreport-backfill-end-date=
cron-scheduler-nhmdashboard=0 1 * * * ? *
##----------------------------------------------------#grievance data sync-----------------------------------------------------------

start-grievancedatasync-scheduler=false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,18 @@ public class NHMDetailCallReportScheduler {
@Value("${start-ctidatacheck-scheduler}")
private boolean startCtiDataCheckFlag;

/**
* Number of days (ending yesterday) checked against t_bencall. Kept in sync with
* the detailed call report backfill window, so that days pulled late from CTI are
* also reconciled. The reconciliation itself is idempotent.
*/
@Value("${nhm-detailedcallreport-backfill-days:7}")
private int lookBackDays;

@Scheduled(cron = "${cron-scheduler-ctidatacheck}")
public void detailedCallReport() {
if (startCtiDataCheckFlag) {
try {
int days = lookBackDays > 0 ? lookBackDays : 1;
LocalDateTime endDay = LocalDateTime.now().minusDays(1);
LocalDateTime startDay = endDay.minusDays(days - 1L);
String endDate = endDay.toString().split("T")[0].concat(" 23:59:59");
String fromDate = startDay.toString().split("T")[0].concat(" 00:00:00");
String endDate = null;
String fromDate = null;
LocalDateTime date = null;
date = LocalDateTime.now().minusDays(1);
String[] dateArr = date.toString().split("T");
endDate = dateArr[0].concat(" 23:59:59");
fromDate = dateArr[0].concat(" 00:00:01");

Timestamp fromTime = Timestamp.valueOf(fromDate);
Timestamp endTime = Timestamp.valueOf(endDate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,15 @@
*/
package com.iemr.common.repository.nhm_dashboard;

import java.sql.Date;
import java.sql.Timestamp;
import java.util.List;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.iemr.common.data.nhm_dashboard.DetailedCallReport;

@Repository
public interface DetailedCallReportRepo extends CrudRepository<DetailedCallReport, Long> {
List<DetailedCallReport> findByCallStartTimeBetween(Timestamp startDate, Timestamp endDate);

/**
* Call dates for which data has already been pulled from CTI. Used to detect
* the days that were missed by earlier scheduler runs, so that they can be
* pulled again instead of staying permanently empty.
*/
@Query(value = "select distinct date(Call_Start_Time) from t_DetailedCallReport "
+ "where Call_Start_Time between :startDate and :endDate", nativeQuery = true)
List<Date> findExistingCallDates(@Param("startDate") Timestamp startDate, @Param("endDate") Timestamp endDate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ public String callUrl(String urlRequest) {
@Override
public void ctiDataSync() {
LocalDate currentDate = LocalDate.now();
// Look back 7 days to retry records that failed in previous runs
LocalDate startDate = currentDate.minusDays(7);
// Up to yesterday
LocalDate endDate = currentDate.minusDays(1);
// Calculate three days before the current date
LocalDate startDate = currentDate.minusDays(3);
// Calculate two days before the current date
LocalDate endDate = currentDate.minusDays(2);
// Convert LocalDate to LocalDateTime to set time as 00:00:00
LocalDateTime startDateTime = startDate.atTime(0, 0, 0);
LocalDateTime endDateTime = endDate.atTime(23, 59, 59);
Expand All @@ -98,78 +98,64 @@ public void ctiDataSync() {
List<BeneficiaryCall> list = callReportRepo.getAllBenCallIDetails(startTimeStamp, endTimeStamp);

if (!list.isEmpty()) {
logger.info("Total records to process for CTI data sync: " + list.size());

// List<Long> benList = new ArrayList<>();
String callDuartion = null;
String filePath = null;
String URL = null;
String callinfoapiURL = null;
String ctiResponse = null;
String callEndTime = null;
String callStartTime = null;
String recordingPath = "";
for (BeneficiaryCall call : list) {
if (call.getCallID() == null) {
logger.warn("Skipping record with null callID, benCallID: " + call.getBenCallID());
continue;
}
String recordingPath = null;
String callDuartion = null;
String callEndTime = null;
String callStartTime = null;
try {
JSONObject requestFile = new JSONObject();
requestFile.put("agent_id", call.getAgentID());
requestFile.put("session_id", call.getCallID());

OutputResponse response1 = ctiService.getVoiceFileNew(requestFile.toString(), "extra parameter");
if(response1 != null && response1.getStatusCode() == 200) {

CTIResponse ctiResponsePath = InputMapper.gson().fromJson(response1.getData(),
CTIResponse.class);
String recordingFilePath = ctiResponsePath.getResponse().toString();
if(recordingFilePath.length() > 20)
recordingPath = recordingFilePath.substring(20);
else if (!recordingFilePath.isEmpty())
recordingPath = recordingFilePath;
logger.info("recordingPath: " + recordingPath);
}

String callInfoURL = this.callinfoapiURL;
String URL = callInfoURL.replace("CTI_SERVER", ctiServerIP).replace("AGENT_ID", call.getAgentID())
.replace("SESSION_ID", call.getCallID()).replace("PHONE_NO", call.getPhoneNo());

logger.info("calling CTI API url: " + URL);
String ctiResponse = this.callUrl(URL);
logger.info("calling CTI_CDR_CALL_INFO API returned " + ctiResponse);

CTIData data = InputMapper.gson().fromJson(ctiResponse, CTIData.class);
CTIResponse model = data.getResponse();

if (model != null && "1".equals(model.getResponse_code())) {
callDuartion = model.getCall_duration();
callEndTime = model.getCall_end_date_time();
callStartTime = model.getCall_start_date_time();
} else {
logger.warn("CTI API returned non-success for sessionID: " + call.getCallID()
+ ", response_code: " + (model != null ? model.getResponse_code() : "null"));
}

// Only save if we got at least the call duration from CTI
if (callDuartion != null) {
call.setCZcallDuration(Integer.parseInt(callDuartion));
if (call.getCallID() != null) {
recordingPath = null;
try {
JSONObject requestFile = new JSONObject();
requestFile.put("agent_id", call.getAgentID());
requestFile.put("session_id", call.getCallID());

OutputResponse response1 = ctiService.getVoiceFileNew(requestFile.toString(), "extra parameter");
if(response1 != null && response1.getStatusCode() == 200) {

CTIResponse ctiResponsePath = InputMapper.gson().fromJson(response1.getData(),
CTIResponse.class);
String recordingFilePath = ctiResponsePath.getResponse().toString();
if(recordingFilePath.length() > 20)
recordingPath = recordingFilePath.substring(20);
logger.info("recordingPath: " + recordingPath);
}

callDuartion = null;
callinfoapiURL = this.callinfoapiURL;
URL = callinfoapiURL.replace("CTI_SERVER", ctiServerIP).replace("AGENT_ID", call.getAgentID())
.replace("SESSION_ID", call.getCallID()).replace("PHONE_NO", call.getPhoneNo());

logger.info("calling CTI API url: " + URL);
ctiResponse = this.callUrl(URL);
logger.info("calling CTI_CDR_CALL_INFO API returned " + ctiResponse);

CTIData data = InputMapper.gson().fromJson(ctiResponse, CTIData.class);
CTIResponse model = data.getResponse();

if (model.getResponse_code().equals("1")) {
callDuartion = model.getCall_duration();
callEndTime = model.getCall_end_date_time();
callStartTime = model.getCall_start_date_time();
}
if (callDuartion != null)
call.setCZcallDuration(Integer.parseInt(callDuartion));
call.setRecordingPath(recordingPath);
call.setCZcallEndTime(callEndTime);
call.setCZcallStartTime(callStartTime);
call.setRecordingPath(recordingPath);
callReportRepo.save(call);
logger.info("CTI data sync saved for benCallID: " + call.getBenCallID());
} else if (recordingPath != null) {
// Duration not available yet, but recording path is β€” save path only
call.setRecordingPath(recordingPath);
callReportRepo.save(call);
logger.info("Only recordingPath saved (duration pending) for benCallID: " + call.getBenCallID());
} else {
logger.warn("No CTI data available yet for sessionID: " + call.getCallID()
+ ", benCallID: " + call.getBenCallID() + " - will retry next run");
logger.info("calling CTI_CDR_CALL_INFO after API call save response " + call);
} catch (Exception e) {
logger.error("VoiceFile failed with error " + e.getMessage(), e);
}
} catch (Exception e) {
logger.error("CTI data sync failed for benCallID: " + call.getBenCallID()
+ ", sessionID: " + call.getCallID() + " - " + e.getMessage(), e);
}
}
} else {
logger.info("No pending records found for CTI data sync");
}
}
}
Loading
Loading