Browse Source

update report

tags/Baseline_30082024_BACKEND_UAT
MSI\derek 1 year ago
parent
commit
fac00ee648
3 changed files with 102 additions and 29 deletions
  1. +96
    -28
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  2. +4
    -1
      src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt
  3. +2
    -0
      src/main/java/com/ffii/tsms/modules/timesheet/entity/LeaveRepository.kt

+ 96
- 28
src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt View File

@@ -4,6 +4,7 @@ import com.ffii.tsms.modules.data.entity.Salary
import com.ffii.tsms.modules.data.entity.Staff
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 org.apache.poi.ss.usermodel.*
import org.apache.poi.ss.util.CellRangeAddress
@@ -41,9 +42,9 @@ open class ReportService {
}

@Throws(IOException::class)
fun generateStaffMonthlyWorkHourAnalysisReport(month: LocalDate, staff: Staff, timesheets: List<Timesheet>, projectList: List<String>): ByteArray {
fun generateStaffMonthlyWorkHourAnalysisReport(month: LocalDate, staff: Staff, timesheets: List<Timesheet>, leaves: List<Leave>, projectList: List<String>): ByteArray {
// Generate the Excel report with query results
val workbook: Workbook = createStaffMonthlyWorkHourAnalysisReport(month, staff, timesheets, projectList, MONTHLY_WORK_HOURS_ANALYSIS_REPORT)
val workbook: Workbook = createStaffMonthlyWorkHourAnalysisReport(month, staff, timesheets, leaves, projectList, MONTHLY_WORK_HOURS_ANALYSIS_REPORT)

// Write the workbook to a ByteArrayOutputStream
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
@@ -251,6 +252,7 @@ open class ReportService {
month: LocalDate,
staff: Staff,
timesheets: List<Timesheet>,
leaves: List<Leave>,
projectList: List<String>,
templatePath: String,
): Workbook {
@@ -261,6 +263,7 @@ open class ReportService {

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

val daysOfMonth = (1..month.lengthOfMonth()).map { day ->
val date = month.withDayOfMonth(day)
@@ -281,6 +284,7 @@ open class ReportService {
var rowSize = 0
var columnSize = 0

var dayInt = 0
// tempCell = tempRow.createCell(columnIndex)
sheet.getRow(rowIndex).getCell(columnIndex).apply {
setCellValue(FORMATTED_TODAY)
@@ -310,13 +314,12 @@ open class ReportService {

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
rowIndex = 7
println(daysOfMonth)
daysOfMonth.forEach { dayInfo ->
rowIndex++
rowSize++
println(dayInfo)
sheet.getRow(rowIndex).getCell(0).apply {
setCellValue(dayInfo.date)
cellStyle.dataFormat = dateStyle
cellStyle.setFont(boldFont)
}
sheet.getRow(rowIndex).getCell(1).apply {
@@ -329,6 +332,8 @@ open class ReportService {
sheet.getRow(rowIndex).getCell(0).apply {
setCellValue("Sub-total")
cellStyle.setFont(boldFont)
// cellStyle.borderTop = BorderStyle.THIN
// cellStyle.borderBottom = BorderStyle.DOUBLE
cellStyle.alignment = HorizontalAlignment.CENTER
}
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1))
@@ -339,22 +344,63 @@ open class ReportService {
// cellStyle.setFont(boldFont)
cellStyle.alignment = HorizontalAlignment.CENTER
}
var normalConsumed = 0.0
var otConsumed = 0.0
var leaveHours = 0.0
if (timesheets.isNotEmpty()) {
timesheets.forEach { t ->
normalConsumed += t.normalConsumed!!
otConsumed += t.otConsumed!!
}
}
sheet.getRow(rowIndex).getCell(2).apply {
setCellValue(normalConsumed)
cellStyle.alignment = HorizontalAlignment.CENTER
cellStyle.dataFormat = accountingStyle
}
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1))
//
rowIndex += 1
sheet.getRow(rowIndex).getCell(0).apply {
setCellValue("Total Other Hours [B]")
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1))
cellStyle.setFont(boldFont)
cellStyle.alignment = HorizontalAlignment.CENTER
}
sheet.getRow(rowIndex).getCell(2).apply {
setCellValue(otConsumed)
cellStyle.alignment = HorizontalAlignment.CENTER
cellStyle.dataFormat = accountingStyle
}

sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1))

rowIndex += 1
sheet.getRow(rowIndex).getCell(0).apply {
setCellValue("Total Leave Hours")
cellStyle.alignment = HorizontalAlignment.CENTER
}
if (leaves.isNotEmpty()) {
leaves.forEach { l ->
leaveHours += l.leaveHours!!
}
}
sheet.getRow(rowIndex).getCell(2).apply {
setCellValue(leaveHours)
cellStyle.dataFormat = accountingStyle
}
rowIndex += 1
sheet.getRow(rowIndex).getCell(0).apply {
setCellValue("Total Spent Manhours [A+B]")
// cellStyle.setFont(boldFont)
cellStyle.setFont(boldFont)
cellStyle.alignment = HorizontalAlignment.CENTER
cellStyle.borderBottom = BorderStyle.DOUBLE
// cellStyle.borderTop = BorderStyle.THIN
// cellStyle.borderBottom = BorderStyle.DOUBLE
}
sheet.getRow(rowIndex).getCell(2).apply {
cellFormula = "C${rowIndex-2}+C${rowIndex-1}"
cellStyle.dataFormat = accountingStyle
// cellStyle.borderTop = BorderStyle.THIN
// cellStyle.borderBottom = BorderStyle.DOUBLE
}
sheet.addMergedRegion(CellRangeAddress(rowIndex,rowIndex , 0, 1))
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -364,6 +410,26 @@ open class ReportService {
sheet.getRow(7).getCell(columnIndex + index).apply {
setCellValue(title)
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (timesheets.isNotEmpty()) {
projectList.forEach { _ ->
timesheets.forEach { timesheet ->
dayInt = timesheet.recordDate!!.dayOfMonth
sheet.getRow(dayInt.plus(7)).getCell(columnIndex).apply {
setCellValue(timesheet.normalConsumed!!)
}
}
columnIndex++
}
}
if (leaves.isNotEmpty()) {
leaves.forEach { leave ->
dayInt = leave.recordDate!!.dayOfMonth
sheet.getRow(dayInt.plus(7)).getCell(columnIndex).apply {
setCellValue(leave.leaveHours!!)
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sheet.getRow(rowIndex).apply {
@@ -377,47 +443,49 @@ open class ReportService {
}
sheet.addMergedRegion(CellRangeAddress(6,6 , 2, columnIndex))
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
for (i in 2 ..columnIndex) {
for (i in 2 until columnIndex) {
for (k in 0 until rowSize) {
sheet.getRow(8+k).getCell(i).apply {
setCellValue(" - ")
setCellValue(0.0)
cellStyle.dataFormat = accountingStyle
}
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (timesheets.isNotEmpty()) {
projectList.forEachIndexed { i, _ ->
timesheets.forEach { timesheet ->
val dayInt = timesheet.recordDate!!.dayOfMonth
sheet.getRow(dayInt.plus(7)).getCell(columnIndex + i).apply {
setCellValue(timesheet.normalConsumed!!)
}
}
}
}

rowIndex = 8
// println("rowSize is: $rowSize")
if (sheet.getRow(rowIndex - 1).getCell(2).stringCellValue == "Leave Hours") {
if (sheet.getRow(rowIndex - 1).getCell(2).stringCellValue != "Leave Hours") {
// cal daily spent manhour
for (i in 0 until rowSize) {
val cell = sheet.getRow(rowIndex)?.getCell(columnIndex) ?: sheet.getRow(rowIndex + i)?.createCell(columnIndex)
cell?.cellFormula = "SUM(${getColumnAlphabet(2)}${rowIndex+1}:${getColumnAlphabet(columnIndex)}${rowIndex+1})" // should columnIndex - 2
rowIndex++
// cell?.setCellValue("testing")
// rowIndex++
}
// println(columnSize)
// cal subtotal
for (i in 0 until columnSize) { // minus last col
val cell = sheet.getRow(rowIndex)?.getCell(2) ?: sheet.getRow(rowIndex)?.createCell(2)
cell?.cellFormula = "SUM(${getColumnAlphabet(2)}${rowIndex}:${getColumnAlphabet(columnIndex + i)}${rowIndex})"
cell?.cellStyle?.dataFormat = accountingStyle
cell?.cellStyle?.setFont(boldFont)
// cell?.cellStyle.borderBottom = border
// cell?.cellStyle?.borderTop = BorderStyle.THIN
// cell?.cellStyle?.borderBottom = BorderStyle.DOUBLE
}
} else { // just for preview when no data
// cal daily spent manhour
for (i in 0 until rowSize) {
val cell = sheet.getRow(rowIndex)?.getCell(columnIndex) ?: sheet.getRow(rowIndex + i)?.createCell(columnIndex)
cell?.setCellValue("daily spent manhour")
rowIndex++
}
// cal subtotal
for (i in 0 until columnSize) { // minus last col
val cell = sheet.getRow(rowIndex)?.getCell(2) ?: sheet.getRow(rowIndex)?.createCell(2)
cell?.setCellValue("testing subtotal")
cell?.cellStyle?.dataFormat = accountingStyle
cell?.cellStyle?.setFont(boldFont)
// cell?.cellStyle?.borderTop = BorderStyle.THIN
// cell?.cellStyle?.borderBottom = BorderStyle.DOUBLE
}
}

return workbook
}



+ 4
- 1
src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt View File

@@ -7,6 +7,7 @@ import com.ffii.tsms.modules.report.service.ReportService
import com.ffii.tsms.modules.project.service.InvoiceService
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 jakarta.validation.Valid
import org.springframework.core.io.ByteArrayResource
@@ -33,6 +34,7 @@ class ReportController(
private val timesheetRepository: TimesheetRepository,
private val projectTaskRepository: ProjectTaskRepository,
private val staffRepository: StaffRepository,
private val leaveRepository: LeaveRepository,
private val invoiceService: InvoiceService) {

@PostMapping("/ProjectCashFlowReport")
@@ -60,11 +62,12 @@ class ReportController(

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, projectList)
val reportResult: ByteArray = excelReportService.generateStaffMonthlyWorkHourAnalysisReport(thisMonth, staff, timesheets, leaves, projectList)
// val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
return ResponseEntity.ok()
// .contentType(mediaType)


+ 2
- 0
src/main/java/com/ffii/tsms/modules/timesheet/entity/LeaveRepository.kt View File

@@ -8,4 +8,6 @@ interface LeaveRepository : AbstractRepository<Leave, Long> {
fun findAllByStaff(staff: Staff): List<Leave>

fun deleteAllByStaffAndRecordDate(staff: Staff, recordDate: LocalDate)

fun findByStaffAndRecordDateBetweenOrderByRecordDate(staff: Staff, start: LocalDate, end: LocalDate): List<Leave>
}

Loading…
Cancel
Save