Browse Source

Debug Cash flow report

tags/Baseline_30082024_BACKEND_UAT
MSI\2Fi 1 year ago
parent
commit
0192b0a30d
3 changed files with 92 additions and 20 deletions
  1. +20
    -0
      src/main/java/com/ffii/tsms/modules/data/entity/projections/FinancialStatusReportInfo.kt
  2. +70
    -19
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  3. +2
    -1
      src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt

+ 20
- 0
src/main/java/com/ffii/tsms/modules/data/entity/projections/FinancialStatusReportInfo.kt View File

@@ -0,0 +1,20 @@
package com.ffii.tsms.modules.data.entity.projections

import java.math.BigDecimal
import java.time.LocalDate

interface FinancialStatusReportInfo {
val code: String
val description: String
val client: String
val teamLead: String
val planStart: LocalDate
val planEnd: LocalDate
val expectedTotalFee: BigDecimal
val staff: String
val normalConsumed: BigDecimal
val otConsumed: BigDecimal
val hourlyRate: BigDecimal
val sumIssuedAmount: BigDecimal
val sumPaidAmount: BigDecimal
}

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

@@ -1,12 +1,16 @@
package com.ffii.tsms.modules.report.service package com.ffii.tsms.modules.report.service


import com.ffii.core.support.JdbcDao
import com.ffii.tsms.modules.data.entity.Salary import com.ffii.tsms.modules.data.entity.Salary
import com.ffii.tsms.modules.data.entity.Staff import com.ffii.tsms.modules.data.entity.Staff
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.Leave import com.ffii.tsms.modules.timesheet.entity.Leave
import com.ffii.tsms.modules.timesheet.entity.Timesheet import com.ffii.tsms.modules.timesheet.entity.Timesheet
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.apache.poi.ss.usermodel.* import org.apache.poi.ss.usermodel.*
import org.apache.poi.ss.util.CellAddress
import org.apache.poi.ss.util.CellRangeAddress import org.apache.poi.ss.util.CellRangeAddress
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
@@ -16,11 +20,14 @@ import java.io.IOException
import java.time.LocalDate import java.time.LocalDate
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.* import java.util.*
import org.apache.poi.ss.util.CellAddress


data class DayInfo(val date: String?, val weekday: String?) data class DayInfo(val date: String?, val weekday: String?)
@Service @Service
open class ReportService {
open class ReportService (
private val jdbcDao: JdbcDao,
)
{
private val logger: Log = LogFactory.getLog(javaClass)
private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd") private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd")
private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER) private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER)


