瀏覽代碼

Merge branch 'master' of https://git.2fi-solutions.com/davidhui/TSMS-backend

tags/Baseline_30082024_BACKEND_UAT
MSI\2Fi 1 年之前
父節點
當前提交
d87520f624
共有 4 個檔案被更改,包括 100 行新增41 行删除
  1. +79
    -31
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  2. +10
    -8
      src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt
  3. +11
    -2
      src/main/java/com/ffii/tsms/modules/timesheet/entity/projections/MonthlyHours.kt
  4. 二進制
      src/main/resources/templates/report/AR08_Monthly Work Hours Analysis Report.xlsx

+ 79
- 31
src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt 查看文件

@@ -7,6 +7,9 @@ import com.ffii.tsms.modules.project.entity.Invoice
import com.ffii.tsms.modules.project.entity.Project
import com.ffii.tsms.modules.timesheet.entity.Leave
import com.ffii.tsms.modules.timesheet.entity.Timesheet
import com.ffii.tsms.modules.timesheet.entity.projections.MonthlyLeave
import com.ffii.tsms.modules.timesheet.entity.projections.ProjectMonthlyHoursWithDate
import com.ffii.tsms.modules.timesheet.entity.projections.TimesheetHours
import com.ffii.tsms.modules.timesheet.web.models.LeaveEntry
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
@@ -20,6 +23,7 @@ import org.springframework.stereotype.Service
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.math.BigDecimal
import java.sql.Time
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.*
@@ -121,9 +125,8 @@ open class ReportService(
fun generateStaffMonthlyWorkHourAnalysisReport(
month: LocalDate,
staff: Staff,
timesheets: List<Timesheet>,
leaves: List<Leave>,
projectList: List<String>
timesheets: List<Map<String, Any>>,
leaves: List<Map<String, Any>>,
): ByteArray {
// Generate the Excel report with query results
val workbook: Workbook = createStaffMonthlyWorkHourAnalysisReport(
@@ -131,7 +134,6 @@ open class ReportService(
staff,
timesheets,
leaves,
projectList,
MONTHLY_WORK_HOURS_ANALYSIS_REPORT
)

@@ -718,21 +720,35 @@ open class ReportService(
private fun createStaffMonthlyWorkHourAnalysisReport(
month: LocalDate,
staff: Staff,
timesheets: List<Timesheet>,
leaves: List<Leave>,
projectList: List<String>,
timesheets: List<Map<String, Any>>,
leaves: List<Map<String, Any>>,
templatePath: String,
): Workbook {
// val yearMonth = YearMonth.of(2022, 5) // May 2022
println("t $timesheets")
println("l $leaves")
println("p $projectList")
var projectList: List<String> = listOf()
println("----timesheets-----")
println(timesheets)
// result = timesheet record mapped
var result: Map<String, Any> = mapOf()
if (timesheets.isNotEmpty()) {
projectList = timesheets.map{ "${it["code"]}\n ${it["name"]}"}.toList()
result = timesheets.groupBy(
{ it["id"].toString() },
{ mapOf(
"date" to it["recordDate"],
"normalConsumed" to it["normalConsumed"],
"otConsumed" to it["otConsumed"],
) }
)
}
println("---result---")
println(result)
println("l $projectList")
val resource = ClassPathResource(templatePath)
val templateInputStream = resource.inputStream
val workbook: Workbook = XSSFWorkbook(templateInputStream)

val accountingStyle = workbook.createDataFormat().getFormat("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)")
val monthStyle = workbook.createDataFormat().getFormat("mmm, yyyy")
val monthStyle = workbook.createDataFormat().getFormat("MMM YYYY")
val dateStyle = workbook.createDataFormat().getFormat("dd/mm/yyyy")

val boldStyle = workbook.createCellStyle()
@@ -748,8 +764,6 @@ open class ReportService(

val sheet: Sheet = workbook.getSheetAt(0)

// sheet.forceFormulaRecalculation = true; //Calculate formulas

var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field
var columnIndex = 1

@@ -766,7 +780,6 @@ open class ReportService(
rowIndex = 2
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(month)
// cellStyle.setFont(boldStyle)

cellStyle.dataFormat = monthStyle
}
@@ -801,11 +814,9 @@ open class ReportService(
tempCell.setCellValue(dayInfo.date)
tempCell.cellStyle = boldStyle
tempCell.cellStyle.dataFormat = dateStyle
// cellStyle.alignment = HorizontalAlignment.LEFT
tempCell = sheet.getRow(rowIndex).createCell(1)
tempCell.setCellValue(dayInfo.weekday)
tempCell.cellStyle = boldStyle
// cellStyle.alignment = HorizontalAlignment.LEFT
}

rowIndex += 1
@@ -827,10 +838,11 @@ open class ReportService(
var normalConsumed = 0.0
var otConsumed = 0.0
var leaveHours = 0.0
// normalConsumed data
if (timesheets.isNotEmpty()) {
timesheets.forEach { t ->
normalConsumed += t.normalConsumed!!
otConsumed += t.otConsumed ?: 0.0
normalConsumed += t["normalConsumed"] as Double
otConsumed += t["otConsumed"] as Double
}
}
tempCell = sheet.getRow(rowIndex).createCell(2)
@@ -858,9 +870,10 @@ open class ReportService(
tempCell.cellStyle = boldStyle
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER)
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1))
// cal total leave hour
if (leaves.isNotEmpty()) {
leaves.forEach { l ->
leaveHours += l.leaveHours!!
leaveHours += l["leaveHours"] as Double
}
}
tempCell = sheet.getRow(rowIndex).createCell(2)
@@ -905,28 +918,30 @@ open class ReportService(
tempCell.setCellValue(0.0)
tempCell.cellStyle.dataFormat = accountingStyle
}
timesheets.forEach { timesheet ->
dayInt = timesheet.recordDate!!.dayOfMonth
tempCell = sheet.getRow(dayInt.plus(7)).createCell(columnIndex)
tempCell.setCellValue(timesheet.normalConsumed!!)

result.forEach{(id, list) ->
for (i in 0 until id.toInt()) {
val temp: List<Map<String, Any>> = list as List<Map<String, Any>>
temp.forEachIndexed { i, _ ->
dayInt = temp[i]["date"].toString().toInt()
tempCell = sheet.getRow(dayInt.plus(7)).createCell(columnIndex)
tempCell.setCellValue(temp[i]["normalConsumed"] as Double)
}
}
}
columnIndex++
}
}
// dates
// leave hours data
if (leaves.isNotEmpty()) {
leaves.forEach { leave ->
for (i in 0 until rowSize) {
tempCell = sheet.getRow(8 + i).createCell(columnIndex)
tempCell.setCellValue(0.0)
tempCell.cellStyle.dataFormat = accountingStyle

}
dayInt = leave.recordDate!!.dayOfMonth
dayInt = leave["recordDate"].toString().toInt()
tempCell = sheet.getRow(dayInt.plus(7)).createCell(columnIndex)
tempCell.setCellValue(leave.leaveHours!!)

tempCell.setCellValue(leave["leaveHours"] as Double)
}
}
///////////////////////////////////////////////////////// Leave Hours ////////////////////////////////////////////////////////////////////
@@ -1126,4 +1141,37 @@ open class ReportService(
return jdbcDao.queryForList(sql.toString(), args)
}

}
open fun getTimesheet(args: Map<String, Any>): List<Map<String, Any>> {
val sql = StringBuilder(
"SELECT"
+ " p.id,"
+ " p.name,"
+ " p.code,"
+ " CAST(DATE_FORMAT(t.recordDate, '%d') AS SIGNED) AS recordDate,"
+ " sum(t.normalConsumed) as normalConsumed,"
+ " IFNULL(sum(t.otConsumed), 0.0) as otConsumed"
+ " from timesheet t"
+ " left join project_task pt on t.projectTaskId = pt.id"
+ " left join project p on p.id = pt.project_id"
+ " where t.staffId = :staffId"
+ " group by p.id, t.recordDate"
+ " order by p.id, t.recordDate"
+ " and t.recordDate BETWEEN :startDate and :endDate"
)
return jdbcDao.queryForList(sql.toString(), args)
}
open fun getLeaves(args: Map<String, Any>): List<Map<String, Any>> {
val sql = StringBuilder(
" SELECT "
+ " sum(leaveHours) as leaveHours, "
+ " CAST(DATE_FORMAT(recordDate, '%d') AS SIGNED) AS recordDate "
+ " from `leave` "
+ " where staffId = :staffId "
+ " and recordDate BETWEEN :startDate and :endDate "
+ " group by recordDate "
+ " order by recordDate "
)
return jdbcDao.queryForList(sql.toString(), args)
}

}

+ 10
- 8
src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt 查看文件

@@ -11,6 +11,7 @@ import com.ffii.tsms.modules.report.web.model.ProjectCashFlowReportRequest
import com.ffii.tsms.modules.report.web.model.StaffMonthlyWorkHourAnalysisReportRequest
import com.ffii.tsms.modules.timesheet.entity.LeaveRepository
import com.ffii.tsms.modules.timesheet.entity.TimesheetRepository
import com.ffii.tsms.modules.timesheet.entity.projections.ProjectMonthlyHoursWithDate
import jakarta.validation.Valid
import org.springframework.core.io.ByteArrayResource
import org.springframework.core.io.Resource
@@ -78,14 +79,15 @@ class ReportController(
val nextMonth = request.yearMonth.plusMonths(1).atDay(1)

val staff = staffRepository.findById(request.id).orElseThrow()
val timesheets = timesheetRepository.findByStaffAndRecordDateBetweenOrderByRecordDate(staff, thisMonth, nextMonth)
val leaves = leaveRepository.findByStaffAndRecordDateBetweenOrderByRecordDate(staff, thisMonth, nextMonth)

val projects = timesheetRepository.findDistinctProjectTaskByStaffAndRecordDateBetweenOrderByRecordDate(staff, thisMonth, nextMonth)
val projectList: List<String> = projects.map { p -> "${p.projectTask!!.project!!.code}\n ${p.projectTask!!.project!!.name}" }


val reportResult: ByteArray = excelReportService.generateStaffMonthlyWorkHourAnalysisReport(thisMonth, staff, timesheets, leaves, projectList)
val args: Map<String, Any> = mutableMapOf(
"staffId" to request.id,
"startDate" to thisMonth,
"endDate" to nextMonth,
)
val timesheets= excelReportService.getTimesheet(args)
val leaves= excelReportService.getLeaves(args)

val reportResult: ByteArray = excelReportService.generateStaffMonthlyWorkHourAnalysisReport(thisMonth, staff, timesheets, leaves)
// val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
return ResponseEntity.ok()
// .contentType(mediaType)


+ 11
- 2
src/main/java/com/ffii/tsms/modules/timesheet/entity/projections/MonthlyHours.kt 查看文件

@@ -2,7 +2,16 @@ package com.ffii.tsms.modules.timesheet.entity.projections

import java.time.LocalDate

data class MonthlyHours(
data class MonthlyLeave(
val date: LocalDate,
val nomralConsumed: Number
val leaveHours: Double
)

data class ProjectMonthlyHoursWithDate(
val id: Long,
val name: String,
val code: String,
val date: LocalDate,
val normalConsumed: Double,
val otConsumed: Double,
)

二進制
src/main/resources/templates/report/AR08_Monthly Work Hours Analysis Report.xlsx 查看文件


Loading…
取消
儲存