Kaynağa Gözat

update email: checking leave + consumed ?>= 8

add_swagger
MSI\derek 11 ay önce
ebeveyn
işleme
62577c9b1c
4 değiştirilmiş dosya ile 172 ekleme ve 39 silme
  1. +113
    -37
      src/main/java/com/ffii/tsms/modules/common/mail/service/MailReminderService.kt
  2. +9
    -0
      src/main/java/com/ffii/tsms/modules/common/mail/web/models/WorkHourRecords.kt
  3. +2
    -0
      src/main/java/com/ffii/tsms/modules/timesheet/entity/LeaveRepository.kt
  4. +48
    -2
      src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt

+ 113
- 37
src/main/java/com/ffii/tsms/modules/common/mail/service/MailReminderService.kt Dosyayı Görüntüle

@@ -3,6 +3,7 @@ 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.WorkHourRecords
import com.ffii.tsms.modules.data.entity.Staff
import com.ffii.tsms.modules.data.entity.StaffRepository
import com.ffii.tsms.modules.data.entity.TeamRepository
@@ -10,6 +11,7 @@ import com.ffii.tsms.modules.data.service.CompanyHolidayService
import com.ffii.tsms.modules.data.service.StaffsService
import com.ffii.tsms.modules.settings.service.SettingsService
import com.ffii.tsms.modules.timesheet.entity.TimesheetRepository
import com.ffii.tsms.modules.timesheet.service.TimesheetsService
import com.ffii.tsms.modules.user.service.UserService
import jakarta.mail.internet.InternetAddress
import org.apache.commons.logging.Log
@@ -26,12 +28,14 @@ data class TableRow(
val name: String,
val missingDates: MutableList<LocalDate>,
)

@Service
open class MailReminderService(
val mailService: MailService,
val userService: UserService,
val settingsService: SettingsService,
val holidayService: HolidayService,
val timesheetsService: TimesheetsService,
val timesheetRepository: TimesheetRepository,
val staffsService: StaffsService,
val staffRepository: StaffRepository,
@@ -117,8 +121,19 @@ open class MailReminderService(
val filteredLastMonthDays = lastMonthDays.filter {
it !in allHolidaysList && it.dayOfWeek != DayOfWeek.SATURDAY && it.dayOfWeek != DayOfWeek.SUNDAY
}

val timesheet = timesheetRepository.findByDeletedFalseAndRecordDateBetweenOrderByRecordDate(filteredLastMonthDays.first(),filteredLastMonthDays.last())
val args = mutableMapOf(
"from" to filteredLastMonthDays.first(),
"to" to filteredLastMonthDays.last(),
)
val ts = timesheetsService.workHourRecordsWithinRange(args)
val timesheet: List<WorkHourRecords> = ts.map {
WorkHourRecords(
staffId = it["staffId"].toString().toLong(),
recordDate = LocalDate.parse(it["recordDate"].toString()),
hours = it["hours"].toString().toDouble()
)
}
// val timesheet = timesheetRepository.findByDeletedFalseAndRecordDateBetweenOrderByRecordDate(filteredLastMonthDays.first(),filteredLastMonthDays.last())
val staffs = staffRepository.findAllByEmployTypeAndDeletedFalseAndDepartDateIsNull(FULLTIME)
val teams = teamRepository.findAll().filter { team -> team.deleted == false }

@@ -128,17 +143,36 @@ open class MailReminderService(
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.staff?.id) }
val timesheetByIdAndRecord = filteredTimesheet.groupBy { it.staff?.id to it.recordDate }
.map { (key, _) ->
val (staffId, recordDate) = key
recordDate to mutableListOf<Long>(staffId ?: 0)
// val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staff?.id) }
val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staffId) }
// val timesheetByIdAndRecord = filteredTimesheet.groupBy { it.staff?.id to it.recordDate }
// .map { (key, _) ->
// val (staffId, recordDate) = key
// recordDate to mutableListOf<Long>(staffId ?: 0)
// }
println(filteredTimesheet.filter { it.staffId == 4.toLong() })
val timesheetByIdAndRecord = filteredTimesheet.groupBy { it.staffId to it.recordDate }
.mapNotNull { (key, records) ->
Triple(
key.second,
key.first,
records.sumOf { it.hours }
)
}
val goodStaffsList = filteredLastMonthDays.map { day ->
timesheetByIdAndRecord.find {
it.first == day
} ?: Pair(day, mutableListOf())
}.sortedBy { it.first }
// val goodStaffsList = filteredLastMonthDays.map { day ->
// timesheetByIdAndRecord.find {
// it.first == day
// } ?: Pair(day, mutableListOf())
// }.sortedBy { it.first }

