Untitled

Anonymous
plain_text
02/12/2026 5:44 AM
8.1 KB
13
Indexable
public Timesheet computeTimesheet(Timesheet timesheet, Schedule schedule) {
        LocalDate workDate = timesheet.getDate();

        var earliestScheduleStart = workDate.atTime(schedule.getEarliestStartTime());
        var latestScheduledStart = workDate.atTime(Optional.ofNullable(schedule.getLatestStartTime())
                .orElse(schedule.getEarliestStartTime()));

        var approvedLeave = leaveRequestRepository.findByLeaveAllocation_EmployeeDetail_EmployeeIdentifierAndLeaveDateAndStatus(
                UserUtil.getUser().getEmployeeNumber(),
                workDate,
                FilingStatus.APPROVED
        );

        if (approvedLeave.isPresent()) {
            if (approvedLeave.get().getPartOfDaySchedule().equals(PartOfDaySchedule.AM)) {
                earliestScheduleStart = workDate.atTime(schedule.getEarliestStartTimeHalfDayPM());
                latestScheduledStart = workDate.atTime(schedule.getLatestStartTimeHalfDayPM());
            }
        }


        //add 1 if earliest is greater than latest in terms of date
        latestScheduledStart = earliestScheduleStart.isAfter(latestScheduledStart) ?
                latestScheduledStart.plusDays(1) : latestScheduledStart;

        var graceTime = latestScheduledStart.plusMinutes(schedule.getGracePeriod());

        //Not late if within grace period, but if after grace period, late minutes will be computed from start time
        // till time in
        if (timesheet.getTimeIn().isAfter(graceTime)) {
            timesheet.setMinutesLate((int) Duration.between(latestScheduledStart, timesheet.getTimeIn().withSecond(0))
                    .toMinutes());
        } else {
            timesheet.setMinutesLate(0);
        }

        if (timesheet.getTimeIn() != null && timesheet.getTimeOut() != null) {
            var scheduledEndTime = isNightShift(schedule) ? workDate.plusDays(1)
                    .atTime(schedule.getEarliestEndTime()) : workDate.atTime(schedule.getEarliestEndTime());

            var totalScheduledMinutes = Duration.between(earliestScheduleStart, scheduledEndTime).toMinutes();

            //get start, set effective start as scheduled start if time in is earlier than scheduled start else the
            // actual time in
            //to be used for computing work minutes, valid work minutes are minutes within the schedule.
            LocalDateTime effectiveStart = timesheet.getTimeIn()
                    .isBefore(earliestScheduleStart) ? earliestScheduleStart : timesheet.getTimeIn();

            //evaluate if schedule ends the next day (eg. night/graveyard shifts)
            var nextDayEnd = isNightShift(schedule);

            LocalDateTime breakStart = workDate.atTime(schedule.getBreakStartTime()).withSecond(0).withNano(0);
            LocalDateTime breakEnd = workDate.atTime(schedule.getBreakEndTime()).withSecond(0).withNano(0);

            if (Optional.ofNullable(schedule.getLatestStartTime()).orElse(schedule.getEarliestStartTime())
                    .isAfter(schedule.getBreakStartTime()) ||
                    timesheet.getTimeIn().isAfter(breakStart)) {
                breakStart = breakStart.plusDays(1);
            }

            if (nextDayEnd && breakEnd.isBefore(breakStart)) {
                breakEnd = breakEnd.plusDays(1);
            }


            var rawWorkedMinutes = Duration.between(effectiveStart.withSecond(0), timesheet.getTimeOut().withSecond(0))
                    .toMinutes();


            if (approvedLeave.isPresent()) {
                if (!approvedLeave.get().getPartOfDaySchedule().equals(PartOfDaySchedule.WHOLE)) {

                    totalScheduledMinutes = totalScheduledMinutes / 2;

                    if (approvedLeave.get().getPartOfDaySchedule().equals(PartOfDaySchedule.PM)) {
                        rawWorkedMinutes = Duration.between(effectiveStart.withSecond(0),
                                        timesheet.getTimeOut().withSecond(0))
                                .toMinutes();

                        var halfScheduledEnd =
                                timesheet.getTimeIn().plusMinutes(totalScheduledMinutes).withSecond(0).withNano(0);

                        // add break duration if AM Attendance end crosses break start
                        if (halfScheduledEnd.isAfter(breakStart)) {
                            totalScheduledMinutes =
                                    totalScheduledMinutes + Duration.between(schedule.getBreakStartTime(),
                                                    schedule.getBreakEndTime())
                                    .toMinutes();
                        }

                    }
                } else {
                    totalScheduledMinutes = 0;
                }
            } else {
                totalScheduledMinutes = totalScheduledMinutes -
                        Duration.between(schedule.getBreakStartTime(), schedule.getBreakEndTime()).toMinutes();
                //deduct break minutes from total work minutes, if break is within the scheduled start and end
                if (timesheet.getTimeIn().isBefore(breakEnd) && timesheet.getTimeOut().isAfter(breakStart)) {
                    Duration breakOverlap = Duration.between(
                            timesheet.getTimeIn().isAfter(breakStart) ? timesheet.getTimeIn().withSecond(0) : breakStart,
                            timesheet.getTimeOut().isBefore(breakEnd) ? timesheet.getTimeOut().withSecond(0) : breakEnd
                    );
                    rawWorkedMinutes -= Math.max(0, breakOverlap.toMinutes());
                }

            }


            timesheet.setTotalWorkMinutes((int) rawWorkedMinutes);

            if (rawWorkedMinutes < totalScheduledMinutes) {
                timesheet.setMinutesUndertime((int) (totalScheduledMinutes - rawWorkedMinutes));
            } else {
                timesheet.setMinutesUndertime(0);
            }

            if (schedule.getOvertimeEligible() && rawWorkedMinutes > totalScheduledMinutes) {
                timesheet.setMinutesOvertime((int) (rawWorkedMinutes - totalScheduledMinutes));
            } else {
                timesheet.setMinutesOvertime(0);
            }

        }

        return timesheet;
    }
Editor is loading...
Leave a Comment