Browse Source

update report

tags/Baseline_30082024_BACKEND_UAT
cyril.tsui 1 year ago
parent
commit
9fb55c3f5a
5 changed files with 42 additions and 12 deletions
  1. +2
    -0
      src/main/java/com/ffii/tsms/modules/project/entity/InvoiceRepository.kt
  2. +35
    -11
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  3. +5
    -1
      src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt
  4. BIN
      src/main/resources/templates/report/AR04_Cost and Expense Report v02.xlsx
  5. BIN
      src/main/resources/templates/report/AR08_Monthly Work Hours Analysis Report.xlsx

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

@@ -12,4 +12,6 @@ interface InvoiceRepository : AbstractRepository<Invoice, Long> {
fun findInvoiceInfoByPaidAmountIsNotNull(): List<InvoiceInfo> fun findInvoiceInfoByPaidAmountIsNotNull(): List<InvoiceInfo>


fun findByInvoiceNo(invoiceNo: String): Invoice fun findByInvoiceNo(invoiceNo: String): Invoice

fun findAllByProjectCodeAndPaidAmountIsNotNull(projectCode: String): List<Invoice>
} }

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

@@ -435,7 +435,8 @@ open class ReportService(
val uninvoiceCell = row.createCell(12) val uninvoiceCell = row.createCell(12)
uninvoiceCell.apply { uninvoiceCell.apply {
cellFormula = cellFormula =
" IF(I${rowNum}<=J${rowNum}, I${rowNum}-L${rowNum}, IF(AND(I${rowNum}>J${rowNum}, J${rowNum}<L${rowNum}), 0, IF(AND(I${rowNum}>J${rowNum}, J${rowNum}>=L${rowNum}), J${rowNum}-L${rowNum}, 0))) "
" IF(I${rowNum}-L${rowNum}<0, 0, I${rowNum}-L${rowNum})"
// " IF(I${rowNum}<=J${rowNum}, I${rowNum}-L${rowNum}, IF(AND(I${rowNum}>J${rowNum}, J${rowNum}<L${rowNum}), 0, IF(AND(I${rowNum}>J${rowNum}, J${rowNum}>=L${rowNum}), J${rowNum}-L${rowNum}, 0))) "
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }


@@ -1080,6 +1081,13 @@ open class ReportService(
val boldFont = workbook.createFont() val boldFont = workbook.createFont()
boldFont.bold = true boldFont.bold = true
boldStyle.setFont(boldFont) boldStyle.setFont(boldFont)

val projectsStyle = workbook.createCellStyle()
val projectsFont = workbook.createFont()
projectsFont.bold = true
projectsFont.fontName = "Times New Roman"
projectsStyle.setFont(projectsFont)

val daysOfMonth = (1..month.lengthOfMonth()).map { day -> val daysOfMonth = (1..month.lengthOfMonth()).map { day ->
val date = month.withDayOfMonth(day) val date = month.withDayOfMonth(day)
val formattedDate = date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) val formattedDate = date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))
@@ -1228,7 +1236,7 @@ open class ReportService(
projectList.forEachIndexed { index, title -> projectList.forEachIndexed { index, title ->
tempCell = sheet.getRow(7).createCell(columnIndex + index) tempCell = sheet.getRow(7).createCell(columnIndex + index)
tempCell.setCellValue(title) tempCell.setCellValue(title)
tempCell.cellStyle = boldStyle
tempCell.cellStyle = projectsStyle
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER)
CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.CENTER) CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.CENTER)
CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom)
@@ -1271,7 +1279,7 @@ open class ReportService(
///////////////////////////////////////////////////////// Leave Hours title //////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////// Leave Hours title ////////////////////////////////////////////////////////////////////
tempCell = sheet.getRow(rowIndex).createCell(columnIndex) tempCell = sheet.getRow(rowIndex).createCell(columnIndex)
tempCell.setCellValue("Leave Hours") tempCell.setCellValue("Leave Hours")
tempCell.cellStyle = boldStyle
tempCell.cellStyle = projectsStyle
CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.CENTER) CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.CENTER)
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER) CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER)
CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom)
@@ -1279,8 +1287,10 @@ open class ReportService(
columnIndex += 1 columnIndex += 1
tempCell = sheet.getRow(rowIndex).createCell(columnIndex) tempCell = sheet.getRow(rowIndex).createCell(columnIndex)
tempCell.setCellValue("Daily Manhour Spent\n(Excluding Leave Hours)") tempCell.setCellValue("Daily Manhour Spent\n(Excluding Leave Hours)")
tempCell.cellStyle = boldStyle
CellUtil.setAlignment(tempCell, HorizontalAlignment.LEFT)
tempCell.cellStyle = projectsStyle
// CellUtil.setAlignment(tempCell, HorizontalAlignment.LEFT)
CellUtil.setVerticalAlignment(tempCell, VerticalAlignment.CENTER)
CellUtil.setAlignment(tempCell, HorizontalAlignment.CENTER)
CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom) CellUtil.setCellStyleProperties(tempCell, ThinBorderBottom)


