Blame | Last modification | View Log | RSS feed
package com.spice.profitmandi.service;import java.time.DayOfWeek;import java.time.LocalDate;import java.time.LocalDateTime;import java.util.List;import java.util.Set;import java.util.stream.Collectors;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.spice.profitmandi.dao.entity.logistics.PublicHolidays;import com.spice.profitmandi.dao.repository.logistics.PublicHolidaysRepository;/*** Service for working days calculations that excludes:* - Sundays (Saturdays are working days)* - Public holidays from the database*/@Servicepublic class WorkingDaysService {@Autowiredprivate PublicHolidaysRepository publicHolidaysRepository;/*** Checks if a given date is a working day (not Sunday, not holiday).* Note: Saturdays are considered working days.*/public boolean isWorkingDay(LocalDate date) {if (date == null) {return false;}// Check if Sunday (Saturdays are working days)if (date.getDayOfWeek() == DayOfWeek.SUNDAY) {return false;}// Check holidayPublicHolidays holiday = publicHolidaysRepository.selectByDate(date);return holiday == null;}/*** Counts working days between two dates (excludes Sundays and holidays).* Note: Saturdays are considered working days.** @param startDate Start date (inclusive)* @param endDate End date (exclusive)* @return Number of working days*/public int countWorkingDays(LocalDate startDate, LocalDate endDate) {if (startDate == null || endDate == null || !startDate.isBefore(endDate)) {return 0;}// Get all holidays in the date range for efficient lookupList<PublicHolidays> holidays = publicHolidaysRepository.selectAllBetweenDates(startDate, endDate);Set<LocalDate> holidayDates = holidays.stream().map(PublicHolidays::getDate).collect(Collectors.toSet());int workingDays = 0;LocalDate current = startDate;while (current.isBefore(endDate)) {boolean isSunday = current.getDayOfWeek() == DayOfWeek.SUNDAY;boolean isHoliday = holidayDates.contains(current);if (!isSunday && !isHoliday) {workingDays++;}current = current.plusDays(1);}return workingDays;}/*** Counts working days from a LocalDateTime to now.*/public int countWorkingDaysSince(LocalDateTime startDateTime) {if (startDateTime == null) {return 0;}return countWorkingDays(startDateTime.toLocalDate(), LocalDate.now());}/*** Adds working days to a date (excludes Sundays and holidays).* Note: Saturdays are considered working days.*/public LocalDate addWorkingDays(LocalDate startDate, int workingDaysToAdd) {if (startDate == null || workingDaysToAdd <= 0) {return startDate;}// Estimate end date range for holiday lookup (add buffer for Sundays/holidays)LocalDate estimatedEndDate = startDate.plusDays(workingDaysToAdd + 10);List<PublicHolidays> holidays = publicHolidaysRepository.selectAllBetweenDates(startDate, estimatedEndDate);Set<LocalDate> holidayDates = holidays.stream().map(PublicHolidays::getDate).collect(Collectors.toSet());LocalDate result = startDate;int addedDays = 0;while (addedDays < workingDaysToAdd) {result = result.plusDays(1);boolean isSunday = result.getDayOfWeek() == DayOfWeek.SUNDAY;boolean isHoliday = holidayDates.contains(result);if (!isSunday && !isHoliday) {addedDays++;}}return result;}/*** Checks if deadline has been exceeded based on working days.*/public boolean isDeadlineExceeded(LocalDateTime startDateTime, int workingDaysLimit) {if (startDateTime == null) {return false;}int elapsedWorkingDays = countWorkingDaysSince(startDateTime);return elapsedWorkingDays >= workingDaysLimit;}/*** Returns working days remaining before deadline.*/public int getWorkingDaysRemaining(LocalDateTime startDateTime, int workingDaysLimit) {if (startDateTime == null) {return 0;}int elapsedWorkingDays = countWorkingDaysSince(startDateTime);return workingDaysLimit - elapsedWorkingDays;}/*** Gets the deadline date given start date and working days.*/public LocalDate getDeadlineDate(LocalDate startDate, int workingDays) {return addWorkingDays(startDate, workingDays);}}