val goodStaffsList = filteredLastMonthDays.map { date ->
val matchedStaffIds = timesheetByIdAndRecord
.filter { it.first == date && it.third >= 8 }
.map { it.second } // Extracting the second element (staffId)
// Returning a Pair of the date and the list of matched staff IDs
Pair(date, matchedStaffIds)
}.sortedBy { it.first } // Sort by date
// return
// creating the email
val intro = StringBuilder("${teamLead.name}, Staffs Missing Timesheet in the Table Below: \n")
val tableData = mutableListOf<TableRow>()
@@ -148,7 +182,7 @@ open class MailReminderService(
goodStaffsList.forEach { (key, value) ->
if (!value.contains(it.id!!)) {
isNaughty = true
missingDates.add(key!!)
missingDates.add(key)
}
}
if (!isNaughty) return@forEach
@@ -176,7 +210,19 @@ open class MailReminderService(
val allHolidaysList: List<LocalDate> = (holidayList + companyHolidayList).toSet().toList()

//get data
val timesheet = timesheetRepository.findByDeletedFalseAndRecordDateBetweenOrderByRecordDate(firstDay, today)
val args = mutableMapOf(
"from" to firstDay,
"to" to today,
)
val ts = timesheetsService.workHourRecordsWithinRange(args)
val timesheet: List<WorkHourRecords> = ts.map {
WorkHourRecords(
staffId = it["staffId"].toString().toLong(),
recordDate = LocalDate.parse(it["recordDate"].toString()),
hours = it["hours"].toString().toDouble()
)
}
// val timesheet = timesheetRepository.findByDeletedFalseAndRecordDateBetweenOrderByRecordDate(firstDay, today)
val staffs = staffRepository.findAllByEmployTypeAndDeletedFalseAndDepartDateIsNull(FULLTIME)
val teams = teamRepository.findAll().filter { team -> team.deleted == false }

@@ -195,18 +241,24 @@ open class MailReminderService(
if (teamMembers.isEmpty()) continue
val teamMembersIds: List<Long?> = teamMembers.map { it.id }.sorted()
// getting the naughty list
val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staff?.id) } // filter team members' timesheet
val timesheetByIdAndRecord = filteredTimesheet.groupBy { it.staff?.id to it.recordDate }
.map { (key, _) ->
val (staffId, recordDate) = key
recordDate to mutableListOf<Long>(staffId ?: 0)
val filteredTimesheet = timesheet.filter { teamMembersIds.contains(it.staffId) } // filter team members' timesheet
val timesheetByIdAndRecord = filteredTimesheet.groupBy { it.staffId to it.recordDate }
.mapNotNull { (key, records) ->
Triple(
key.second,
key.first,
records.sumOf { it.hours }
)
}
// change the date list with desired time range
val goodStaffsList = filteredDatesList.map { day ->
timesheetByIdAndRecord.find {
it.first == day
} ?: Pair(day, mutableListOf())
val goodStaffsList = filteredDatesList.map { date ->
val matchedStaffIds = timesheetByIdAndRecord
.filter { it.first == date && it.third >= 8 }
.map { it.second } // Extracting the second element (staffId)
// Returning a Pair of the date and the list of matched staff IDs
Pair(date, matchedStaffIds)
}.sortedBy { it.first }

// creating the email content
val intro = StringBuilder("${teamLead.name}, Staffs Missing Timesheet in the Table Below: ($firstDay-$today) \n")
val tableData = mutableListOf<TableRow>()
@@ -216,7 +268,7 @@ open class MailReminderService(
goodStaffsList.forEach { (key, value) ->
if (!value.contains(it.id!!)) {
isNaughty = true
missingDates.add(key!!)
missingDates.add(key)
}
}
if (!isNaughty) return@forEach
@@ -267,22 +319,46 @@ open class MailReminderService(
daysBefore = daysBefore.minusDays(1)
}

val timesheet = timesheetRepository.findByDeletedFalseAndRecordDateBetweenOrderByRecordDate(sevenDaysBefore, fourDaysBefore)
val args = mutableMapOf(
"from" to sevenDaysBefore,
"to" to fourDaysBefore,
)

val ts = timesheetsService.workHourRecordsWithinRange(args)
val timesheet: List<WorkHourRecords> = ts.map {
WorkHourRecords(
staffId = it["staffId"].toString().toLong(),
recordDate = LocalDate.parse(it["recordDate"].toString()),
hours = it["hours"].toString().toDouble()
)
}
// val timesheet = timesheetRepository.findByDeletedFalseAndRecordDateBetweenOrderByRecordDate(sevenDaysBefore, fourDaysBefore)
val staffs = staffRepository.findAllByEmployTypeAndDeletedFalseAndDepartDateIsNull(FULLTIME) // FT? FT? etc
val staffIds: List<Long> = staffs.map { it.id as Long }

val timesheetByIdAndRecord = timesheet.groupBy { it.staff?.id to it.recordDate }
.map { (key, _) ->
val (staffId, recordDate) = key
"$recordDate" to mutableListOf<Long>(staffId ?: 0)
}
val goodStaffsList = workingDaysList.map { it ->
val key = it.toString()
timesheetByIdAndRecord.find {
it.first == key
}?: Pair(key, mutableListOf())
}.sortedBy { it.first }

// val timesheetByIdAndRecord = timesheet.groupBy { it.staff?.id to it.recordDate }
// .map { (key, _) ->
// val (staffId, recordDate) = key
// "$recordDate" to mutableListOf<Long>(staffId ?: 0)
// }
val timesheetByIdAndRecord = timesheet.groupBy {
it.staffId to it.recordDate
}.mapNotNull { (key, records) ->
Triple(
key.second,
key.first,
records.sumOf { it.hours }
)
}
val goodStaffsList = workingDaysList.map { date ->
val matchedStaffIds = timesheetByIdAndRecord
.filter { it.first == date && it.third >= 8 }
.map { it.second } // Extracting the second element (staffId)
// Returning a Pair of the date and the list of matched staff IDs
Pair(date, matchedStaffIds)
}.sortedBy { it.first } // Sort by date
println("goodStaffsList")
println(goodStaffsList)
// change this list with the staffs that need checking
staffIds.forEach { id ->
var isNaughty: Boolean = false


+ 9
- 0
src/main/java/com/ffii/tsms/modules/common/mail/web/models/WorkHourRecords.kt Dosyayı Görüntüle

@@ -0,0 +1,9 @@
package com.ffii.tsms.modules.common.mail.web.models

import java.time.LocalDate

data class WorkHourRecords(
val staffId: Long,
val recordDate: LocalDate,
val hours: Double,
)

+ 2
- 0
src/main/java/com/ffii/tsms/modules/timesheet/entity/LeaveRepository.kt Dosyayı Görüntüle

@@ -10,4 +10,6 @@ interface LeaveRepository : AbstractRepository<Leave, Long> {
fun deleteAllByStaffAndRecordDate(staff: Staff, recordDate: LocalDate)

fun findByStaffAndRecordDateBetweenOrderByRecordDate(staff: Staff, start: LocalDate, end: LocalDate): List<Leave>
fun findByDeletedFalseAndRecordDateBetweenOrderByRecordDate(start: LocalDate, end: LocalDate): List<Leave>

}

+ 48
- 2
src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt Dosyayı Görüntüle

@@ -1,6 +1,9 @@
package com.ffii.tsms.modules.timesheet.service

import com.ffii.core.exception.BadRequestException
import com.ffii.core.support.AbstractBaseEntityService
import com.ffii.core.support.JdbcDao
import com.ffii.tsms.modules.data.entity.Staff
import com.ffii.tsms.modules.data.entity.StaffRepository
import com.ffii.tsms.modules.data.service.StaffsService
import com.ffii.tsms.modules.data.service.TeamService
@@ -28,8 +31,10 @@ open class TimesheetsService(
private val projectRepository: ProjectRepository,
private val taskRepository: TaskRepository,
private val staffsService: StaffsService,
private val teamService: TeamService, private val staffRepository: StaffRepository, private val leaveRepository: LeaveRepository
) {
private val teamService: TeamService,
private val staffRepository: StaffRepository, private val leaveRepository: LeaveRepository,
private val jdbcDao: JdbcDao,
) : AbstractBaseEntityService<Timesheet, Long, TimesheetRepository>(jdbcDao, timesheetRepository) {
@Transactional
open fun saveTimesheet(recordTimeEntry: Map<LocalDate, List<TimeEntry>>): Map<String, List<TimeEntry>> {
// Need to be associated with a staff
@@ -378,4 +383,45 @@ open class TimesheetsService(

return "Rearrange success"
}
open fun workHourRecordsWithinRange(args: Map<String, Any>): List<Map<String, Any>> {
val sql = StringBuilder("WITH ts_cte AS ("
+ " SELECT "
+ " t.recordDate, "
+ " t.staffId, "
+ " SUM(coalesce(t.normalConsumed, 0)) + SUM(COALESCE(t.otConsumed, 0)) AS hours "
+ " , 'normal' as tp"
+ " FROM timesheet t "
+ " where t.deleted = false "
+ " GROUP BY t.staffId, t.recordDate "
+ " ), "
+ " l_cte AS ( "
+ " SELECT "
+ " l.recordDate, "
+ " l.staffId, "
+ " SUM(COALESCE(l.leaveHours, 0)) AS hours "
+ " ,'ot' as tp "
+ " FROM `leave` l "
+ " where l.deleted = false "
+ " GROUP BY l.staffId, l.recordDate "
+ " ) "
+ " select "
+ " recordDate, "
+ " staffId, "
+ " hours "
+ " ,tp "
+ " from ( "
+ " SELECT "
+ " * "
+ " FROM ts_cte tc "
+ " union "
+ " SELECT "
+ " * "
+ " FROM l_cte lc "
+ " ) ut "
)
if (args.containsKey("from") && args.containsKey("to"))
sql.append(" where recordDate BETWEEN :from AND :to ");
return jdbcDao.queryForList(sql.toString(), args)
}

}

Yükleniyor…
İptal
Kaydet