@@ -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.SettingNames
import com.ffii.tsms.modules.common.holiday.service.HolidayService
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.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.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.Staff
import com.ffii.tsms.modules.data.entity.StaffRepository
import com.ffii.tsms.modules.data.entity.StaffRepository
import com.ffii.tsms.modules.data.entity.TeamRepository
import com.ffii.tsms.modules.data.entity.TeamRepository
@@ -121,11 +123,12 @@ open class MailReminderService(
"to" to filteredLastMonthDays.last(),
"to" to filteredLastMonthDays.last(),
)
)
val ts = timesheetsService.workHourRecordsWithinRange(args)
val ts = timesheetsService.workHourRecordsWithinRange(args)
val timesheet: List<WorkHourRecords> = ts.map {
WorkHourRecords(
val timesheet: List<WorkHourRecordsWithJoinDate > = ts.map {
WorkHourRecordsWithJoinDate (
staffId = it["staffId"].toString().toLong(),
staffId = it["staffId"].toString().toLong(),
recordDate = LocalDate.parse(it["recordDate"].toString()),
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"}
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
if (teamMembers.isEmpty()) continue
val teamMembersIds: List<Long> = teamMembers.map { it.id!! }.sorted()
val teamMembersIds: List<Long> = teamMembers.map { it.id!! }.sorted()
val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staffId) }
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) ->
.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 goodStaffsList = filteredLastMonthDays.map { date ->
val matchedStaffIds = timesheetByIdAndRecord
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
// Returning a Pair of the date and the list of matched staff IDs
Pair(date, matchedStaffIds)
Pair(date, matchedStaffIds)
}.sortedBy { it.first } // Sort by date
}.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<LocalDate> = (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<LocalDate> = (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<WorkHourRecordsWithJoinDate> = 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<Staff> = staffs.filter { it.team != null && it.team.id == team.id }
if (teamMembers.isEmpty()) continue
val teamMembersIds: List<Long> = 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 51 14 * * ?") // (SS/MM/HH/DD/MM/YY)
@Scheduled(cron = "0 0 6 15 * ?") // (SS/MM/HH/DD/MM/YY)
@Scheduled(cron = "0 0 6 15 * ?") // (SS/MM/HH/DD/MM/YY)
open fun sendTimesheetToTeamLead15TH() {
open fun sendTimesheetToTeamLead15TH() {
if (!isSettingsConfigValid()) return
if (!isSettingsConfigValid()) return
val today = LocalDate.now() // should always be 15
val today = LocalDate.now().minusDays(1) // should always be 14, exclude 1 5th because the email is sent at 0600, suppose no one input timesheet in advance
val firstDay = today.withDayOfMonth(1)
val firstDay = today.withDayOfMonth(1)
val holidayList = holidayService.commonHolidayList().map { it.date }
val holidayList = holidayService.commonHolidayList().map { it.date }
val companyHolidayList = companyHolidayService.allCompanyHolidays().map { it.date }
val companyHolidayList = companyHolidayService.allCompanyHolidays().map { it.date }
@@ -195,11 +272,12 @@ open class MailReminderService(
"to" to today,
"to" to today,
)
)
val ts = timesheetsService.workHourRecordsWithinRange(args)
val ts = timesheetsService.workHourRecordsWithinRange(args)
val timesheet: List<WorkHourRecords> = ts.map {
WorkHourRecords(
val timesheet: List<WorkHourRecordsWithJoinDate > = ts.map {
WorkHourRecordsWithJoinDate (
staffId = it["staffId"].toString().toLong(),
staffId = it["staffId"].toString().toLong(),
recordDate = LocalDate.parse(it["recordDate"].toString()),
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"}
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<Long?> = teamMembers.map { it.id }.sorted()
val teamMembersIds: List<Long?> = teamMembers.map { it.id }.sorted()
// getting the naughty list
// getting the naughty list
val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staffId) } // filter team members' timesheet
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) ->
.mapNotNull { (key, records) ->
Triple (
StaffRecords (
key.second,
key.second,
key.first,
key.first,
records.sumOf { it.hours }
records.sumOf { it.hours },
key.third
)
)
}
}
// change the date list with desired time range
// change the date list with desired time range
val goodStaffsList = filteredDatesList.map { date ->
val goodStaffsList = filteredDatesList.map { date ->
val matchedStaffIds = timesheetByIdAndRecord
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
// Returning a Pair of the date and the list of matched staff IDs
Pair(date, matchedStaffIds)
Pair(date, matchedStaffIds)
}.sortedBy { it.first }
}.sortedBy { it.first }