@@ -1,12 +1,11 @@
package com.ffii.tsms.modules.report.service
import com.ffii.tsms.modules.data.entity.Salary
import com.ffii.tsms.modules.data.entity.projections.SalarySearchInfo
import com.ffii.tsms.modules.project.entity.Invoice
import com.ffii.tsms.modules.project.entity.Project
import com.ffii.tsms.modules.timesheet.entity.Timesheet
import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.xssf.usermodel.XSSFDataFormat
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.springframework.core.io.ClassPathResource
import org.springframework.stereotype.Service
@@ -25,9 +24,9 @@ open class ReportService {
// ==============================|| GENERATE REPORT ||============================== //
@Throws(IOException::class)
fun generateProjectCashFlowReport(project: Project, invoices: List<Invoice>): ByteArray {
fun generateProjectCashFlowReport(project: Project, invoices: List<Invoice>, timesheets: List<Timesheet> ): ByteArray {
// Generate the Excel report with query results
val workbook: Workbook = createProjectCashFlowReport(project, invoices, PROJECT_CASH_FLOW_REPORT)
val workbook: Workbook = createProjectCashFlowReport(project, invoices, timesheets, PROJECT_CASH_FLOW_REPORT)
// Write the workbook to a ByteArrayOutputStream
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
@@ -55,6 +54,7 @@ open class ReportService {
private fun createProjectCashFlowReport(
project: Project,
invoices: List<Invoice>,
timesheets: List<Timesheet>,
templatePath: String,
): Workbook {
// please create a new function for each report template
@@ -108,10 +108,11 @@ open class ReportService {
rowIndex = 10
val actualIncome = invoices.sumOf { invoice -> invoice.paidAmount!! }
val actualExpenditure = timesheets.sumOf { timesheet -> timesheet.staff!!.salary.hourlyRate.toDouble() * ((timesheet.normalConsumed ?: 0.0) + (timesheet.otConsumed ?: 0.0)) }
sheet.getRow(rowIndex).apply {
getCell(1).apply {
// TODO: Replace by actual expenditure
setCellValue(actualIncome * 0.8 )
setCellValue(actualExpenditure )
cellStyle.dataFormat = accountingStyle
}
@@ -136,37 +137,77 @@ open class ReportService {
}
// TODO: Add expenditure
// formula =IF(B17>0,D16-B17,D16+C17)
rowIndex = 15
val combinedResults = (invoices.map { it.receiptDate } + timesheets.map { it.recordDate }).filterNotNull().sortedBy { it }
val dateFormatter = DateTimeFormatter.ofPattern("MMM YYYY")
invoices.forEach { invoice: Invoice ->
sheet.getRow(rowIndex++).apply {
getCell(0).apply {
setCellValue(invoice.receiptDate!!.format(dateFormatter))
}
combinedResults.forEach { result: LocalDate ->
val invoice = invoices.find { invoice: Invoice -> invoice.receiptDate == result }
val timesheet = timesheets.find { timesheet: Timesheet -> timesheet.recordDate == result}
getCell(1).apply {
setCellValue(0.0)
cellStyle.dataFormat = accountingStyle
}
if (invoice != null) {
sheet.getRow(rowIndex++).apply {
getCell(2).apply {
setCellValue(invoice.paidAmount!!)
cellStyle.dataFormat = accountingStyle
}
getCell(0).apply {
setCellValue(result.format(dateFormatter))
}
getCell(1).apply {
setCellValue(0.0)
cellStyle.dataFormat = accountingStyle
}
getCell(2).apply {
setCellValue(invoice.paidAmount!!)
cellStyle.dataFormat = accountingStyle
}
getCell(3).apply {
val lastRow = rowIndex - 1
if (lastRow == 15) {
cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString())
} else {
cellFormula = "IF(B{currentRow}>0,D{lastRow}-B{currentRow},D{lastRow}+C{currentRow})".replace("{currentRow}", rowIndex.toString()).replace("{lastRow}", lastRow.toString())
}
cellStyle.dataFormat = accountingStyle
}
getCell(3).apply {
val lastRow = rowIndex - 1
if (lastRow == 15) {
cellFormula = "C{currentRow}".replace("{currentRow}", rowIndex.toString())
} else {
cellFormula = "IF(B{currentRow}>0,D{lastRow}-B{currentRow},D{lastRow}+C{currentRow})".replace("{currentRow}", rowIndex.toString()).replace("{lastRow}", lastRow.toString())
getCell(4).apply {
setCellValue(invoice.milestonePayment!!.description!!)
}
cellStyle.dataFormat = accountingStyle
}
}
if (timesheet != null) {
sheet.getRow(rowIndex++).apply {
getCell(0).apply {
setCellValue(result.format(dateFormatter))
}
getCell(1).apply {
setCellValue(timesheet.staff!!.salary.hourlyRate.toDouble() * ((timesheet.normalConsumed ?: 0.0) + (timesheet.otConsumed ?: 0.0)))
cellStyle.dataFormat = accountingStyle
}
getCell(4).apply {
setCellValue(invoice.milestonePayment!!.description!!)
getCell(2).apply {
setCellValue(0.0)
cellStyle.dataFormat = accountingStyle
}
getCell(3).apply {
val lastRow = rowIndex - 1
if (lastRow == 15) {
cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString())
} else {
cellFormula = "IF(B{currentRow}>0,D{lastRow}-B{currentRow},D{lastRow}+C{currentRow})".replace("{currentRow}", rowIndex.toString()).replace("{lastRow}", lastRow.toString())
}
cellStyle.dataFormat = accountingStyle
}
getCell(4).apply {
setCellValue("Monthly Manpower Expenditure")
}
}
}
}