From 827d8ea6d1aa95cdae4745ab05e2e52236ff294a Mon Sep 17 00:00:00 2001 From: "MSI\\2Fi" Date: Tue, 11 Mar 2025 15:29:29 +0800 Subject: [PATCH] check join date when sending email reminder --- .../mail/service/MailReminderService.kt | 124 +++++++++++++++--- .../modules/common/mail/web/MailController.kt | 5 + .../common/mail/web/models/WorkHourRecords.kt | 14 ++ .../timesheet/service/TimesheetsService.kt | 7 +- 4 files changed, 130 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/ffii/tsms/modules/common/mail/service/MailReminderService.kt b/src/main/java/com/ffii/tsms/modules/common/mail/service/MailReminderService.kt index 30d6a1f..50cf4f3 100644 --- a/src/main/java/com/ffii/tsms/modules/common/mail/service/MailReminderService.kt +++ b/src/main/java/com/ffii/tsms/modules/common/mail/service/MailReminderService.kt @@ -3,7 +3,9 @@ package com.ffii.tsms.modules.common.mail.service import com.ffii.tsms.modules.common.SettingNames import com.ffii.tsms.modules.common.holiday.service.HolidayService import com.ffii.tsms.modules.common.mail.pojo.MailRequest +import com.ffii.tsms.modules.common.mail.web.models.StaffRecords import com.ffii.tsms.modules.common.mail.web.models.WorkHourRecords +import com.ffii.tsms.modules.common.mail.web.models.WorkHourRecordsWithJoinDate import com.ffii.tsms.modules.data.entity.Staff import com.ffii.tsms.modules.data.entity.StaffRepository import com.ffii.tsms.modules.data.entity.TeamRepository @@ -121,11 +123,12 @@ open class MailReminderService( "to" to filteredLastMonthDays.last(), ) val ts = timesheetsService.workHourRecordsWithinRange(args) - val timesheet: List = ts.map { - WorkHourRecords( + val timesheet: List = ts.map { + WorkHourRecordsWithJoinDate( staffId = it["staffId"].toString().toLong(), recordDate = LocalDate.parse(it["recordDate"].toString()), - hours = it["hours"].toString().toDouble() + hours = it["hours"].toString().toDouble(), + joinDate = LocalDate.parse(it["joinDate"].toString()) ) } val staffs = staffRepository.findAllByEmployTypeAndDeletedFalseAndDepartDateIsNull(FULLTIME).filter { it.staffId != "A003" && it.staffId != "A004" && it.staffId != "B011" }.filter{ it.team?.code != "HO"} @@ -139,18 +142,26 @@ open class MailReminderService( if (teamMembers.isEmpty()) continue val teamMembersIds: List = teamMembers.map { it.id!! }.sorted() val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staffId) } - val timesheetByIdAndRecord = filteredTimesheet.groupBy { it.staffId to it.recordDate } + val timesheetByIdAndRecord = filteredTimesheet.groupBy { Triple(it.staffId, it.recordDate, it.joinDate) } .mapNotNull { (key, records) -> - Triple( - key.second, - key.first, - records.sumOf { it.hours } + StaffRecords( + key.second, // recordDate + key.first, // staffId + records.sumOf { it.hours }, + key.third ) } val goodStaffsList = filteredLastMonthDays.map { date -> val matchedStaffIds = timesheetByIdAndRecord - .filter { it.first == date && it.third >= 8 } - .map { it.second } // Extracting the second element (staffId) + .filter { + if(it.joinDate!! <= date){ + it.recordDate == date && it.sumOfHours >= 8 + }else{ + true + } + } + .map { it.staffId } // Extracting the second element (staffId) + .distinct() // Returning a Pair of the date and the list of matched staff IDs Pair(date, matchedStaffIds) }.sortedBy { it.first } // Sort by date @@ -180,11 +191,77 @@ open class MailReminderService( } } + // Testing function to print the good staff list + open fun test7thStaffList(){ + val today = LocalDate.now() + val holidayList = holidayService.commonHolidayList().map { it.date } + val companyHolidayList = companyHolidayService.allCompanyHolidays().map { it.date } + val allHolidaysList: List = (holidayList + companyHolidayList).toSet().toList() + // get working days from last month + val lastMonth = today.minusMonths(1) + val yearMonth = YearMonth.from(lastMonth) + val daysInLastMonth = yearMonth.lengthOfMonth() + val lastMonthDays: List = (1..daysInLastMonth).map { LocalDate.of(yearMonth.year, yearMonth.month, it) } + val filteredLastMonthDays = lastMonthDays.filter { + it !in allHolidaysList && it.dayOfWeek != DayOfWeek.SATURDAY && it.dayOfWeek != DayOfWeek.SUNDAY + } + val args = mutableMapOf( + "from" to filteredLastMonthDays.first(), + "to" to filteredLastMonthDays.last(), + ) + val ts = timesheetsService.workHourRecordsWithinRange(args) + val timesheet: List = ts.map { + WorkHourRecordsWithJoinDate( + staffId = it["staffId"].toString().toLong(), + recordDate = LocalDate.parse(it["recordDate"].toString()), + hours = it["hours"].toString().toDouble(), + joinDate = LocalDate.parse(it["joinDate"].toString()) + ) + } + val staffs = staffRepository.findAllByEmployTypeAndDeletedFalseAndDepartDateIsNull(FULLTIME).filter { it.staffId != "A003" && it.staffId != "A004" && it.staffId != "B011" }.filter{ it.team?.code != "HO"} + val teams = teamRepository.findAll().filter { team -> team.deleted == false +// && ( team.code == "WY" || team.code == "TW" || team.code == "CH" || team.code == "MN" || team.code == "MC" ) + } + + for (team in teams) { + val teamLead = team.staff + val teamMembers: List = staffs.filter { it.team != null && it.team.id == team.id } + if (teamMembers.isEmpty()) continue + val teamMembersIds: List = teamMembers.map { it.id!! }.sorted() + val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staffId) } + val timesheetByIdAndRecord = filteredTimesheet.groupBy { Triple(it.staffId, it.recordDate, it.joinDate) } + .mapNotNull { (key, records) -> + StaffRecords( + key.second, // recordDate + key.first, // staffId + records.sumOf { it.hours }, + key.third + ) + } + + val goodStaffsList = filteredLastMonthDays.map { date -> + val matchedStaffIds = timesheetByIdAndRecord + .filter { + if(it.joinDate!! <= date){ + it.recordDate == date && it.sumOfHours >= 8 + }else{ + true + } + } + .map { it.staffId } // Extracting the second element (staffId) + .distinct() + // Returning a Pair of the date and the list of matched staff IDs + Pair(date, matchedStaffIds) + }.sortedBy { it.first } + + } + } + // @Scheduled(cron = "0 51 14 * * ?") // (SS/MM/HH/DD/MM/YY) @Scheduled(cron = "0 0 6 15 * ?") // (SS/MM/HH/DD/MM/YY) open fun sendTimesheetToTeamLead15TH() { if (!isSettingsConfigValid()) return - val today = LocalDate.now() // should always be 15 + val today = LocalDate.now().minusDays(1) // should always be 14, exclude 15th because the email is sent at 0600, suppose no one input timesheet in advance val firstDay = today.withDayOfMonth(1) val holidayList = holidayService.commonHolidayList().map { it.date } val companyHolidayList = companyHolidayService.allCompanyHolidays().map { it.date } @@ -195,11 +272,12 @@ open class MailReminderService( "to" to today, ) val ts = timesheetsService.workHourRecordsWithinRange(args) - val timesheet: List = ts.map { - WorkHourRecords( + val timesheet: List = ts.map { + WorkHourRecordsWithJoinDate( staffId = it["staffId"].toString().toLong(), recordDate = LocalDate.parse(it["recordDate"].toString()), - hours = it["hours"].toString().toDouble() + hours = it["hours"].toString().toDouble(), + joinDate = LocalDate.parse(it["joinDate"].toString()) ) } val staffs = staffRepository.findAllByEmployTypeAndDeletedFalseAndDepartDateIsNull(FULLTIME).filter { it.staffId != "A003" && it.staffId != "A004" && it.staffId != "B011" }.filter{ it.team?.code != "HO"} @@ -221,19 +299,27 @@ open class MailReminderService( val teamMembersIds: List = teamMembers.map { it.id }.sorted() // getting the naughty list val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staffId) } // filter team members' timesheet - val timesheetByIdAndRecord = filteredTimesheet.groupBy { it.staffId to it.recordDate } + val timesheetByIdAndRecord = filteredTimesheet.groupBy { Triple(it.staffId, it.recordDate, it.joinDate) } .mapNotNull { (key, records) -> - Triple( + StaffRecords( key.second, key.first, - records.sumOf { it.hours } + records.sumOf { it.hours }, + key.third ) } // change the date list with desired time range val goodStaffsList = filteredDatesList.map { date -> val matchedStaffIds = timesheetByIdAndRecord - .filter { it.first == date && it.third >= 8 } - .map { it.second } // Extracting the second element (staffId) + .filter { + if(it.joinDate!! <= date){ + it.recordDate == date && it.sumOfHours >= 8 + }else{ + true + } + } + .map { it.staffId } // Extracting the second element (staffId) + .distinct() // Returning a Pair of the date and the list of matched staff IDs Pair(date, matchedStaffIds) }.sortedBy { it.first } diff --git a/src/main/java/com/ffii/tsms/modules/common/mail/web/MailController.kt b/src/main/java/com/ffii/tsms/modules/common/mail/web/MailController.kt index 19ab589..0ea91c5 100644 --- a/src/main/java/com/ffii/tsms/modules/common/mail/web/MailController.kt +++ b/src/main/java/com/ffii/tsms/modules/common/mail/web/MailController.kt @@ -43,4 +43,9 @@ class MailController( fun test15th() { mailReminderService.sendTimesheetToTeamLead15TH() } + + @GetMapping("/test7th-staff-list") + fun test7thStaffList(){ + mailReminderService.test7thStaffList() + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/tsms/modules/common/mail/web/models/WorkHourRecords.kt b/src/main/java/com/ffii/tsms/modules/common/mail/web/models/WorkHourRecords.kt index 7b41728..942ba17 100644 --- a/src/main/java/com/ffii/tsms/modules/common/mail/web/models/WorkHourRecords.kt +++ b/src/main/java/com/ffii/tsms/modules/common/mail/web/models/WorkHourRecords.kt @@ -7,3 +7,17 @@ data class WorkHourRecords( val recordDate: LocalDate, val hours: Double, ) + +data class WorkHourRecordsWithJoinDate( + val staffId: Long, + val recordDate: LocalDate, + val hours: Double, + val joinDate: LocalDate +) + +data class StaffRecords( + val recordDate: LocalDate, + val staffId: Long, + val sumOfHours: Double, + val joinDate: LocalDate? = LocalDate.of(1970,1,1) +) diff --git a/src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt b/src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt index 5573028..2bda259 100644 --- a/src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt +++ b/src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt @@ -498,25 +498,30 @@ open class TimesheetsService( val sql = StringBuilder("WITH ts_cte AS (" + " SELECT " + " t.recordDate, " + + " s.joinDate, " + " t.staffId, " + " SUM(coalesce(t.normalConsumed, 0)) + SUM(COALESCE(t.otConsumed, 0)) AS hours " + " , 'normal' as tp" + " FROM timesheet t " + + " left join staff s on s.id = t.staffId " + " where t.deleted = false " + " GROUP BY t.staffId, t.recordDate " + " ), " + " l_cte AS ( " + " SELECT " + " l.recordDate, " + + " s.joinDate, " + " l.staffId, " + " SUM(COALESCE(l.leaveHours, 0)) AS hours " + " ,'ot' as tp " - + " FROM `leave` l " + + " FROM `leave` l " + + " left join staff s on s.id = l.staffId " + " where l.deleted = false " + " GROUP BY l.staffId, l.recordDate " + " ) " + " select " + " recordDate, " + + " joinDate, " + " staffId, " + " hours " + " ,tp "