sheet.addMergedRegion(CellRangeAddress(6, 6, 2, columnIndex)) sheet.addMergedRegion(CellRangeAddress(6, 6, 2, columnIndex))
@@ -1375,7 +1385,7 @@ open class ReportService(
rowIndex = 5 rowIndex = 5
columnIndex = 0 columnIndex = 0


generalCreateReportIndexed(sheet, result, rowIndex, columnIndex)
generalCreateReportIndexed(sheet, result.distinct(), rowIndex, columnIndex)
return workbook return workbook
} }


@@ -1825,12 +1835,12 @@ open class ReportService(
+ " (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) as budgetConsumptionRate, " + " (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) as budgetConsumptionRate, "
+ " (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) as manhourConsumptionRate, " + " (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) as manhourConsumptionRate, "
+ " CASE " + " CASE "
+ " when (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= :lowerLimit and (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) <= 1 "
+ " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= :lowerLimit and (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) <= 1 "
+ " then 'Potential Overconsumption' "
+ " when (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= 1 " + " when (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= 1 "
+ " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 1 " + " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 1 "
+ " then 'Overconsumption' " + " then 'Overconsumption' "
+ " when (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= :lowerLimit and (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) <= 1 "
+ " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= :lowerLimit and (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) <= 1 "
+ " then 'Potential Overconsumption' "
+ " else 'Within Budget' " + " else 'Within Budget' "
+ " END as status " + " END as status "
+ " FROM project p " + " FROM project p "
@@ -1884,6 +1894,15 @@ open class ReportService(
+ " left join salary s2 on s.salaryId = s2.salaryPoint" + " left join salary s2 on s.salaryId = s2.salaryPoint"
+ " left join team t2 on t2.id = s.teamId" + " left join team t2 on t2.id = s.teamId"
+ " )," + " ),"
+ " cte_timesheet_sum as ("
+ " Select p.code, sum((IFNULL(t.normalConsumed, 0) + IFNULL(t.otConsumed , 0)) * s2.hourlyRate) as sumManhourExpenditure"
+ " 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"
+ " group by p.code"
+ " ),"
+ " cte_invoice as (" + " cte_invoice as ("
+ " select p.code, sum(i.issueAmount) as sumIssuedAmount , sum(i.paidAmount) as sumPaidAmount" + " select p.code, sum(i.issueAmount) as sumIssuedAmount , sum(i.paidAmount) as sumPaidAmount"
+ " from invoice i" + " from invoice i"
@@ -1893,10 +1912,11 @@ open class ReportService(
+ " select p.code, p.description, c.name as client, IFNULL(s2.name, \"N/A\") as subsidiary, concat(t.code, \" - \", t.name) as teamLead," + " select p.code, p.description, c.name as client, IFNULL(s2.name, \"N/A\") as subsidiary, concat(t.code, \" - \", t.name) as teamLead,"
+ " IFNULL(cte_ts.normalConsumed, 0) as normalConsumed, IFNULL(cte_ts.otConsumed, 0) as otConsumed, DATE_FORMAT(cte_ts.recordDate, '%Y-%m') as recordDate, " + " IFNULL(cte_ts.normalConsumed, 0) as normalConsumed, IFNULL(cte_ts.otConsumed, 0) as otConsumed, DATE_FORMAT(cte_ts.recordDate, '%Y-%m') as recordDate, "
+ " IFNULL(cte_ts.salaryPoint, 0) as salaryPoint, " + " IFNULL(cte_ts.salaryPoint, 0) as salaryPoint, "
+ " IFNULL(cte_ts.hourlyRate, 0) as hourlyRate, IFNULL(cte_i.sumIssuedAmount, 0) as sumIssuedAmount, IFNULL(cte_i.sumPaidAmount, 0) as sumPaidAmount,"
+ " IFNULL(cte_ts.hourlyRate, 0) as hourlyRate, IFNULL(cte_i.sumIssuedAmount, 0) as sumIssuedAmount, IFNULL(cte_i.sumPaidAmount, 0) as sumPaidAmount, IFNULL(cte_tss.sumManhourExpenditure, 0) as sumManhourExpenditure,"
+ " s.name, s.staffId, g.code as gradeCode, g.name as gradeName, t2.code as teamCode, t2.name as teamName" + " s.name, s.staffId, g.code as gradeCode, g.name as gradeName, t2.code as teamCode, t2.name as teamName"
+ " from project p" + " from project p"
+ " left join cte_timesheet cte_ts on p.code = cte_ts.code" + " left join cte_timesheet cte_ts on p.code = cte_ts.code"
+ " left join cte_timesheet_sum cte_tss on p.code = cte_tss.code"
+ " left join customer c on c.id = p.customerId" + " left join customer c on c.id = p.customerId"
+ " left join tsmsdb.team t on t.teamLead = p.teamLead" + " left join tsmsdb.team t on t.teamLead = p.teamLead"
+ " left join cte_invoice cte_i on cte_i.code = p.code" + " left join cte_invoice cte_i on cte_i.code = p.code"
@@ -1959,6 +1979,9 @@ open class ReportService(
if (info["code"] == item["code"] && "subsidiary" !in info) { if (info["code"] == item["code"] && "subsidiary" !in info) {
info["subsidiary"] = item.getValue("subsidiary") info["subsidiary"] = item.getValue("subsidiary")
} }
if (info["manhourExpenditure"] != item.getValue("sumManhourExpenditure")) {
info["manhourExpenditure"] = item.getValue("sumManhourExpenditure")
}
if (info["description"] != item.getValue("description")) { if (info["description"] != item.getValue("description")) {
info["description"] = item.getValue("description") info["description"] = item.getValue("description")
} }
@@ -2319,7 +2342,8 @@ open class ReportService(
} }
val totalManhourECell = totalManhourERow.getCell(1) ?: totalManhourERow.createCell(1) val totalManhourECell = totalManhourERow.getCell(1) ?: totalManhourERow.createCell(1)
totalManhourECell.apply { totalManhourECell.apply {
cellFormula = "SUM(${lastColumnIndex}${startRow}:${lastColumnIndex}${startRow + staffInfoList.size})"
// cellFormula = "SUM(${lastColumnIndex}${startRow}:${lastColumnIndex}${startRow + staffInfoList.size})"
setCellValue(info.getValue("manhourExpenditure") as Double)
cellStyle.dataFormat = accountingStyle cellStyle.dataFormat = accountingStyle
} }
CellUtil.setCellStyleProperty(totalManhourETitleCell, "borderBottom", BorderStyle.THIN) CellUtil.setCellStyleProperty(totalManhourETitleCell, "borderBottom", BorderStyle.THIN)


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

@@ -34,6 +34,8 @@ import java.time.format.DateTimeFormatter
import com.ffii.tsms.modules.project.entity.Project import com.ffii.tsms.modules.project.entity.Project
import com.ffii.tsms.modules.project.service.SubsidiaryService import com.ffii.tsms.modules.project.service.SubsidiaryService
import com.ffii.tsms.modules.report.web.model.* import com.ffii.tsms.modules.report.web.model.*
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.data.domain.Example import org.springframework.data.domain.Example
import org.springframework.data.domain.ExampleMatcher import org.springframework.data.domain.ExampleMatcher


@@ -58,6 +60,7 @@ class ReportController(
private val subsidiaryRepository: SubsidiaryRepository private val subsidiaryRepository: SubsidiaryRepository
) { ) {


private val logger: Log = LogFactory.getLog(javaClass)
@PostMapping("/fetchProjectsFinancialStatusReport") @PostMapping("/fetchProjectsFinancialStatusReport")
@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> {
@@ -76,7 +79,8 @@ class ReportController(


val project = projectRepository.findById(request.projectId).orElseThrow() val project = projectRepository.findById(request.projectId).orElseThrow()
val projectTasks = projectTaskRepository.findAllByProject(project) val projectTasks = projectTaskRepository.findAllByProject(project)
val invoices = invoiceService.findAllByProjectAndPaidAmountIsNotNull(project)
// val invoices = invoiceService.findAllByProjectAndPaidAmountIsNotNull(project)
val invoices = invoiceRepository.findAllByProjectCodeAndPaidAmountIsNotNull(project.code!!)
val timesheets = timesheetRepository.findAllByProjectTaskIn(projectTasks) val timesheets = timesheetRepository.findAllByProjectTaskIn(projectTasks)


val reportResult: ByteArray = excelReportService.generateProjectCashFlowReport(project, invoices, timesheets, request.dateType) val reportResult: ByteArray = excelReportService.generateProjectCashFlowReport(project, invoices, timesheets, request.dateType)


BIN
src/main/resources/templates/report/AR04_Cost and Expense Report v02.xlsx View File


BIN
src/main/resources/templates/report/AR08_Monthly Work Hours Analysis Report.xlsx View File


Loading…
Cancel
Save