@@ -1,12 +1,11 @@
package com.ffii.tsms.modules.report.service
package com.ffii.tsms.modules.report.service
import com.ffii.tsms.modules.data.entity.Salary
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.Invoice
import com.ffii.tsms.modules.project.entity.Project
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.Sheet
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.xssf.usermodel.XSSFDataFormat
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.ClassPathResource
import org.springframework.stereotype.Service
import org.springframework.stereotype.Service
@@ -25,9 +24,9 @@ open class ReportService {
// ==============================|| GENERATE REPORT ||============================== //
// ==============================|| GENERATE REPORT ||============================== //
@Throws(IOException::class)
@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
// 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
// Write the workbook to a ByteArrayOutputStream
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
@@ -55,6 +54,7 @@ open class ReportService {
private fun createProjectCashFlowReport(
private fun createProjectCashFlowReport(
project: Project,
project: Project,
invoices: List<Invoice>,
invoices: List<Invoice>,
timesheets: List<Timesheet>,
templatePath: String,
templatePath: String,
): Workbook {
): Workbook {
// please create a new function for each report template
// please create a new function for each report template
@@ -108,10 +108,11 @@ open class ReportService {
rowIndex = 10
rowIndex = 10
val actualIncome = invoices.sumOf { invoice -> invoice.paidAmount!! }
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 {
sheet.getRow(rowIndex).apply {
getCell(1).apply {
getCell(1).apply {
// TODO: Replace by actual expenditure
// TODO: Replace by actual expenditure
setCellValue(actualIncome * 0.8 )
setCellValue(actualExpenditure )
cellStyle.dataFormat = accountingStyle
cellStyle.dataFormat = accountingStyle
}
}
@@ -136,37 +137,77 @@ open class ReportService {
}
}
// TODO: Add expenditure
// TODO: Add expenditure
// formula =IF(B17>0,D16-B17,D16+C17)
rowIndex = 15
rowIndex = 15
val combinedResults = (invoices.map { it.receiptDate } + timesheets.map { it.recordDate }).filterNotNull().sortedBy { it }
val dateFormatter = DateTimeFormatter.ofPattern("MMM YYYY")
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")
}
}
}
}
}
}
}