Selaa lähdekoodia

Update Import timesheet function

add_swagger
cyril.tsui 9 kuukautta sitten
vanhempi
commit
bb18fd66f2
4 muutettua tiedostoa jossa 150 lisäystä ja 34 poistoa
  1. +25
    -0
      src/main/java/com/ffii/tsms/modules/timesheet/entity/FormerStaffTimesheetHistory.kt
  2. +7
    -0
      src/main/java/com/ffii/tsms/modules/timesheet/entity/FormerStaffTimesheetHistoryRepository.kt
  3. +96
    -34
      src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt
  4. +22
    -0
      src/main/resources/db/changelog/changes/20241107_01_cyril/01_create_former_staff_timesheet_history_table.sql

+ 25
- 0
src/main/java/com/ffii/tsms/modules/timesheet/entity/FormerStaffTimesheetHistory.kt Näytä tiedosto

@@ -0,0 +1,25 @@
package com.ffii.tsms.modules.timesheet.entity

import com.ffii.core.entity.BaseEntity
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.JoinColumn
import jakarta.persistence.OneToOne
import jakarta.persistence.Table

// Update when 'Timesheet' migration
@Entity
@Table(name = "former_staff_timesheet_history")
open class FormerStaffTimesheetHistory : BaseEntity<Long>() {

@JoinColumn(name = "timesheetId")
@OneToOne
open var timesheet: Timesheet? = null

@Column(name = "staffId")
open var staffId: String? = null

// Master Id from other company
@Column(name = "mtsid")
open var mtsid: Int? = null
}

+ 7
- 0
src/main/java/com/ffii/tsms/modules/timesheet/entity/FormerStaffTimesheetHistoryRepository.kt Näytä tiedosto

@@ -0,0 +1,7 @@
package com.ffii.tsms.modules.timesheet.entity

import com.ffii.core.support.AbstractRepository

interface FormerStaffTimesheetHistoryRepository : AbstractRepository<FormerStaffTimesheetHistory, Long> {

}

+ 96
- 34
src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt Näytä tiedosto

@@ -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.TeamService
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.TimeEntry
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.Workbook
import org.springframework.stereotype.Service
@@ -38,7 +36,9 @@ open class TimesheetsService(
private val teamService: TeamService,
private val teamLogService: TeamLogService,
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,
) : AbstractBaseEntityService<Timesheet, Long, TimesheetRepository>(jdbcDao, timesheetRepository) {
@Transactional
@@ -173,15 +173,19 @@ open class TimesheetsService(
}
}

data class FormerStaff(val staffId: String, val mtsid: Int)

@Transactional(rollbackFor = [Exception::class])
open fun importFile(workbook: Workbook?): String {
val logger = LogFactory.getLog(javaClass)
val formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy")

if (workbook == null) {
return "No Excel import" // if workbook is null
}

val notExistProjectList = mutableListOf<String>()
val formerStaffList = mutableListOf<FormerStaff>()
val sheet: Sheet = workbook.getSheetAt(0)

logger.info("---------Start Import Timesheets-------")
@@ -189,30 +193,50 @@ open class TimesheetsService(
for (i in 1..<sheet.lastRowNum) {
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)

// process 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) {
staff = staffRepository.findByStaffId("B000").orElseThrow()
formerStaffList += FormerStaff(
staffId = staffId,
mtsid = mtsid
)
}

// process 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('-')
projectCode = splitMainProjectCode[0] + '-' + String.format(
"%04d",
splitMainProjectCode[1].toInt()
) + '-' + String.format("%03d", subCode.toInt())
) + '-' + projectSubCode
} else {
val splitProjectCode = projectCode.split('-')
projectCode = splitProjectCode[0] + '-' + String.format("%04d", splitProjectCode[1].toInt())
@@ -229,14 +253,13 @@ open class TimesheetsService(

// process 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
logger.info("---------normal hour + ot hour-------")
val hours: Double = row.getCell(7).numericCellValue
val normalHours = if (hours > 8.0) 8.0 else hours
val otHours = if (hours > 8.0) hours - 8.0 else 0.0
logger.info("Normal Hours: $normalHours | OT Hours: $otHours")

if (project != null) {
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])
open fun importOSFile(workbook: Workbook?): String {
val logger = LogFactory.getLog(javaClass)
val formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy")

if (workbook == null) {
return "No Excel import" // if workbook is null
}

val notExistStaffIdList = mutableListOf<String>()
val formerStaffList = mutableListOf<FormerStaff>()
val sheet: Sheet = workbook.getSheetAt(0)

logger.info("---------Start Import OS Timesheets-------")
@@ -276,18 +317,26 @@ open class TimesheetsService(
for (i in 1..<sheet.lastRowNum) {
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)

// process staff
logger.info("---------staff-------")
var staff = staffRepository.findByStaffId(row.getCell(1).stringCellValue).getOrNull()
var staff = staffRepository.findByStaffId(staffId).getOrNull()
if (staff == null) {
notExistStaffIdList += row.getCell(1).stringCellValue
staff = staffRepository.findByStaffId("B000").orElseThrow()
formerStaffList += FormerStaff(
staffId = staffId,
mtsid = mtsid
)
}

// process project
@@ -300,14 +349,12 @@ open class TimesheetsService(
val projectTask = null

val nonBillableTask = taskRepository.findById(42).orElseThrow()

// process 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
logger.info("---------normal hour + ot hour-------")
val hours: Double = row.getCell(8).numericCellValue
val normalHours = if (hours > 8.0) 8.0 else hours
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(
projectId: Long,


+ 22
- 0
src/main/resources/db/changelog/changes/20241107_01_cyril/01_create_former_staff_timesheet_history_table.sql Näytä tiedosto

@@ -0,0 +1,22 @@
-- liquibase formatted sql

-- changeset cyril:former_staff_timesheet_history
CREATE TABLE `former_staff_timesheet_history` (
`id` INT NOT NULL AUTO_INCREMENT,
`version` INT NOT NULL DEFAULT '0',
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdBy` VARCHAR(30) CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci' NULL DEFAULT NULL,
`modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modifiedBy` VARCHAR(30) CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci' NULL DEFAULT NULL,
`deleted` TINYINT(1) NOT NULL DEFAULT '0',
`timesheetId` INT NULL,
`staffId` VARCHAR(30) NULL,
`mtsid` INT NULL,
PRIMARY KEY (`id`),
INDEX `FK_STAFF_ON_TIMESHEETID` (`timesheetId` ASC) VISIBLE,
CONSTRAINT `FK_STAFF_ON_TIMESHEETID`
FOREIGN KEY (`timesheetId`)
REFERENCES `timesheet` (`id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT)
;

Ladataan…
Peruuta
Tallenna