Browse Source

add timesheet import

tags/Baseline_30082024_BACKEND_UAT
cyril.tsui 1 year ago
parent
commit
c760a08a49
3 changed files with 105 additions and 5 deletions
  1. +2
    -2
      src/main/java/com/ffii/tsms/modules/project/service/ProjectsService.kt
  2. +81
    -3
      src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt
  3. +22
    -0
      src/main/java/com/ffii/tsms/modules/timesheet/web/TimesheetsController.kt

+ 2
- 2
src/main/java/com/ffii/tsms/modules/project/service/ProjectsService.kt View File

@@ -480,7 +480,7 @@ open class ProjectsService(
for (i in 2..<sheet.lastRowNum) { for (i in 2..<sheet.lastRowNum) {
val row = sheet.getRow(i) val row = sheet.getRow(i)


if (row.getCell(0) != null && !row.getCell(0).stringCellValue.isNullOrBlank()) {
if (row?.getCell(0) != null && !row.getCell(0).stringCellValue.isNullOrBlank()) {
logger.info("row :$i | lastCellNum" + row.lastCellNum) logger.info("row :$i | lastCellNum" + row.lastCellNum)


// process client // process client
@@ -659,7 +659,7 @@ open class ProjectsService(
projectId = projectId, projectId = projectId,
projectStatus = "On-going", projectStatus = "On-going",
clientContactId = null, clientContactId = null,
isSubsidiaryContact = subsidiary?.id != null && subsidiary.id > 0,
isSubsidiaryContact = subsidiary?.id != null && subsidiary.id!! > 0,
manhourPercentageByGrade = taskTemplate.gradeAllocations.associateBy( manhourPercentageByGrade = taskTemplate.gradeAllocations.associateBy(
keySelector = { it.grade!!.id!! }, keySelector = { it.grade!!.id!! },
valueTransform = { it.percentage!! } valueTransform = { it.percentage!! }


+ 81
- 3
src/main/java/com/ffii/tsms/modules/timesheet/service/TimesheetsService.kt View File

@@ -1,17 +1,22 @@
package com.ffii.tsms.modules.timesheet.service package com.ffii.tsms.modules.timesheet.service


import com.ffii.core.exception.BadRequestException import com.ffii.core.exception.BadRequestException
import com.ffii.core.utils.ExcelUtils
import com.ffii.tsms.modules.data.entity.BuildingType
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.WorkNature
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.data.service.TeamService
import com.ffii.tsms.modules.project.entity.ProjectRepository
import com.ffii.tsms.modules.project.entity.ProjectTaskRepository
import com.ffii.tsms.modules.project.entity.TaskRepository
import com.ffii.tsms.modules.project.entity.*
import com.ffii.tsms.modules.project.web.models.*
import com.ffii.tsms.modules.timesheet.entity.Timesheet import com.ffii.tsms.modules.timesheet.entity.Timesheet
import com.ffii.tsms.modules.timesheet.entity.TimesheetRepository import com.ffii.tsms.modules.timesheet.entity.TimesheetRepository
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.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.Workbook
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
@@ -159,4 +164,77 @@ open class TimesheetsService(
) } ) }
} }
} }

@Transactional(rollbackFor = [Exception::class])
open fun importFile(workbook: Workbook?): String {
val logger = LogFactory.getLog(javaClass)

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

val sheet: Sheet = workbook.getSheetAt(0)

val timesheetList = mutableListOf<Timesheet>().toMutableList();
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()) {
logger.info("row :$i | lastCellNum" + row.lastCellNum)

// process staff
logger.info("---------staff-------")
var staff = staffRepository.findByStaffId(row.getCell(0).stringCellValue).getOrNull()
if (staff == null) {
staff = staffRepository.findByStaffId("B000").orElseThrow()
}

// process project
logger.info("---------project-------")
var projectCode = StringBuilder(row.getCell(3).stringCellValue).insert(1, '-').toString()

if (projectCode.contains('(')) {
val splitProjectCode = projectCode.split('(')
val splitMainProjectCode = splitProjectCode[0].split('-')
projectCode = splitMainProjectCode[0] + '-' + String.format("%04d", splitMainProjectCode[1].toInt()) + '-' + String.format("%03d", splitProjectCode[1].split(')')[0].toInt())
} else {
val splitProjectCode = projectCode.split('-')
projectCode = splitProjectCode[0] + '-' + String.format("%04d", splitProjectCode[1].toInt())
}
logger.info("Project Code: $projectCode")

val project = projectRepository.findByCode(projectCode)

// process project task
logger.info("---------project task-------")
val task = taskRepository.findById(41).getOrNull()
val projectTask = project?.let { p -> task?.let { t -> projectTaskRepository.findByProjectAndTask(p, t) } }

// process record date
logger.info("---------record date-------")
val formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy")
val recordDate = LocalDate.parse(row.getCell(6).toString(), formatter);

// 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

timesheetList += Timesheet().apply {
this.staff = staff
this.recordDate = recordDate
this.normalConsumed = normalHours
this.otConsumed = otHours
this.projectTask = projectTask
this.project = project
}
}
}

timesheetRepository.saveAll(timesheetList)
logger.info("---------end-------")

return if (sheet.lastRowNum > 0) "Import Excel success" else "Import Excel failure"
}
} }

+ 22
- 0
src/main/java/com/ffii/tsms/modules/timesheet/web/TimesheetsController.kt View File

@@ -5,12 +5,18 @@ 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.* import com.ffii.tsms.modules.timesheet.web.models.*
import jakarta.servlet.http.HttpServletRequest
import jakarta.validation.Valid import jakarta.validation.Valid
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.ServletRequestBindingException
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
import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
import org.springframework.web.multipart.MultipartHttpServletRequest
import java.time.LocalDate import java.time.LocalDate
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter


@@ -85,4 +91,20 @@ class TimesheetsController(private val timesheetsService: TimesheetsService, pri
fun leaveTypes(): List<LeaveType> { fun leaveTypes(): List<LeaveType> {
return leaveService.getLeaveTypes() return leaveService.getLeaveTypes()
} }

@PostMapping("/import")
@Throws(ServletRequestBindingException::class)
fun importFile(request: HttpServletRequest): ResponseEntity<*> {
var workbook: Workbook? = null

try {
val multipartFile = (request as MultipartHttpServletRequest).getFile("multipartFileList")
workbook = XSSFWorkbook(multipartFile?.inputStream)
} catch (e: Exception) {
println("Excel Wrong")
println(e)
}

return ResponseEntity.ok(timesheetsService.importFile(workbook))
}
} }

Loading…
Cancel
Save