io.mosip.preregistration.batchjob.impl.SlotAvailabilityGenerator Maven / Gradle / Ivy
package io.mosip.preregistration.batchjob.impl;
import static java.time.temporal.ChronoUnit.MINUTES;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAmount;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import io.mosip.kernel.core.logger.spi.Logger;
import io.mosip.preregistration.batchjob.code.PreRegBatchContants;
import io.mosip.preregistration.batchjob.entity.AvailibityEntity;
import io.mosip.preregistration.batchjob.helper.CancelAndNotifyHelper;
import io.mosip.preregistration.batchjob.helper.PreRegBatchDBHelper;
import io.mosip.preregistration.batchjob.helper.RegCenterIdsHolder;
import io.mosip.preregistration.batchjob.helper.RestHelper;
import io.mosip.preregistration.batchjob.model.RegistrationCenterDto;
import io.mosip.preregistration.batchjob.repository.utils.BatchJpaRepositoryImpl;
import io.mosip.preregistration.core.code.AuditLogVariables;
import io.mosip.preregistration.core.code.EventId;
import io.mosip.preregistration.core.code.EventName;
import io.mosip.preregistration.core.code.EventType;
import io.mosip.preregistration.core.common.entity.RegistrationBookingEntity;
import io.mosip.preregistration.core.config.LoggerConfiguration;
/**
* @author Mahammed Taheer
* @since 1.2.0
*
*/
@Component
public class SlotAvailabilityGenerator {
private Logger LOGGER = LoggerConfiguration.logConfig(SlotAvailabilityGenerator.class);
@Value("${preregistration.availability.sync}")
int noOfDaysToSync;
@Value("${mosip.mandatory-languages}")
private String mandatoryLangCodes;
@Value("${mosip.optional-languages}")
private String optionalLangCodes;
@Value("${notification.url}")
private String notificationURL;
@Value("${mosip.batch.token.authmanager.userName}")
private String auditUsername;
@Value("${mosip.batch.token.authmanager.appId}")
private String auditUserId;
@Autowired
private RestHelper restHelper;
/**
* Autowired reference for {@link #batchServiceDAO}
*/
@Autowired
private BatchJpaRepositoryImpl batchServiceDAO;
@Autowired
private PreRegBatchDBHelper batchDBHelper;
@Autowired
private CancelAndNotifyHelper cancelAndNotifyHelper;
public void generateRegistrationAvailabilitySlots(String partName, List regCenterIdsPartList) {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, PreRegBatchContants.EMPTY,
"No of days configured to generate slots availability: " + noOfDaysToSync);
RegCenterIdsHolder idsHolder = RegCenterIdsHolder.getInstance();
List regCentersList = restHelper.getRegistrationCenterDetails(regCenterIdsPartList, idsHolder);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, PreRegBatchContants.EMPTY,
"Total Number of registration Found available in Master Data: <" + regCentersList.size() +
">, on partition Name: " + partName + ", regCenterIdsPartList (Page Nos): " + regCenterIdsPartList);
long partStartTime = System.currentTimeMillis();
Map cancelledTracker = new HashMap<>();
Map notifierTracker = new HashMap<>();
List errorredRegCenters = new ArrayList<>();
final AtomicInteger procCounter = new AtomicInteger(1);
regCentersList.stream().forEach(regCenter -> {
long startTime = System.currentTimeMillis();
// identifier for debugging
String logIdentifier = partName + "_" + regCenter.getId() + "_" + System.currentTimeMillis();
try {
List regCenterholidaysList = restHelper.getRegistrationHolidayList(regCenter.getId(), regCenter.getLangCode(),
noOfDaysToSync);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Processing Generation of Slots for Reg Center Id: " + regCenter.getId() +
", Reg Center Holiday List: " + regCenterholidaysList);
LocalDate slotGenStartDate = LocalDate.now();
LocalDate slotGenEndDate = slotGenStartDate.plusDays(noOfDaysToSync);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Slot Generation/Updation Start Date: " + slotGenStartDate + " and End Date: " + slotGenEndDate);
slotGenStartDate.datesUntil(slotGenEndDate, Period.ofDays(1)).forEach(slotGenDate -> {
List slotsAvailableList = batchServiceDAO.findSlots(slotGenDate, regCenter.getId());
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"For date: " + slotGenDate + ", Slots available: " + slotsAvailableList.size());
// First, check date is in holiday list.
if (regCenterholidaysList.contains(slotGenDate.toString())) {
checkAndSaveEmptySlot(regCenter, slotsAvailableList, slotGenDate, logIdentifier, cancelledTracker, notifierTracker);
} else {
// Second, calculate and save the availability slots.
// Scenario 1 - slots are not available for the day, means not calculated yet.
if (slotsAvailableList.size() == 0) {
calculateFullDaySlotsAndSave(regCenter, slotGenDate, logIdentifier);
} else if(slotsAvailableList.size() == 1) {
// Scenario 2 - only one slot available, may be got added thought holiday now removed from holiday list.
purgeAndCalculateFullDaySlotsThenSave(regCenter, slotGenDate, logIdentifier, slotsAvailableList);
} else {
// Scenario 3 - many slots available, check for any change in start, lunch & end time and take action accordingly.
checkAndReCalculateFullDaySlotsThenSave(regCenter, slotGenDate, logIdentifier, slotsAvailableList,
cancelledTracker, notifierTracker);
}
}
});
} catch(Throwable t) {
LOGGER.error(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier, "Unknown Error: " + t.getMessage(), t);
errorredRegCenters.add(regCenter.getId());
}
batchServiceDAO.flushAvailability();
long endTime = System.currentTimeMillis();
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Time took to complete slot generation for registration center: " + (endTime - startTime) + " in ms," +
" procCounter: " + procCounter.getAndIncrement());
});
long partEndTime = System.currentTimeMillis();
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, PreRegBatchContants.EMPTY,
"Total Time Took to process partition: " + partName + ", Time(In millis): " + (partEndTime - partStartTime));
// Deleting all the added slots for the expired registration centers.
/* List slotsAddedRegCenters = batchServiceDAO.findRegCenter(LocalDate.now());
slotsAddedRegCenters.stream().filter(regCenterId -> !processingRegCentersList.contains(regCenterId))
.forEach(regCenterId -> purgeExpiredRegCenterSlots(regCenterId, cancelledTracker, notifierTracker)); */
// Printing the cancelled & notification status
printCancelNotifyStatus(cancelledTracker, "CANCEL-TRACKER");
printCancelNotifyStatus(notifierTracker, "NOTIFY-TRACKER");
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, PreRegBatchContants.EMPTY,
"Total Unique Registration Centers Found...");
idsHolder.printAllRegCenterIds();
if (errorredRegCenters.size() > 0) {
String regCenterIds = String.join(",", errorredRegCenters);
restHelper.sendAuditDetails(EventId.PRE_405.toString(), EventName.EXCEPTION.toString(), EventType.SYSTEM.toString(),
"Add Availability Slots Failed, List of Reg Centers.", AuditLogVariables.NO_ID.toString(),
auditUserId, auditUsername, regCenterIds, AuditLogVariables.BOOK.toString(), AuditLogVariables.BOOKING_SERVICE.toString());
return;
}
// No Reg Center has resulted in Error.
restHelper.sendAuditDetails(EventId.PRE_407.toString(), EventName.PERSIST.toString(), EventType.SYSTEM.toString(),
"Add Availability Slots Successfull.", AuditLogVariables.MULTIPLE_ID.toString(),
auditUserId, auditUsername, PreRegBatchContants.EMPTY, AuditLogVariables.BOOK.toString(),
AuditLogVariables.BOOKING_SERVICE.toString());
}
private void checkAndSaveEmptySlot(RegistrationCenterDto regCenterDetails, List slotsAvailableList,
LocalDate slotGenCurrentDay, String logIdentifier, Map cancelledTracker,
Map notifierTracker) {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Processing For holiday date: " + slotGenCurrentDay);
LocalTime midnightTime = LocalTime.MIDNIGHT;
// First, simply insert the empty slot if not already slots available
if (slotsAvailableList.size() == 0) {
batchDBHelper.saveAvailability(regCenterDetails.getId(), regCenterDetails.getContactPerson(),
PreRegBatchContants.ZERO_KIOSK, slotGenCurrentDay, midnightTime, midnightTime);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Inserted Empty slot for the date: " + slotGenCurrentDay);
return;
}
// Second, already slots available, check size and decide.
if (slotsAvailableList.size() == 1) {
AvailibityEntity slotAvailibityEntity = slotsAvailableList.get(0);
if (slotAvailibityEntity.getFromTime().equals(midnightTime) &&
slotAvailibityEntity.getToTime().equals(midnightTime)) {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Existing One Slot available & its empty slot: " + slotGenCurrentDay);
return;
}
// TODO - Check with Team what needs to be done if case time did not match.
// Should we implement cancellation & notification logic here.
// For now just deleting the existing record and inserting empty slot.
batchServiceDAO.deleteSlots(regCenterDetails.getId(), slotGenCurrentDay);
batchDBHelper.saveAvailability(regCenterDetails.getId(), regCenterDetails.getContactPerson(),
PreRegBatchContants.ZERO_KIOSK, slotGenCurrentDay, midnightTime, midnightTime);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Deleted & Inserted Empty slot for the date (Existing One Slot available): " + slotGenCurrentDay);
return;
}
// Third, more than one slot already create for an holiday list.
// May be some exceptional holiday.
List regBookingEntityList = batchServiceDAO.findAllPreIds(regCenterDetails.getId(),
slotGenCurrentDay);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of bookings available on the day: " + regBookingEntityList.size());
regBookingEntityList.stream().forEach(bookedSlot -> {
cancelAndNotifyHelper.cancelAndNotifyApplicant(bookedSlot, logIdentifier, cancelledTracker, notifierTracker);
});
batchServiceDAO.deleteSlots(regCenterDetails.getId(), slotGenCurrentDay);
batchDBHelper.saveAvailability(regCenterDetails.getId(), regCenterDetails.getContactPerson(),
PreRegBatchContants.ZERO_KIOSK, slotGenCurrentDay, midnightTime, midnightTime);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Deleted & Inserted Empty slot for the date (Existing All Slots available): " + slotGenCurrentDay);
}
private void calculateFullDaySlotsAndSave(RegistrationCenterDto regCenterDetails, LocalDate slotGenCurrentDay,
String logIdentifier) {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Processing For Full Day Slots for date: " + slotGenCurrentDay);
LocalTime centerStartTime = regCenterDetails.getCenterStartTime();
LocalTime centerEndTime = regCenterDetails.getCenterEndTime();
LocalTime centerLunchStartTime = regCenterDetails.getLunchStartTime();
LocalTime centerLunchEndTime = regCenterDetails.getLunchEndTime();
LocalTime perKioskProcessTime = regCenterDetails.getPerKioskProcessTime();
LocalTime midnight = LocalTime.MIDNIGHT;
int totalSlotAdded = 0;
if (centerStartTime.equals(midnight) || centerEndTime.equals(midnight)) {
LOGGER.error(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Not Processing For Full Day because either start/end time not configured");
return;
}
if (centerLunchStartTime.equals(midnight) || centerLunchEndTime.equals(midnight)) {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Processing For Full Day without considering lunch hour(s).");
totalSlotAdded += calculateAndSaveSlot(centerStartTime, centerEndTime, perKioskProcessTime,
regCenterDetails, slotGenCurrentDay, logIdentifier);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of slots added(without lunch): " + totalSlotAdded + ", Processing Day: " + slotGenCurrentDay);
return;
}
// save slots before lunch.
totalSlotAdded += calculateAndSaveSlot(centerStartTime, centerLunchStartTime, perKioskProcessTime,
regCenterDetails, slotGenCurrentDay, logIdentifier);
// save lunch slot
batchDBHelper.saveAvailability(regCenterDetails.getId(), regCenterDetails.getContactPerson(),
PreRegBatchContants.ZERO_KIOSK, slotGenCurrentDay, centerLunchStartTime, centerLunchEndTime);
totalSlotAdded += 1; // adding lunch slot also. just to find total how many slots saved.
// save slots after lunch
totalSlotAdded += calculateAndSaveSlot(centerLunchEndTime, centerEndTime, perKioskProcessTime,
regCenterDetails, slotGenCurrentDay, logIdentifier);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of slots added (full day including lunch): " + totalSlotAdded + ", Processing Day: " + slotGenCurrentDay);
}
private int calculateAndSaveSlot(LocalTime startTime, LocalTime endTime, LocalTime perKioskProcessTime,
RegistrationCenterDto regCenterDetails, LocalDate slotGenCurrentDay, String logIdentifier) {
LocalTime slotStartTime = startTime;
LocalTime slotEndTime = startTime.plusHours(perKioskProcessTime.getHour()).plusMinutes(perKioskProcessTime.getMinute());
int slotsCnt = 0;
do {
if (slotEndTime.isAfter(endTime)) {
break;
}
slotsCnt++;
batchDBHelper.saveAvailability(regCenterDetails.getId(), regCenterDetails.getContactPerson(),
regCenterDetails.getNumberOfKiosks(), slotGenCurrentDay, slotStartTime, slotEndTime);
slotStartTime = slotEndTime;
slotEndTime = slotEndTime.plusHours(perKioskProcessTime.getHour()).plusMinutes(perKioskProcessTime.getMinute());
} while(slotEndTime.isBefore(endTime) || slotEndTime.equals(endTime));
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Slots Saved : " + slotsCnt +
", startTime: " + startTime.format(timeFormatter) +
", endTime: " + endTime.format(timeFormatter) +
", perKioskProcessTime: " + perKioskProcessTime.format(timeFormatter));
return slotsCnt;
}
private void purgeAndCalculateFullDaySlotsThenSave(RegistrationCenterDto regCenterDetails, LocalDate slotGenCurrentDay,
String logIdentifier, List slotsAvailableList) {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Purge existing one slot & Processing For Full Day Slots for date: " + slotGenCurrentDay);
LocalTime midnightTime = LocalTime.MIDNIGHT;
AvailibityEntity slotAvailibityEntity = slotsAvailableList.get(0);
if (slotAvailibityEntity.getFromTime().equals(midnightTime) &&
slotAvailibityEntity.getToTime().equals(midnightTime)) {
batchServiceDAO.deleteSlots(regCenterDetails.getId(), slotGenCurrentDay);
calculateFullDaySlotsAndSave(regCenterDetails, slotGenCurrentDay, logIdentifier);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Purged existing one holiday slot & Processed For Full Day Slots for date: " + slotGenCurrentDay);
return;
}
// TODO - Not sure why only one slot with different time got added in DB. Need to check the scenario.
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Not able to Purged existing one slot because slot start and end time not" +
" matching with MIDNIGHT time for date: " + slotGenCurrentDay);
}
private void checkAndReCalculateFullDaySlotsThenSave(RegistrationCenterDto regCenterDetails, LocalDate slotGenCurrentDay,
String logIdentifier, List slotsAvailableList, Map cancelledTracker,
Map notifierTracker) {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Checking existing slots for change in start, lunch & end time for date: " + slotGenCurrentDay);
LocalTime centerStartTime = regCenterDetails.getCenterStartTime();
LocalTime centerEndTime = regCenterDetails.getCenterEndTime();
LocalTime centerLunchStartTime = regCenterDetails.getLunchStartTime();
LocalTime centerLunchEndTime = regCenterDetails.getLunchEndTime();
LocalTime firstSlotStartTime = slotsAvailableList.get(0).getFromTime();
LocalTime lastSlotEndTime = slotsAvailableList.get(slotsAvailableList.size() - 1).getToTime();
// To Handle already generated slots. Existing slots generation did not have the lunch slot.
LocalTime lunchSlotStartTime = LocalTime.MIDNIGHT;
LocalTime lunchSlotEndTime = LocalTime.MIDNIGHT;
LocalTime midnightTime = LocalTime.MIDNIGHT;
boolean foundLunchSlots = false;
Optional lunchSlotTiming = slotsAvailableList.stream().filter(slot -> slot.getAvailableKiosks() == 0).findFirst();
if (lunchSlotTiming.isPresent()) {
lunchSlotStartTime = lunchSlotTiming.get().getFromTime();
lunchSlotEndTime = lunchSlotTiming.get().getToTime();
foundLunchSlots = true;
} else {
Object[] lunchTime = findLunchTimes(slotsAvailableList);
if (Objects.nonNull(lunchTime[0])) {
lunchSlotStartTime = (LocalTime) lunchTime[0];
long mins = MINUTES.between(lunchSlotStartTime, centerLunchStartTime);
// Scenario -- slot end time = 12:20 and lunch start time = 12:30 and perkiosk time = 20 mins.
// as 10 mins slot cannot be added so updating the lunch start time if there is difference.
if (mins != 0) {
LocalTime perKioskTime = regCenterDetails.getPerKioskProcessTime();
int perKioskTimeInMins = perKioskTime.getHour() * 60 + perKioskTime.getMinute();
if (mins < perKioskTimeInMins) {
lunchSlotStartTime = centerLunchStartTime;
}
}
}
if (Objects.nonNull(lunchTime[1]))
lunchSlotEndTime = (LocalTime) lunchTime[1];
if (Objects.nonNull(lunchTime[0]) && Objects.nonNull(lunchTime[1])){
// save lunch slot, will be useful in next calculation.
batchDBHelper.saveAvailability(regCenterDetails.getId(), regCenterDetails.getContactPerson(),
PreRegBatchContants.ZERO_KIOSK, slotGenCurrentDay, lunchSlotStartTime, lunchSlotEndTime);
foundLunchSlots = true;
}
}
if (centerStartTime.equals(firstSlotStartTime) && centerEndTime.equals(lastSlotEndTime) &&
centerLunchStartTime.equals(lunchSlotStartTime) && centerLunchEndTime.equals(lunchSlotEndTime)) {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"no recalculation required as no change found in start, lunch & end time for date: " + slotGenCurrentDay);
return;
}
// Start Time.
if (!centerStartTime.equals(firstSlotStartTime)) {
// centerConfiguredTime = 09:30
// slotCalculatedTime = 09:00
// cancel/notify the slots from 09:00 to 09:30 -> 30 mins
// centerConfiguredTime = 09:00
// slotCalculatedTime = 09:30
// add new slots from 09:00 to 09:30 -> 30 mins
recalculateSlots(centerStartTime, firstSlotStartTime, regCenterDetails, slotGenCurrentDay, logIdentifier,
cancelledTracker, notifierTracker);
}
// End Time.
if (!centerEndTime.equals(lastSlotEndTime)) {
// certerConfiguredTime = 17:30 (centerEndTime)
// slotCalculatedTime = 17:00 (lastSlotEndTime)
// add new slots from 17:00 to 17:30 -> 30 mins.
// certerConfiguredTime = 17:00 (centerEndTime)
// slotCalculatedTime = 17:30 (lastSlotEndTime)
// cancel/notify the slots from 17:00 to 17:30 -> 30 mins.
// just goes reverse here.... but need to validate the scenario.
recalculateSlots(lastSlotEndTime, centerEndTime, regCenterDetails, slotGenCurrentDay, logIdentifier,
cancelledTracker, notifierTracker);
}
// Scenario - Previously no lunch hours configured, now configured lunch hours.
// Need to cancel all the appointment and send notification to residents.
if (!foundLunchSlots && lunchSlotStartTime.equals(midnightTime) && lunchSlotStartTime.equals(lunchSlotEndTime)) {
long diffMins = MINUTES.between(centerLunchStartTime, centerLunchEndTime);
if (diffMins > 0) {
List regBookingEntityList = batchServiceDAO.findAllPreIdsBydateAndBetweenHours(regCenterDetails.getId(),
slotGenCurrentDay, centerLunchStartTime, centerLunchEndTime);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of bookings available between hours(lunch hours): " + regBookingEntityList.size());
final AtomicInteger counter = new AtomicInteger();
regBookingEntityList.stream().forEach(bookedSlot -> {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Cancelling Application for PreReg Id(lunch hours): " + bookedSlot.getPreregistrationId());
counter.incrementAndGet();
cancelAndNotifyHelper.cancelAndNotifyApplicant(bookedSlot, logIdentifier, cancelledTracker, notifierTracker);
});
LocalTime newCenterLunchEndTime = centerLunchEndTime.minusMinutes(1);
int deleted = batchServiceDAO.deleteSlotsBetweenHours(regCenterDetails.getId(), slotGenCurrentDay,
centerLunchStartTime, newCenterLunchEndTime);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of bookings cancel & notified between hours(lunch hours): " + counter.get());
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of slots deleted(lunch hours): " + deleted);
batchDBHelper.saveAvailability(regCenterDetails.getId(), regCenterDetails.getContactPerson(),
PreRegBatchContants.ZERO_KIOSK, slotGenCurrentDay, centerLunchStartTime, centerLunchEndTime);
return;
}
}
// Lunch Start Time.
if (!centerLunchStartTime.equals(lunchSlotStartTime)) {
// previously lunch hours configured, updated now as no lunch hours (removed lunch hours)
// add new slots for the lunch hour.
if (centerLunchStartTime.equals(midnightTime) && centerLunchStartTime.equals(centerLunchEndTime)) {
batchServiceDAO.deleteSlotForStartTimeEndTime(regCenterDetails.getId(), slotGenCurrentDay, lunchSlotStartTime, lunchSlotEndTime);
int totalSlotAdded = calculateAndSaveSlot(lunchSlotStartTime, lunchSlotEndTime, regCenterDetails.getPerKioskProcessTime(),
regCenterDetails, slotGenCurrentDay, logIdentifier);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of new bookings slots added between hours(removed lunch hours): " + totalSlotAdded);
} else {
// certerConfiguredTime = 13:30 (centerLunchStartTime)
// slotCalculatedTime = 13:00 (lunchSlotStartTime)
// add new slots from 13:00 to 13:30 -> 30 mins.
// certerConfiguredTime = 13:00 (centerLunchStartTime)
// slotCalculatedTime = 13:30 (lunchSlotStartTime)
// cancel/notify the slots from 13:00 to 13:30 -> 30 mins.
recalculateSlots(lunchSlotStartTime, centerLunchStartTime, regCenterDetails, slotGenCurrentDay, logIdentifier,
cancelledTracker, notifierTracker);
}
}
// Lunch End Time.
if (!centerLunchEndTime.equals(lunchSlotEndTime)) {
if (!(centerLunchStartTime.equals(midnightTime) && centerLunchStartTime.equals(centerLunchEndTime))) {
// certerConfiguredTime = 14:30 (centerLunchStartTime)
// slotCalculatedTime = 14:00 (lunchSlotStartTime)
// cancel/notify the slots from 14:00 to 14:30 -> 30 mins.
// certerConfiguredTime = 13:30 (centerLunchStartTime)
// slotCalculatedTime = 14:00 (lunchSlotStartTime)
// add new slots from 13:30 to 14:00 -> 30 mins.
recalculateSlots(centerLunchEndTime, lunchSlotEndTime, regCenterDetails, slotGenCurrentDay, logIdentifier,
cancelledTracker, notifierTracker);
}
}
}
private void recalculateSlots(LocalTime centerConfiguredTime, LocalTime slotCalculatedTime, RegistrationCenterDto regCenterDetails,
LocalDate slotGenCurrentDay, String logIdentifier, Map cancelledTracker,
Map notifierTracker) {
long diffMins = MINUTES.between(centerConfiguredTime, slotCalculatedTime);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"recalculating slots, centerConfiguredTime: " + centerConfiguredTime + ", slotCalculatedTime: " + slotCalculatedTime +
", diffMins: " + diffMins);
if (diffMins < 0){
List regBookingEntityList = batchServiceDAO.findAllPreIdsBydateAndBetweenHours(regCenterDetails.getId(),
slotGenCurrentDay, slotCalculatedTime, centerConfiguredTime);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of bookings available between hours: " + regBookingEntityList.size());
final AtomicInteger counter = new AtomicInteger();
regBookingEntityList.stream().forEach(bookedSlot -> {
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Cancelling Application for PreReg Id: " + bookedSlot.getPreregistrationId());
counter.incrementAndGet();
cancelAndNotifyHelper.cancelAndNotifyApplicant(bookedSlot, logIdentifier, cancelledTracker, notifierTracker);
});
batchServiceDAO.deleteSlotsBetweenHours(regCenterDetails.getId(), slotGenCurrentDay, slotCalculatedTime, centerConfiguredTime);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of bookings cancel & notified between hours: " + counter.get());
return;
}
int totalSlotAdded = calculateAndSaveSlot(centerConfiguredTime, slotCalculatedTime, regCenterDetails.getPerKioskProcessTime(),
regCenterDetails, slotGenCurrentDay, logIdentifier);
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, logIdentifier,
"Total Number of new bookings slots added between hours: " + totalSlotAdded);
}
private Object[] findLunchTimes(List slotsAvailableList) {
int listSize = slotsAvailableList.size();
LocalTime lunchSlotStartTime = null;
LocalTime lunchSlotEndTime = null;
for (int i = 0; i < listSize; i++) {
if ((i + 1) == listSize) {
break;
}
long diffMins = MINUTES.between(slotsAvailableList.get(i + 1).getFromTime(), slotsAvailableList.get(i).getToTime());
if (diffMins != 0) {
lunchSlotStartTime = slotsAvailableList.get(i).getToTime();
lunchSlotEndTime = slotsAvailableList.get(i + 1).getFromTime();
break;
}
}
return new Object[] {lunchSlotStartTime, lunchSlotEndTime};
}
private void printCancelNotifyStatus(Map tracker, String trackerLog) {
tracker.entrySet().stream().forEach(trackerKey -> {
String mesg = trackerKey.getValue() == Boolean.TRUE ? "Success" : "Failed";
LOGGER.info(PreRegBatchContants.SESSIONID, PreRegBatchContants.PRE_REG_BATCH, trackerLog,
"For Pre Reg Id: " + trackerKey.getKey() + ", Status: " + mesg);
});
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy