|
@@ -11,13 +11,11 @@ import com.ffii.tsms.modules.data.service.StaffsService |
|
|
import com.ffii.tsms.modules.data.service.TeamLogService |
|
|
import com.ffii.tsms.modules.data.service.TeamLogService |
|
|
import com.ffii.tsms.modules.data.service.TeamService |
|
|
import com.ffii.tsms.modules.data.service.TeamService |
|
|
import com.ffii.tsms.modules.project.entity.* |
|
|
import com.ffii.tsms.modules.project.entity.* |
|
|
import com.ffii.tsms.modules.timesheet.entity.Leave |
|
|
|
|
|
import com.ffii.tsms.modules.timesheet.entity.LeaveRepository |
|
|
|
|
|
import com.ffii.tsms.modules.timesheet.entity.Timesheet |
|
|
|
|
|
import com.ffii.tsms.modules.timesheet.entity.TimesheetRepository |
|
|
|
|
|
|
|
|
import com.ffii.tsms.modules.timesheet.entity.* |
|
|
import com.ffii.tsms.modules.timesheet.web.models.TeamMemberTimeEntries |
|
|
import com.ffii.tsms.modules.timesheet.web.models.TeamMemberTimeEntries |
|
|
import com.ffii.tsms.modules.timesheet.web.models.TimeEntry |
|
|
import com.ffii.tsms.modules.timesheet.web.models.TimeEntry |
|
|
import org.apache.commons.logging.LogFactory |
|
|
import org.apache.commons.logging.LogFactory |
|
|
|
|
|
import org.apache.poi.ss.usermodel.CellType |
|
|
import org.apache.poi.ss.usermodel.Sheet |
|
|
import org.apache.poi.ss.usermodel.Sheet |
|
|
import org.apache.poi.ss.usermodel.Workbook |
|
|
import org.apache.poi.ss.usermodel.Workbook |
|
|
import org.springframework.stereotype.Service |
|
|
import org.springframework.stereotype.Service |
|
@@ -38,7 +36,9 @@ open class TimesheetsService( |
|
|
private val teamService: TeamService, |
|
|
private val teamService: TeamService, |
|
|
private val teamLogService: TeamLogService, |
|
|
private val teamLogService: TeamLogService, |
|
|
private val salaryEffectiveService: SalaryEffectiveService, |
|
|
private val salaryEffectiveService: SalaryEffectiveService, |
|
|
private val staffRepository: StaffRepository, private val leaveRepository: LeaveRepository, |
|
|
|
|
|
|
|
|
private val staffRepository: StaffRepository, |
|
|
|
|
|
private val leaveRepository: LeaveRepository, |
|
|
|
|
|
private val formerStaffTimesheetHistoryRepository: FormerStaffTimesheetHistoryRepository, |
|
|
private val jdbcDao: JdbcDao, |
|
|
private val jdbcDao: JdbcDao, |
|
|
) : AbstractBaseEntityService<Timesheet, Long, TimesheetRepository>(jdbcDao, timesheetRepository) { |
|
|
) : AbstractBaseEntityService<Timesheet, Long, TimesheetRepository>(jdbcDao, timesheetRepository) { |
|
|
@Transactional |
|
|
@Transactional |
|
@@ -173,15 +173,19 @@ open class TimesheetsService( |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
data class FormerStaff(val staffId: String, val mtsid: Int) |
|
|
|
|
|
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
open fun importFile(workbook: Workbook?): String { |
|
|
open fun importFile(workbook: Workbook?): String { |
|
|
val logger = LogFactory.getLog(javaClass) |
|
|
val logger = LogFactory.getLog(javaClass) |
|
|
|
|
|
val formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy") |
|
|
|
|
|
|
|
|
if (workbook == null) { |
|
|
if (workbook == null) { |
|
|
return "No Excel import" // if workbook is null |
|
|
return "No Excel import" // if workbook is null |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val notExistProjectList = mutableListOf<String>() |
|
|
val notExistProjectList = mutableListOf<String>() |
|
|
|
|
|
val formerStaffList = mutableListOf<FormerStaff>() |
|
|
val sheet: Sheet = workbook.getSheetAt(0) |
|
|
val sheet: Sheet = workbook.getSheetAt(0) |
|
|
|
|
|
|
|
|
logger.info("---------Start Import Timesheets-------") |
|
|
logger.info("---------Start Import Timesheets-------") |
|
@@ -189,30 +193,50 @@ open class TimesheetsService( |
|
|
for (i in 1..<sheet.lastRowNum) { |
|
|
for (i in 1..<sheet.lastRowNum) { |
|
|
val row = sheet.getRow(i) |
|
|
val row = sheet.getRow(i) |
|
|
|
|
|
|
|
|
if (row?.getCell(0) != null && !row.getCell(0).stringCellValue.isNullOrBlank() && row.getCell(3) != null && !row.getCell( |
|
|
|
|
|
3 |
|
|
|
|
|
).stringCellValue.isNullOrBlank() |
|
|
|
|
|
) { |
|
|
|
|
|
|
|
|
// Necessary Cell Value |
|
|
|
|
|
val mtsid = row.getCell(0).numericCellValue.toInt() |
|
|
|
|
|
val staffId = row.getCell(1).stringCellValue |
|
|
|
|
|
var projectCode = when (row.getCell(4).stringCellValue.isNullOrBlank()) { |
|
|
|
|
|
true -> "" |
|
|
|
|
|
false -> StringBuilder(row.getCell(4).stringCellValue).insert(1, '-').toString() |
|
|
|
|
|
} |
|
|
|
|
|
val projectSubCode = when (row.getCell(5)?.cellType) { |
|
|
|
|
|
CellType.STRING -> row.getCell(5).stringCellValue.padStart(3, '0') |
|
|
|
|
|
CellType.NUMERIC -> row.getCell(5).numericCellValue.toString().padStart(3, '0') |
|
|
|
|
|
else -> "" |
|
|
|
|
|
} |
|
|
|
|
|
val recordDate = when (row.getCell(7).toString().isBlank()) { |
|
|
|
|
|
true -> null |
|
|
|
|
|
false -> LocalDate.parse(row.getCell(7).toString(), formatter); |
|
|
|
|
|
} |
|
|
|
|
|
val hours: Double = row.getCell(8).numericCellValue |
|
|
|
|
|
|
|
|
|
|
|
// Start Process |
|
|
|
|
|
if (!staffId.isNullOrBlank() && projectCode.isNotBlank()) { |
|
|
logger.info("row :$i | lastCellNum" + row.lastCellNum) |
|
|
logger.info("row :$i | lastCellNum" + row.lastCellNum) |
|
|
|
|
|
|
|
|
// process staff |
|
|
// process staff |
|
|
logger.info("---------staff-------") |
|
|
logger.info("---------staff-------") |
|
|
var staff = staffRepository.findByStaffId(row.getCell(0).stringCellValue).getOrNull() |
|
|
|
|
|
|
|
|
logger.info("mtsid: $mtsid") |
|
|
|
|
|
logger.info("Staff ID: $staffId") |
|
|
|
|
|
var staff = staffRepository.findByStaffId(staffId).getOrNull() |
|
|
if (staff == null) { |
|
|
if (staff == null) { |
|
|
staff = staffRepository.findByStaffId("B000").orElseThrow() |
|
|
staff = staffRepository.findByStaffId("B000").orElseThrow() |
|
|
|
|
|
formerStaffList += FormerStaff( |
|
|
|
|
|
staffId = staffId, |
|
|
|
|
|
mtsid = mtsid |
|
|
|
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// process project |
|
|
// process project |
|
|
logger.info("---------project-------") |
|
|
logger.info("---------project-------") |
|
|
var projectCode = StringBuilder(row.getCell(3).stringCellValue).insert(1, '-').toString() |
|
|
|
|
|
|
|
|
|
|
|
if (row.getCell(4) != null && row.getCell(4).toString().isNotBlank()) { |
|
|
|
|
|
val subCode = row.getCell(4).numericCellValue |
|
|
|
|
|
|
|
|
if (projectSubCode.isNotBlank()) { |
|
|
val splitMainProjectCode = projectCode.split('-') |
|
|
val splitMainProjectCode = projectCode.split('-') |
|
|
projectCode = splitMainProjectCode[0] + '-' + String.format( |
|
|
projectCode = splitMainProjectCode[0] + '-' + String.format( |
|
|
"%04d", |
|
|
"%04d", |
|
|
splitMainProjectCode[1].toInt() |
|
|
splitMainProjectCode[1].toInt() |
|
|
) + '-' + String.format("%03d", subCode.toInt()) |
|
|
|
|
|
|
|
|
) + '-' + projectSubCode |
|
|
} else { |
|
|
} else { |
|
|
val splitProjectCode = projectCode.split('-') |
|
|
val splitProjectCode = projectCode.split('-') |
|
|
projectCode = splitProjectCode[0] + '-' + String.format("%04d", splitProjectCode[1].toInt()) |
|
|
projectCode = splitProjectCode[0] + '-' + String.format("%04d", splitProjectCode[1].toInt()) |
|
@@ -229,14 +253,13 @@ open class TimesheetsService( |
|
|
|
|
|
|
|
|
// process record date |
|
|
// process record date |
|
|
logger.info("---------record date-------") |
|
|
logger.info("---------record date-------") |
|
|
val formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy") |
|
|
|
|
|
val recordDate = LocalDate.parse(row.getCell(6).toString(), formatter); |
|
|
|
|
|
|
|
|
logger.info("Recode Date: $recordDate") |
|
|
|
|
|
|
|
|
// normal hour + ot hour |
|
|
// normal hour + ot hour |
|
|
logger.info("---------normal hour + ot hour-------") |
|
|
logger.info("---------normal hour + ot hour-------") |
|
|
val hours: Double = row.getCell(7).numericCellValue |
|
|
|
|
|
val normalHours = if (hours > 8.0) 8.0 else hours |
|
|
val normalHours = if (hours > 8.0) 8.0 else hours |
|
|
val otHours = if (hours > 8.0) hours - 8.0 else 0.0 |
|
|
val otHours = if (hours > 8.0) hours - 8.0 else 0.0 |
|
|
|
|
|
logger.info("Normal Hours: $normalHours | OT Hours: $otHours") |
|
|
|
|
|
|
|
|
if (project != null) { |
|
|
if (project != null) { |
|
|
timesheetList += Timesheet().apply { |
|
|
timesheetList += Timesheet().apply { |
|
@@ -253,22 +276,40 @@ open class TimesheetsService( |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
timesheetRepository.saveAll(timesheetList) |
|
|
|
|
|
logger.info("---------end-------") |
|
|
|
|
|
logger.info("Not Exist Project List: "+ notExistProjectList.distinct().joinToString(", ")) |
|
|
|
|
|
|
|
|
val savedTimesheetList = timesheetRepository.saveAll(timesheetList) |
|
|
|
|
|
logger.info("---------End Of Import Timesheet-------") |
|
|
|
|
|
logger.info("---------Start Insert Former Staff Timesheet History-------") |
|
|
|
|
|
|
|
|
|
|
|
val formerStaffTimesheetHistoryList = mutableListOf<FormerStaffTimesheetHistory>() |
|
|
|
|
|
savedTimesheetList.filter { it.staff?.staffId == "B000" }.zip(formerStaffList).forEach {(savedTimesheet: Timesheet, formerStaff: FormerStaff) -> |
|
|
|
|
|
logger.info("Staff ID: ${formerStaff.staffId} | mtsid: ${formerStaff.mtsid}") |
|
|
|
|
|
formerStaffTimesheetHistoryList += FormerStaffTimesheetHistory().apply { |
|
|
|
|
|
this.timesheet = savedTimesheet |
|
|
|
|
|
this.staffId = formerStaff.staffId |
|
|
|
|
|
this.mtsid = formerStaff.mtsid |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
formerStaffTimesheetHistoryRepository.saveAll(formerStaffTimesheetHistoryList.filter { it.mtsid != null }) |
|
|
|
|
|
logger.info("---------End-------") |
|
|
|
|
|
val notExistProjects = notExistProjectList.distinct().joinToString(", ") |
|
|
|
|
|
val notExistStaffs = formerStaffTimesheetHistoryList.map { it.staffId }.distinct().joinToString(", ") |
|
|
|
|
|
logger.info("Not Exist Project List: $notExistProjects") |
|
|
|
|
|
logger.info("Not Exist Staff List: $notExistStaffs") |
|
|
|
|
|
|
|
|
return if (sheet.lastRowNum > 0) "Import Excel success btw " + notExistProjectList.distinct().joinToString(", ") else "Import Excel failure" |
|
|
|
|
|
|
|
|
return if (sheet.lastRowNum > 0) "Import Excel success btw not exist project list: $notExistProjects ; not exist staff list: $notExistStaffs" else "Import Excel failure" |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
open fun importOSFile(workbook: Workbook?): String { |
|
|
open fun importOSFile(workbook: Workbook?): String { |
|
|
val logger = LogFactory.getLog(javaClass) |
|
|
val logger = LogFactory.getLog(javaClass) |
|
|
|
|
|
val formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy") |
|
|
|
|
|
|
|
|
if (workbook == null) { |
|
|
if (workbook == null) { |
|
|
return "No Excel import" // if workbook is null |
|
|
return "No Excel import" // if workbook is null |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val notExistStaffIdList = mutableListOf<String>() |
|
|
|
|
|
|
|
|
val formerStaffList = mutableListOf<FormerStaff>() |
|
|
val sheet: Sheet = workbook.getSheetAt(0) |
|
|
val sheet: Sheet = workbook.getSheetAt(0) |
|
|
|
|
|
|
|
|
logger.info("---------Start Import OS Timesheets-------") |
|
|
logger.info("---------Start Import OS Timesheets-------") |
|
@@ -276,18 +317,26 @@ open class TimesheetsService( |
|
|
for (i in 1..<sheet.lastRowNum) { |
|
|
for (i in 1..<sheet.lastRowNum) { |
|
|
val row = sheet.getRow(i) |
|
|
val row = sheet.getRow(i) |
|
|
|
|
|
|
|
|
if (row.getCell(1) != null && !row.getCell( |
|
|
|
|
|
1 |
|
|
|
|
|
).stringCellValue.isNullOrBlank() |
|
|
|
|
|
) { |
|
|
|
|
|
|
|
|
val mtsid = row.getCell(0).numericCellValue.toInt() |
|
|
|
|
|
val staffId = row.getCell(1).stringCellValue |
|
|
|
|
|
val recordDate = when (row.getCell(7).toString().isBlank()) { |
|
|
|
|
|
true -> null |
|
|
|
|
|
false -> LocalDate.parse(row.getCell(7).toString(), formatter); |
|
|
|
|
|
} |
|
|
|
|
|
val hours: Double = row.getCell(8).numericCellValue |
|
|
|
|
|
|
|
|
|
|
|
if (!staffId.isNullOrBlank()) { |
|
|
logger.info("row :$i | lastCellNum" + row.lastCellNum) |
|
|
logger.info("row :$i | lastCellNum" + row.lastCellNum) |
|
|
|
|
|
|
|
|
// process staff |
|
|
// process staff |
|
|
logger.info("---------staff-------") |
|
|
logger.info("---------staff-------") |
|
|
var staff = staffRepository.findByStaffId(row.getCell(1).stringCellValue).getOrNull() |
|
|
|
|
|
|
|
|
var staff = staffRepository.findByStaffId(staffId).getOrNull() |
|
|
if (staff == null) { |
|
|
if (staff == null) { |
|
|
notExistStaffIdList += row.getCell(1).stringCellValue |
|
|
|
|
|
staff = staffRepository.findByStaffId("B000").orElseThrow() |
|
|
staff = staffRepository.findByStaffId("B000").orElseThrow() |
|
|
|
|
|
formerStaffList += FormerStaff( |
|
|
|
|
|
staffId = staffId, |
|
|
|
|
|
mtsid = mtsid |
|
|
|
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// process project |
|
|
// process project |
|
@@ -300,14 +349,12 @@ open class TimesheetsService( |
|
|
val projectTask = null |
|
|
val projectTask = null |
|
|
|
|
|
|
|
|
val nonBillableTask = taskRepository.findById(42).orElseThrow() |
|
|
val nonBillableTask = taskRepository.findById(42).orElseThrow() |
|
|
|
|
|
|
|
|
// process record date |
|
|
// process record date |
|
|
logger.info("---------record date-------") |
|
|
logger.info("---------record date-------") |
|
|
val formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy") |
|
|
|
|
|
val recordDate = LocalDate.parse(row.getCell(7).toString(), formatter); |
|
|
|
|
|
|
|
|
|
|
|
// normal hour + ot hour |
|
|
// normal hour + ot hour |
|
|
logger.info("---------normal hour + ot hour-------") |
|
|
logger.info("---------normal hour + ot hour-------") |
|
|
val hours: Double = row.getCell(8).numericCellValue |
|
|
|
|
|
val normalHours = if (hours > 8.0) 8.0 else hours |
|
|
val normalHours = if (hours > 8.0) 8.0 else hours |
|
|
val otHours = if (hours > 8.0) hours - 8.0 else 0.0 |
|
|
val otHours = if (hours > 8.0) hours - 8.0 else 0.0 |
|
|
|
|
|
|
|
@@ -323,10 +370,25 @@ open class TimesheetsService( |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
timesheetRepository.saveAll(timesheetList) |
|
|
|
|
|
logger.info("---------end-------") |
|
|
|
|
|
|
|
|
val savedTimesheetList = timesheetRepository.saveAll(timesheetList) |
|
|
|
|
|
logger.info("---------End Of Import Timesheet-------") |
|
|
|
|
|
logger.info("---------Start Insert Former Staff Timesheet History-------") |
|
|
|
|
|
val formerStaffTimesheetHistoryList = mutableListOf<FormerStaffTimesheetHistory>() |
|
|
|
|
|
savedTimesheetList.filter { it.staff?.staffId == "B000" }.zip(formerStaffList).forEach {(savedTimesheet: Timesheet, formerStaffList: FormerStaff) -> |
|
|
|
|
|
formerStaffTimesheetHistoryList += FormerStaffTimesheetHistory().apply { |
|
|
|
|
|
this.timesheet = savedTimesheet |
|
|
|
|
|
this.staffId = formerStaffList.staffId |
|
|
|
|
|
this.mtsid = formerStaffList.mtsid |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
formerStaffTimesheetHistoryRepository.saveAll(formerStaffTimesheetHistoryList) |
|
|
|
|
|
logger.info("---------End-------") |
|
|
|
|
|
|
|
|
|
|
|
val notExistStaffs = formerStaffTimesheetHistoryList.map { it.staffId }.distinct().joinToString(", ") |
|
|
|
|
|
logger.info("Not Exist Staff List: $notExistStaffs") |
|
|
|
|
|
|
|
|
return if (sheet.lastRowNum > 0) "Import Excel success btw staffId:" + notExistStaffIdList.distinct().joinToString(", ") else "Import Excel failure" |
|
|
|
|
|
|
|
|
return if (sheet.lastRowNum > 0) "Import Excel success btw staffId: : $notExistStaffs" else "Import Excel failure" |
|
|
} |
|
|
} |
|
|
open fun getManpowerExpenseByProjectId( |
|
|
open fun getManpowerExpenseByProjectId( |
|
|
projectId: Long, |
|
|
projectId: Long, |
|
|