|
|
@@ -75,6 +75,7 @@ open class ReportService( |
|
|
|
private val CROSS_TEAM_CHARGE_REPORT = "templates/report/Cross Team Charge Report.xlsx" |
|
|
|
private val PROJECT_MANHOUR_SUMMARY = "templates/report/Project Manhour Summary.xlsx" |
|
|
|
private val PROJECT_MONTHLY_REPORT = "templates/report/AR09_Project Daily Work Hours Analysis Report.xlsx" |
|
|
|
private val LAST_RECORD_REPORT = "templates/report/AR10_Staff Last Record Report.xlsx" |
|
|
|
|
|
|
|
private fun cellBorderArgs(top: Int, bottom: Int, left: Int, right: Int): MutableMap<String, Any> { |
|
|
|
var cellBorderArgs = mutableMapOf<String, Any>() |
|
|
@@ -5652,4 +5653,145 @@ open class ReportService( |
|
|
|
|
|
|
|
return outputStream.toByteArray() |
|
|
|
} |
|
|
|
|
|
|
|
data class StaffLastRecordData( |
|
|
|
val staffId: String, |
|
|
|
val staffName: String, |
|
|
|
val email: String, |
|
|
|
val team: String, |
|
|
|
val lastRecordDate: String, |
|
|
|
) |
|
|
|
private fun getStaffLastRecordDateByDate(date: LocalDate): List<StaffLastRecordData>{ |
|
|
|
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") |
|
|
|
val sql = StringBuilder( |
|
|
|
"with cte_lastRecordDate as ( " + |
|
|
|
"select staffId, " + |
|
|
|
"max( timesheet.recordDate ) as lastRecordDate " + |
|
|
|
"from timesheet " + |
|
|
|
"group by staffId " + |
|
|
|
") " + |
|
|
|
"select " + |
|
|
|
"s.staffId, " + |
|
|
|
"s.name, " + |
|
|
|
"COALESCE(s.email, '') as email, " + |
|
|
|
"t.code as team, " + |
|
|
|
"lmd.lastRecordDate " + |
|
|
|
"from cte_lastRecordDate lmd " + |
|
|
|
"left join staff s on s.id = lmd.staffid " + |
|
|
|
"left join team t on s.teamId = t.id " + |
|
|
|
"where s.staffId != 'B000' and s.teamId != 7 " + |
|
|
|
"and lmd.lastrecorddate <= DATE_SUB(:searchDate, INTERVAL 7 DAY) " + |
|
|
|
"order by lmd.lastrecorddate " |
|
|
|
) |
|
|
|
|
|
|
|
val results = jdbcDao.queryForList(sql.toString(), mapOf("searchDate" to date.format(formatter))).map { |
|
|
|
result -> |
|
|
|
StaffLastRecordData( |
|
|
|
result["staffId"] as String, |
|
|
|
result["name"] as String, |
|
|
|
result["email"] as String, |
|
|
|
result["team"] as String, |
|
|
|
(result["lastRecordDate"] as java.sql.Date).toString() |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
return results |
|
|
|
} |
|
|
|
|
|
|
|
@Throws(IOException::class) |
|
|
|
private fun createLastRecordReportWorkbook( |
|
|
|
date: LocalDate, |
|
|
|
templatePath: String, |
|
|
|
): Workbook{ |
|
|
|
val resource = ClassPathResource(templatePath) |
|
|
|
val templateInputStream = resource.inputStream |
|
|
|
val workbook: Workbook = XSSFWorkbook(templateInputStream) |
|
|
|
|
|
|
|
val result = getStaffLastRecordDateByDate(date) |
|
|
|
println(result) |
|
|
|
|
|
|
|
var sheet: Sheet = workbook.getSheetAt(0) |
|
|
|
var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field |
|
|
|
var columnIndex = 1 |
|
|
|
|
|
|
|
val blackFont = workbook.createFont().apply { |
|
|
|
color = IndexedColors.BLACK.index |
|
|
|
fontHeightInPoints = 12 |
|
|
|
} |
|
|
|
|
|
|
|
val blackFontStyle = workbook.createCellStyle().apply { |
|
|
|
setFont(blackFont) |
|
|
|
borderTop = BorderStyle.THIN |
|
|
|
borderBottom = BorderStyle.THIN |
|
|
|
borderLeft = BorderStyle.THIN |
|
|
|
borderRight = BorderStyle.THIN |
|
|
|
} |
|
|
|
|
|
|
|
sheet.getRow(rowIndex).createCell(columnIndex+1).apply { |
|
|
|
setCellValue(FORMATTED_TODAY) |
|
|
|
} |
|
|
|
|
|
|
|
rowIndex = 2 |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex+1).apply { |
|
|
|
setCellValue(date.format(DATE_FORMATTER)) |
|
|
|
} |
|
|
|
|
|
|
|
rowIndex = 3 |
|
|
|
sheet.getRow(rowIndex).getCell(columnIndex+1).apply { |
|
|
|
setCellValue( "${result.size}" ) |
|
|
|
} |
|
|
|
|
|
|
|
var startRowIndex = 6 |
|
|
|
val startColumnIndex = 1 |
|
|
|
|
|
|
|
result.forEach { |
|
|
|
val row = if(sheet.getRow(startRowIndex) == null) sheet.createRow(startRowIndex) else sheet.getRow(startRowIndex) |
|
|
|
val staffIdCell = row.createCell(0) |
|
|
|
val staffNameCell = row.createCell(1) |
|
|
|
val emailCell = row.createCell(2) |
|
|
|
val teamCell = row.createCell(3) |
|
|
|
val lastRecordDateCell = row.createCell(4) |
|
|
|
|
|
|
|
staffIdCell.apply { |
|
|
|
setCellValue(it.staffId) |
|
|
|
cellStyle =blackFontStyle |
|
|
|
} |
|
|
|
|
|
|
|
staffNameCell.apply { |
|
|
|
setCellValue(it.staffName) |
|
|
|
cellStyle =blackFontStyle |
|
|
|
} |
|
|
|
|
|
|
|
emailCell.apply { |
|
|
|
setCellValue(it.email) |
|
|
|
cellStyle =blackFontStyle |
|
|
|
} |
|
|
|
|
|
|
|
teamCell.apply { |
|
|
|
setCellValue(it.team) |
|
|
|
cellStyle =blackFontStyle |
|
|
|
} |
|
|
|
|
|
|
|
lastRecordDateCell.apply { |
|
|
|
setCellValue(it.lastRecordDate) |
|
|
|
cellStyle =blackFontStyle |
|
|
|
} |
|
|
|
|
|
|
|
startRowIndex++ |
|
|
|
} |
|
|
|
|
|
|
|
return workbook |
|
|
|
} |
|
|
|
|
|
|
|
fun genLastRecordReport( |
|
|
|
date: LocalDate, |
|
|
|
): ByteArray{ |
|
|
|
val workbook = createLastRecordReportWorkbook(date, LAST_RECORD_REPORT) |
|
|
|
|
|
|
|
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() |
|
|
|
workbook.write(outputStream) |
|
|
|
workbook.close() |
|
|
|
|
|
|
|
return outputStream.toByteArray() |
|
|
|
} |
|
|
|
} |