@@ -2,18 +2,22 @@ package com.ffii.tsms.modules.timesheet.service | |||||
import com.ffii.core.exception.BadRequestException | import com.ffii.core.exception.BadRequestException | ||||
import com.ffii.tsms.modules.data.service.StaffsService | import com.ffii.tsms.modules.data.service.StaffsService | ||||
import com.ffii.tsms.modules.data.service.TeamService | |||||
import com.ffii.tsms.modules.timesheet.entity.* | import com.ffii.tsms.modules.timesheet.entity.* | ||||
import com.ffii.tsms.modules.timesheet.web.models.LeaveEntry | import com.ffii.tsms.modules.timesheet.web.models.LeaveEntry | ||||
import com.ffii.tsms.modules.timesheet.web.models.TeamMemberLeaveEntries | |||||
import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
import org.springframework.transaction.annotation.Transactional | import org.springframework.transaction.annotation.Transactional | ||||
import java.time.LocalDate | import java.time.LocalDate | ||||
import java.time.format.DateTimeFormatter | import java.time.format.DateTimeFormatter | ||||
import kotlin.jvm.optionals.getOrDefault | |||||
@Service | @Service | ||||
open class LeaveService( | open class LeaveService( | ||||
private val leaveRepository: LeaveRepository, | private val leaveRepository: LeaveRepository, | ||||
private val leaveTypeRepository: LeaveTypeRepository, | private val leaveTypeRepository: LeaveTypeRepository, | ||||
private val staffsService: StaffsService | |||||
private val staffsService: StaffsService, | |||||
private val teamService: TeamService | |||||
) { | ) { | ||||
open fun getLeaveTypes(): List<LeaveType> { | open fun getLeaveTypes(): List<LeaveType> { | ||||
return leaveTypeRepository.findAll() | return leaveTypeRepository.findAll() | ||||
@@ -51,6 +55,45 @@ open class LeaveService( | |||||
return transformToLeaveEntryMap(savedLeaves) | return transformToLeaveEntryMap(savedLeaves) | ||||
} | } | ||||
@Transactional | |||||
open fun saveMemberLeaveEntry(staffId: Long, entry: LeaveEntry, recordDate: LocalDate?): Map<String, List<LeaveEntry>> { | |||||
val currentStaff = staffsService.currentStaff() ?: throw BadRequestException() | |||||
// Make sure current staff is a team lead | |||||
teamService.getMyTeamForStaff(currentStaff) ?: throw BadRequestException() | |||||
val leaveTypesMap = getLeaveTypes().associateBy { it.id } | |||||
val memberStaff = staffsService.getStaff(staffId) | |||||
val leave = leaveRepository.findById(entry.id).getOrDefault(Leave()).apply { | |||||
this.leaveHours = entry.inputHours | |||||
this.leaveType = leaveTypesMap[entry.leaveTypeId] | |||||
this.remark = entry.remark | |||||
this.recordDate = this.recordDate ?: recordDate | |||||
this.staff = this.staff ?: memberStaff | |||||
} | |||||
leaveRepository.save(leave) | |||||
return transformToLeaveEntryMap(leaveRepository.findAllByStaff(memberStaff)) | |||||
} | |||||
open fun getTeamMemberLeave(): Map<Long, TeamMemberLeaveEntries> { | |||||
val currentStaff = staffsService.currentStaff() ?: return emptyMap() | |||||
// Get team where current staff is team lead | |||||
val myTeam = teamService.getMyTeamForStaff(currentStaff) ?: return emptyMap() | |||||
val teamMembers = staffsService.findAllByTeamId(myTeam.id!!).getOrDefault(emptyList()) | |||||
return teamMembers.associate { member -> | |||||
Pair( | |||||
member.id!!, | |||||
TeamMemberLeaveEntries( | |||||
staffId = member.staffId, | |||||
name = member.name, | |||||
leaveEntries = transformToLeaveEntryMap(leaveRepository.findAllByStaff(member)) | |||||
) | |||||
) | |||||
} | |||||
} | |||||
private fun transformToLeaveEntryMap(leaves: List<Leave>): Map<String, List<LeaveEntry>> { | private fun transformToLeaveEntryMap(leaves: List<Leave>): Map<String, List<LeaveEntry>> { | ||||
return leaves | return leaves | ||||
.groupBy { leave -> leave.recordDate!!.format(DateTimeFormatter.ISO_LOCAL_DATE) } | .groupBy { leave -> leave.recordDate!!.format(DateTimeFormatter.ISO_LOCAL_DATE) } | ||||
@@ -89,7 +89,7 @@ open class TimesheetsService( | |||||
return transformToTimeEntryMap(timesheetRepository.findAllByStaff(currentStaff)) | return transformToTimeEntryMap(timesheetRepository.findAllByStaff(currentStaff)) | ||||
} | } | ||||
open fun getTimeMemberTimesheet(): Map<Long, TeamMemberTimeEntries> { | |||||
open fun getTeamMemberTimesheet(): Map<Long, TeamMemberTimeEntries> { | |||||
val currentStaff = staffsService.currentStaff() ?: return emptyMap() | val currentStaff = staffsService.currentStaff() ?: return emptyMap() | ||||
// Get team where current staff is team lead | // Get team where current staff is team lead | ||||
val myTeam = teamService.getMyTeamForStaff(currentStaff) ?: return emptyMap() | val myTeam = teamService.getMyTeamForStaff(currentStaff) ?: return emptyMap() | ||||
@@ -4,10 +4,7 @@ import com.ffii.core.exception.BadRequestException | |||||
import com.ffii.tsms.modules.timesheet.entity.LeaveType | import com.ffii.tsms.modules.timesheet.entity.LeaveType | ||||
import com.ffii.tsms.modules.timesheet.service.LeaveService | import com.ffii.tsms.modules.timesheet.service.LeaveService | ||||
import com.ffii.tsms.modules.timesheet.service.TimesheetsService | import com.ffii.tsms.modules.timesheet.service.TimesheetsService | ||||
import com.ffii.tsms.modules.timesheet.web.models.LeaveEntry | |||||
import com.ffii.tsms.modules.timesheet.web.models.TeamMemberTimeEntries | |||||
import com.ffii.tsms.modules.timesheet.web.models.TeamTimeEntry | |||||
import com.ffii.tsms.modules.timesheet.web.models.TimeEntry | |||||
import com.ffii.tsms.modules.timesheet.web.models.* | |||||
import jakarta.validation.Valid | import jakarta.validation.Valid | ||||
import org.springframework.web.bind.annotation.GetMapping | import org.springframework.web.bind.annotation.GetMapping | ||||
import org.springframework.web.bind.annotation.PostMapping | import org.springframework.web.bind.annotation.PostMapping | ||||
@@ -47,7 +44,12 @@ class TimesheetsController(private val timesheetsService: TimesheetsService, pri | |||||
@GetMapping("/teamTimesheets") | @GetMapping("/teamTimesheets") | ||||
fun getTeamMemberTimesheetEntries(): Map<Long, TeamMemberTimeEntries> { | fun getTeamMemberTimesheetEntries(): Map<Long, TeamMemberTimeEntries> { | ||||
return timesheetsService.getTimeMemberTimesheet() | |||||
return timesheetsService.getTeamMemberTimesheet() | |||||
} | |||||
@GetMapping("/teamLeaves") | |||||
fun getTeamMemberLeaveEntries(): Map<Long, TeamMemberLeaveEntries> { | |||||
return leaveService.getTeamMemberLeave() | |||||
} | } | ||||
@PostMapping("/saveMemberEntry") | @PostMapping("/saveMemberEntry") | ||||
@@ -57,6 +59,13 @@ class TimesheetsController(private val timesheetsService: TimesheetsService, pri | |||||
}.getOrNull()) | }.getOrNull()) | ||||
} | } | ||||
@PostMapping("/saveMemberLeave") | |||||
fun saveMemberLeave(@Valid @RequestBody request: TeamLeaveEntry): Map<String, List<LeaveEntry>> { | |||||
return leaveService.saveMemberLeaveEntry(request.staffId, request.entry, runCatching { | |||||
LocalDate.parse(request.recordDate, DateTimeFormatter.ISO_LOCAL_DATE) | |||||
}.getOrNull()) | |||||
} | |||||
@GetMapping("/leaves") | @GetMapping("/leaves") | ||||
fun getLeaveEntry(): Map<String, List<LeaveEntry>> { | fun getLeaveEntry(): Map<String, List<LeaveEntry>> { | ||||
return leaveService.getLeaves() | return leaveService.getLeaves() | ||||
@@ -0,0 +1,7 @@ | |||||
package com.ffii.tsms.modules.timesheet.web.models | |||||
data class TeamLeaveEntry( | |||||
val staffId: Long, | |||||
val entry: LeaveEntry, | |||||
val recordDate: String, | |||||
) |
@@ -0,0 +1,7 @@ | |||||
package com.ffii.tsms.modules.timesheet.web.models | |||||
data class TeamMemberLeaveEntries( | |||||
val leaveEntries: Map<String, List<LeaveEntry>>, | |||||
val staffId: String?, | |||||
val name: String?, | |||||
) |