@@ -32,8 +39,8 @@ open class ReportService {


// ==============================|| GENERATE REPORT ||============================== // // ==============================|| GENERATE REPORT ||============================== //


fun genFinancialStatusReport(): ByteArray {
val workbook: Workbook = createFinancialStatusReport(FINANCIAL_STATUS_REPORT)
fun genFinancialStatusReport(projectId: Long): ByteArray {
val workbook: Workbook = createFinancialStatusReport(FINANCIAL_STATUS_REPORT, projectId)


val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
workbook.write(outputStream) workbook.write(outputStream)
@@ -94,6 +101,7 @@ open class ReportService {
// EX01 Financial Report // EX01 Financial Report
private fun createFinancialStatusReport( private fun createFinancialStatusReport(
templatePath: String, templatePath: String,
projectId: Long,
) : Workbook { ) : Workbook {
val resource = ClassPathResource(templatePath) val resource = ClassPathResource(templatePath)
val templateInputStream = resource.inputStream val templateInputStream = resource.inputStream
@@ -191,30 +199,40 @@ open class ReportService {
// TODO: Add expenditure // TODO: Add expenditure
rowIndex = 15 rowIndex = 15
val combinedResults = (invoices.map { it.receiptDate } + timesheets.map { it.recordDate }).filterNotNull().sortedBy { it } val combinedResults = (invoices.map { it.receiptDate } + timesheets.map { it.recordDate }).filterNotNull().sortedBy { it }

logger.info("combinedResults-------------- $combinedResults")
invoices.forEach{
logger.info("Invoice--------- $it. \n")
}
val dateFormatter = DateTimeFormatter.ofPattern("MMM YYYY") val dateFormatter = DateTimeFormatter.ofPattern("MMM YYYY")
combinedResults.forEach { result: LocalDate -> combinedResults.forEach { result: LocalDate ->
val invoice = invoices.find { invoice: Invoice -> invoice.receiptDate == result } val invoice = invoices.find { invoice: Invoice -> invoice.receiptDate == result }
val timesheet = timesheets.find { timesheet: Timesheet -> timesheet.recordDate == result} val timesheet = timesheets.find { timesheet: Timesheet -> timesheet.recordDate == result}


logger.info("result--------------: $result")
if (invoice != null) { if (invoice != null) {
sheet.getRow(rowIndex++).apply {

getCell(0).apply {
setCellValue(result.format(dateFormatter))
sheet.getRow(rowIndex++)?.apply {

logger.info("INVOICE NOT NULL--------------:")
logger.info("getCell(0)--------------: ${getCell(0)}")
logger.info("dateFormatter--------------: $dateFormatter")
logger.info("result.format--------------: ${result.format(dateFormatter)}")
getCell(0)?.apply {
setCellValue(result.format(dateFormatter).toString())
} }


getCell(1).apply {
getCell(1)?.apply {
setCellValue(0.0) setCellValue(0.0)
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }


getCell(2).apply {
logger.info("invoice.paidAmount------------: ${invoice.paidAmount}")
logger.info("invoice.paidAmount------------: ${invoice.paidAmount!!.toDouble()}")
getCell(2)?.apply {
setCellValue(invoice.paidAmount!!.toDouble()) setCellValue(invoice.paidAmount!!.toDouble())
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }


getCell(3).apply {
getCell(3)?.apply {
val lastRow = rowIndex - 1 val lastRow = rowIndex - 1
if (lastRow == 15) { if (lastRow == 15) {
cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString()) cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString())
@@ -224,30 +242,34 @@ open class ReportService {
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }


getCell(4).apply {
getCell(4)?.apply {
setCellValue(invoice.milestonePayment!!.description!!) setCellValue(invoice.milestonePayment!!.description!!)
} }
} }
} }


if (timesheet != null) { if (timesheet != null) {
sheet.getRow(rowIndex++).apply {
sheet.getRow(rowIndex++)?.apply {


getCell(0).apply {
logger.info("TIMESHEET NOT NULL--------------:")
logger.info("getCell(0)--------------: ${getCell(0)}")
logger.info("dateFormatter--------------: $dateFormatter")
logger.info("result.format--------------: ${result.format(dateFormatter)}")
getCell(0)?.apply {
setCellValue(result.format(dateFormatter)) setCellValue(result.format(dateFormatter))
} }


getCell(1).apply {
getCell(1)?.apply {
setCellValue(timesheet.staff!!.salary.hourlyRate.toDouble() * ((timesheet.normalConsumed ?: 0.0) + (timesheet.otConsumed ?: 0.0))) setCellValue(timesheet.staff!!.salary.hourlyRate.toDouble() * ((timesheet.normalConsumed ?: 0.0) + (timesheet.otConsumed ?: 0.0)))
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }


getCell(2).apply {
getCell(2)?.apply {
setCellValue(0.0) setCellValue(0.0)
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }


getCell(3).apply {
getCell(3)?.apply {
val lastRow = rowIndex - 1 val lastRow = rowIndex - 1
if (lastRow == 15) { if (lastRow == 15) {
cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString()) cellFormula = "C{currentRow}-B{currentRow}".replace("{currentRow}", rowIndex.toString())
@@ -257,7 +279,7 @@ open class ReportService {
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }


getCell(4).apply {
getCell(4)?.apply {
setCellValue("Monthly Manpower Expenditure") setCellValue("Monthly Manpower Expenditure")
} }
} }
@@ -634,4 +656,33 @@ open class ReportService {
return workbook return workbook
} }


open fun getFinancialStatus(projectId: Long?): List<Map<String, Any>> {
val sql = StringBuilder(
"with cte_invoice as (select p.code, sum(i.issueAmount) as sumIssuedAmount , sum(i.paidAmount) as sumPaidAmount"
+ "from invoice i"
+ "left join project p on p.code = i.projectCode"
+ "group by p.code"
+ ")"
+ " Select p.code, p.description, c.name, t2.name, p.planStart , p.planEnd , p.expectedTotalFee ,"
+ " s.name , IFNULL(t.normalConsumed, 0) as normalConsumed, IFNULL(t.otConsumed , 0) as otConsumed, s2.hourlyRate,"
+ " cte_i.sumIssuedAmount, cte_i.sumPaidAmount"
+ " from timesheet t"
+ " left join project_task pt on pt.id = t.projectTaskId"
+ " left join project p ON p.id = pt.project_id"
+ " left join staff s on s.id = t.staffId"
+ " left join salary s2 on s.salaryId = s2.salaryPoint"
+ " left join customer c on c.id = p.customerId"
+ " left join team t2 on t2.id = s.teamId"
+ " left join cte_invoice cte_i on cte_i.code = p.code"
)

if (projectId!! > 0){
sql.append(" where p.id = :projectId ")
}
sql.append(" order by p.code")
val args = mapOf("projectId" to projectId)

return jdbcDao.queryForList(sql.toString(), args)
}

} }

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

@@ -44,7 +44,8 @@ class ReportController(
@Throws(ServletRequestBindingException::class, IOException::class) @Throws(ServletRequestBindingException::class, IOException::class)
fun getFinancialStatusReport(@RequestBody @Valid request: FinancialStatusReportRequest): ResponseEntity<Resource> { fun getFinancialStatusReport(@RequestBody @Valid request: FinancialStatusReportRequest): ResponseEntity<Resource> {


val reportResult: ByteArray = excelReportService.genFinancialStatusReport()

val reportResult: ByteArray = excelReportService.genFinancialStatusReport(request.projectId)


return ResponseEntity.ok() return ResponseEntity.ok()
.header("filename", "Financial Status Report - " + LocalDate.now() + ".xlsx") .header("filename", "Financial Status Report - " + LocalDate.now() + ".xlsx")


Loading…
Cancel
Save