Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
35567 amit 1
package com.spice.profitmandi.service;
2
 
3
import java.time.DayOfWeek;
4
import java.time.LocalDate;
5
import java.time.LocalDateTime;
6
import java.util.List;
7
import java.util.Set;
8
import java.util.stream.Collectors;
9
 
10
import org.springframework.beans.factory.annotation.Autowired;
11
import org.springframework.stereotype.Service;
12
 
13
import com.spice.profitmandi.dao.entity.logistics.PublicHolidays;
14
import com.spice.profitmandi.dao.repository.logistics.PublicHolidaysRepository;
15
 
16
/**
17
 * Service for working days calculations that excludes:
18
 * - Sundays (Saturdays are working days)
19
 * - Public holidays from the database
20
 */
21
@Service
22
public class WorkingDaysService {
23
 
24
    @Autowired
25
    private PublicHolidaysRepository publicHolidaysRepository;
26
 
27
    /**
28
     * Checks if a given date is a working day (not Sunday, not holiday).
29
     * Note: Saturdays are considered working days.
30
     */
31
    public boolean isWorkingDay(LocalDate date) {
32
        if (date == null) {
33
            return false;
34
        }
35
 
36
        // Check if Sunday (Saturdays are working days)
37
        if (date.getDayOfWeek() == DayOfWeek.SUNDAY) {
38
            return false;
39
        }
40
 
41
        // Check holiday
42
        PublicHolidays holiday = publicHolidaysRepository.selectByDate(date);
43
        return holiday == null;
44
    }
45
 
46
    /**
47
     * Counts working days between two dates (excludes Sundays and holidays).
48
     * Note: Saturdays are considered working days.
49
     *
50
     * @param startDate Start date (inclusive)
51
     * @param endDate   End date (exclusive)
52
     * @return Number of working days
53
     */
54
    public int countWorkingDays(LocalDate startDate, LocalDate endDate) {
55
        if (startDate == null || endDate == null || !startDate.isBefore(endDate)) {
56
            return 0;
57
        }
58
 
59
        // Get all holidays in the date range for efficient lookup
60
        List<PublicHolidays> holidays = publicHolidaysRepository.selectAllBetweenDates(startDate, endDate);
61
        Set<LocalDate> holidayDates = holidays.stream()
62
                .map(PublicHolidays::getDate)
63
                .collect(Collectors.toSet());
64
 
65
        int workingDays = 0;
66
        LocalDate current = startDate;
67
 
68
        while (current.isBefore(endDate)) {
69
            boolean isSunday = current.getDayOfWeek() == DayOfWeek.SUNDAY;
70
            boolean isHoliday = holidayDates.contains(current);
71
 
72
            if (!isSunday && !isHoliday) {
73
                workingDays++;
74
            }
75
            current = current.plusDays(1);
76
        }
77
 
78
        return workingDays;
79
    }
80
 
81
    /**
82
     * Counts working days from a LocalDateTime to now.
83
     */
84
    public int countWorkingDaysSince(LocalDateTime startDateTime) {
85
        if (startDateTime == null) {
86
            return 0;
87
        }
88
        return countWorkingDays(startDateTime.toLocalDate(), LocalDate.now());
89
    }
90
 
91
    /**
92
     * Adds working days to a date (excludes Sundays and holidays).
93
     * Note: Saturdays are considered working days.
94
     */
95
    public LocalDate addWorkingDays(LocalDate startDate, int workingDaysToAdd) {
96
        if (startDate == null || workingDaysToAdd <= 0) {
97
            return startDate;
98
        }
99
 
100
        // Estimate end date range for holiday lookup (add buffer for Sundays/holidays)
101
        LocalDate estimatedEndDate = startDate.plusDays(workingDaysToAdd + 10);
102
        List<PublicHolidays> holidays = publicHolidaysRepository.selectAllBetweenDates(startDate, estimatedEndDate);
103
        Set<LocalDate> holidayDates = holidays.stream()
104
                .map(PublicHolidays::getDate)
105
                .collect(Collectors.toSet());
106
 
107
        LocalDate result = startDate;
108
        int addedDays = 0;
109
 
110
        while (addedDays < workingDaysToAdd) {
111
            result = result.plusDays(1);
112
            boolean isSunday = result.getDayOfWeek() == DayOfWeek.SUNDAY;
113
            boolean isHoliday = holidayDates.contains(result);
114
 
115
            if (!isSunday && !isHoliday) {
116
                addedDays++;
117
            }
118
        }
119
 
120
        return result;
121
    }
122
 
123
    /**
124
     * Checks if deadline has been exceeded based on working days.
125
     */
126
    public boolean isDeadlineExceeded(LocalDateTime startDateTime, int workingDaysLimit) {
127
        if (startDateTime == null) {
128
            return false;
129
        }
130
        int elapsedWorkingDays = countWorkingDaysSince(startDateTime);
131
        return elapsedWorkingDays >= workingDaysLimit;
132
    }
133
 
134
    /**
135
     * Returns working days remaining before deadline.
136
     */
137
    public int getWorkingDaysRemaining(LocalDateTime startDateTime, int workingDaysLimit) {
138
        if (startDateTime == null) {
139
            return 0;
140
        }
141
        int elapsedWorkingDays = countWorkingDaysSince(startDateTime);
142
        return workingDaysLimit - elapsedWorkingDays;
143
    }
144
 
145
    /**
146
     * Gets the deadline date given start date and working days.
147
     */
148
    public LocalDate getDeadlineDate(LocalDate startDate, int workingDays) {
149
        return addWorkingDays(startDate, workingDays);
150
    }
151
}