From 1eab253266a5d1ca519f283adbabfa903ba9cdad Mon Sep 17 00:00:00 2001 From: "MSI\\2Fi" Date: Tue, 17 Sep 2024 16:02:24 +0800 Subject: [PATCH] Cah Flow Report --- .../entity/ProjectExpenseRepository.kt | 2 + .../modules/report/service/ReportService.kt | 41 +++++++++++++----- .../modules/report/web/ReportController.kt | 2 +- .../report/EX02_Project Cash Flow Report.xlsx | Bin 13340 -> 13605 bytes 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/ffii/tsms/modules/project/entity/ProjectExpenseRepository.kt b/src/main/java/com/ffii/tsms/modules/project/entity/ProjectExpenseRepository.kt index 16829c3..0cd0987 100644 --- a/src/main/java/com/ffii/tsms/modules/project/entity/ProjectExpenseRepository.kt +++ b/src/main/java/com/ffii/tsms/modules/project/entity/ProjectExpenseRepository.kt @@ -5,4 +5,6 @@ import com.ffii.tsms.modules.project.entity.projections.ProjectExpenseSearchInfo interface ProjectExpenseRepository : AbstractRepository { fun findExpenseSearchInfoByDeletedFalse(): List + + fun findAllByProjectIdAndDeletedFalse(projectId: Long): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt b/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt index 528ddb8..377734d 100644 --- a/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt +++ b/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt @@ -822,9 +822,12 @@ open class ReportService( it.staff.staffId == timesheet.staff?.staffId && it.date.year == timesheet.recordDate?.year && it.date.month == timesheet.recordDate?.month }?.hourlyRate ?: 0.0) * ((timesheet.normalConsumed ?: 0.0) + (timesheet.otConsumed ?: 0.0)) } + + val sumProjectExpense = projectExpenses.sumOf { it.amount?: 0.0 } + sheet.getRow(rowIndex).apply { createCell(1).apply { - setCellValue(actualExpenditure) + setCellValue(actualExpenditure + sumProjectExpense) cellStyle.dataFormat = accountingStyle } @@ -899,8 +902,8 @@ open class ReportService( ) } } - println("grouped Project Expense") - println(groupedProjectExpense) +// println("grouped Project Expense") +// println(groupedProjectExpense) // groupedTimesheets.entries.forEach { (key, value) -> // logger.info("key: $key") // logger.info("value: " + value.sumOf { it }) @@ -932,18 +935,23 @@ open class ReportService( } createCell(2).apply { - setCellValue(invoice["paidAmount"] as Double? ?: 0.0) + setCellValue(0.0) cellStyle.dataFormat = accountingStyle } createCell(3).apply { + setCellValue(invoice["paidAmount"] as Double? ?: 0.0) + cellStyle.dataFormat = accountingStyle + } + + createCell(4).apply { val lastRow = rowIndex - 1 if (lastRow == 16) { cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString()) } else { cellFormula = - "IF(B{currentRow}>0,D{lastRow}-B{currentRow},D{lastRow}+C{currentRow})".replace( + "IF(B{currentRow}>0,E{lastRow}-B{currentRow}-C{currentRow},E{lastRow}+D{currentRow}-C{currentRow})".replace( "{currentRow}", rowIndex.toString() ).replace("{lastRow}", lastRow.toString()) @@ -951,7 +959,7 @@ open class ReportService( cellStyle.dataFormat = accountingStyle } - createCell(4)?.apply { + createCell(5)?.apply { setCellValue( "Invoice Receipt: " + (invoice["invoiceNo"] as String? ?: "N/A").toString() ) @@ -971,18 +979,23 @@ open class ReportService( } createCell(2).apply { - setCellValue(groupedInvoices[result]?.sumOf { it["paidAmount"] as Double } ?: 0.0) + setCellValue(0.0) cellStyle.dataFormat = accountingStyle } createCell(3).apply { + setCellValue(groupedInvoices[result]?.sumOf { it["paidAmount"] as Double } ?: 0.0) + cellStyle.dataFormat = accountingStyle + } + + createCell(4).apply { val lastRow = rowIndex - 1 if (lastRow == 16) { cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString()) } else { cellFormula = - "IF(B{currentRow}>0,D{lastRow}-B{currentRow},D{lastRow}+C{currentRow})".replace( + "IF(B{currentRow}>0,E{lastRow}-B{currentRow}-C{currentRow},E{lastRow}+D{currentRow}-C{currentRow})".replace( "{currentRow}", rowIndex.toString() ).replace("{lastRow}", lastRow.toString()) @@ -990,7 +1003,7 @@ open class ReportService( cellStyle.dataFormat = accountingStyle } - createCell(4)?.apply { + createCell(5)?.apply { // setCellValue(invoice["description"].toString()) val invoiceNos = groupedInvoices[result]?.map { it["invoiceNo"] } if (invoiceNos?.size != null && invoiceNos.size > 1) { @@ -1023,12 +1036,17 @@ open class ReportService( } createCell(3).apply { + setCellValue(0.0) + cellStyle.dataFormat = accountingStyle + } + + createCell(4).apply { val lastRow = rowIndex - 1 if (lastRow == 16) { cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString()) } else { cellFormula = - "IF(B{currentRow}>0,D{lastRow}-B{currentRow},D{lastRow}+C{currentRow})".replace( + "IF(B{currentRow}>0,E{lastRow}-B{currentRow}-C{currentRow},E{lastRow}+D{currentRow}-C{currentRow})".replace( "{currentRow}", rowIndex.toString() ).replace("{lastRow}", lastRow.toString()) @@ -1036,12 +1054,13 @@ open class ReportService( cellStyle.dataFormat = accountingStyle } - createCell(4).apply { + createCell(5).apply { setCellValue("Manpower Expenditure") } } } + } conditionalFormattingNegative(sheet) diff --git a/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt b/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt index c12c060..62d0190 100644 --- a/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt +++ b/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt @@ -89,7 +89,7 @@ class ReportController( // val invoices = invoiceService.findAllByProjectAndPaidAmountIsNotNull(project) val invoices = invoiceRepository.findAllByProjectCodeAndPaidAmountIsNotNullAndDeletedFalse(project.code!!) val timesheets = timesheetRepository.findAllByProjectTaskIn(projectTasks) - val projectExpenses = projectExpenseRepository.findAll().filter { it.project == project } + val projectExpenses = projectExpenseRepository.findAllByProjectIdAndDeletedFalse(project.id!!) val monthlyStaffSalaryEffective = salaryEffectiveService.getMonthlyStaffSalaryData(timesheets.minByOrNull { it.recordDate!! }?.recordDate ?: LocalDate.parse("2012-01-01"), timesheets.maxByOrNull { it.recordDate!! }?.recordDate ?: LocalDate.now()) val reportResult: ByteArray = excelReportService.generateProjectCashFlowReport(project, invoices, timesheets, projectExpenses, monthlyStaffSalaryEffective, request.dateType) diff --git a/src/main/resources/templates/report/EX02_Project Cash Flow Report.xlsx b/src/main/resources/templates/report/EX02_Project Cash Flow Report.xlsx index 2726f567512fa8e6bf49e0c4b39fc71a2d958645..d0e60e7ca4c12adcec6fc7016bba664b25ab4dd8 100644 GIT binary patch delta 5719 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 QK*Wu>6JWqt<@rbYe|gCzz5oCK