Browse Source

[Report] Add sub-teamlead column & update formula & fix bugs. (financial status report & P&L report)

master
cyril.tsui 2 weeks ago
parent
commit
b94fe4d2d4
3 changed files with 95 additions and 75 deletions
  1. +95
    -75
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  2. BIN
      src/main/resources/templates/report/AR07_Project P&L Report v02.xlsx
  3. BIN
      src/main/resources/templates/report/EX01_Financial Status Report.xlsx

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

@@ -547,13 +547,16 @@ open class ReportService(
val teamLeadCell = row.createCell(4)
teamLeadCell.setCellValue(if (item["teamLead"] != null) item.getValue("teamLead").toString() else "N/A")

val startDateCell = row.createCell(5)
val subTeamLeadCell = row.createCell(5)
subTeamLeadCell.setCellValue(if (item["subTeamLead"] != null) item.getValue("subTeamLead").toString() else "N/A")

val startDateCell = row.createCell(6)
startDateCell.setCellValue(if (item["planStart"] != null) item.getValue("planStart").toString() else "N/A")

val endDateCell = row.createCell(6)
val endDateCell = row.createCell(7)
endDateCell.setCellValue(if (item["planEnd"] != null) item.getValue("planEnd").toString() else "N/A")

val totalFeeCell = row.createCell(7)
val totalFeeCell = row.createCell(8)
val totalFee =
(item["expectedTotalFee"]?.let { it as Double } ?: 0.0)
totalFeeCell.apply {
@@ -566,19 +569,19 @@ open class ReportService(

val fee = (item["expectedTotalFee"]?.let { it as Double } ?: 0.0)

val budgetCell = row.createCell(8)
val budgetCell = row.createCell(9)
budgetCell.apply {
setCellValue(fee.times(0.8))
cellStyle.dataFormat = accountingStyle
}

val cumExpenditureCell = row.createCell(9)
val cumExpenditureCell = row.createCell(10)
cumExpenditureCell.apply {
cellFormula = "K${rowNum} + L${rowNum}"
cellFormula = "L${rowNum} + M${rowNum}"
cellStyle.dataFormat = accountingStyle
}

val cumManHourSpentCell = row.createCell(10)
val cumManHourSpentCell = row.createCell(11)
// val normalConsumed = item["normalConsumed"]?.let { it as BigDecimal } ?: BigDecimal(0)
// val otConsumed = item["otConsumed"]?.let { it as BigDecimal } ?: BigDecimal(0)
// val cumExpenditure = normalConsumed.add(otConsumed)
@@ -588,20 +591,20 @@ open class ReportService(
cellStyle.dataFormat = accountingStyle
}

val projectExpenseCell = row.createCell(11)
val projectExpenseCell = row.createCell(12)
val projectExpense = item["projectExpense"]?.let { it as BigDecimal } ?: BigDecimal(0)
projectExpenseCell.apply {
setCellValue(projectExpense.toDouble())
cellStyle.dataFormat = accountingStyle
}

val budgetVCell = row.createCell(12)
val budgetVCell = row.createCell(13)
budgetVCell.apply {
cellFormula = "I${rowNum} - J${rowNum}"
cellFormula = "J${rowNum} - K${rowNum}"
cellStyle.dataFormat = accountingStyle
}

val issuedCell = row.createCell(13)
val issuedCell = row.createCell(14)
val issuedAmount = item["sumIssuedAmount"]?.let { it as BigDecimal } ?: BigDecimal(0)
issuedCell.apply {
setCellValue(issuedAmount.toDouble())
@@ -609,37 +612,37 @@ open class ReportService(
cellStyle.dataFormat = accountingStyle
}

val uninvoiceCell = row.createCell(14)
val uninvoiceCell = row.createCell(15)
uninvoiceCell.apply {
cellFormula =
" H${rowNum}-N${rowNum} "
" I${rowNum}-O${rowNum} "
// " IF(H${rowNum}-N${rowNum}<0, 0, H${rowNum}-N${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
}

val cpiCell = row.createCell(15)
val cpiCell = row.createCell(16)
cpiCell.apply {
cellFormula = "IF(J${rowNum} = 0, 0, N${rowNum}/(J${rowNum}))"
cellFormula = "IF(K${rowNum} = 0, 0, O${rowNum}/(K${rowNum}))"
cellStyle = boldFontCellStyle
}

val projectedCpiCell = row.createCell(16)
val projectedCpiCell = row.createCell(17)
projectedCpiCell.apply {
cellFormula = "IF(J${rowNum} = 0, 0, H${rowNum}/(J${rowNum}))"
cellFormula = "IF(K${rowNum} = 0, 0, I${rowNum}/(K${rowNum}))"
cellStyle = boldFontCellStyle
}

val receivedAmountCell = row.createCell(17)
val receivedAmountCell = row.createCell(18)
val paidAmount = item["sumPaidAmount"]?.let { it as BigDecimal } ?: BigDecimal(0)
receivedAmountCell.apply {
setCellValue(paidAmount.toDouble())
cellStyle.dataFormat = accountingStyle
}

val unsettledAmountCell = row.createCell(18)
val unsettledAmountCell = row.createCell(19)
unsettledAmountCell.apply {
cellFormula = "N${rowNum}-R${rowNum}"
cellFormula = "O${rowNum}-S${rowNum}"
cellStyle = boldFontCellStyle
cellStyle.dataFormat = accountingStyle
}
@@ -648,13 +651,13 @@ open class ReportService(
val lastRowNum = rowNum + 1

val row: Row = sheet.createRow(rowNum)
for (i in 0..5) {
for (i in 0..6) {
val cell = row.createCell(i)
CellUtil.setCellStyleProperty(cell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(cell, "borderBottom", BorderStyle.DOUBLE)
}

val subTotalCell = row.createCell(6)
val subTotalCell = row.createCell(7)
subTotalCell.apply {
setCellValue("Sub-total:")
}
@@ -662,85 +665,85 @@ open class ReportService(
CellUtil.setCellStyleProperty(subTotalCell, "borderBottom", BorderStyle.DOUBLE)


val sumTotalFeeCell = row.createCell(7)
val sumTotalFeeCell = row.createCell(8)
sumTotalFeeCell.apply {
cellFormula = "SUM(H15:H${rowNum})"
cellFormula = "SUM(I15:I${rowNum})"
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumTotalFeeCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumTotalFeeCell, "borderBottom", BorderStyle.DOUBLE)

val sumBudgetCell = row.createCell(8)
val sumBudgetCell = row.createCell(9)
sumBudgetCell.apply {
cellFormula = "SUM(I15:I${rowNum})"
cellFormula = "SUM(J15:J${rowNum})"
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumBudgetCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumBudgetCell, "borderBottom", BorderStyle.DOUBLE)

val sumCumExpenditureCell = row.createCell(9)
val sumCumExpenditureCell = row.createCell(10)
sumCumExpenditureCell.apply {
cellFormula = "SUM(J15:J${rowNum})"
cellFormula = "SUM(K15:K${rowNum})"
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumCumExpenditureCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumCumExpenditureCell, "borderBottom", BorderStyle.DOUBLE)

val sumTotalManHourSpent = row.createCell(10)
val sumTotalManHourSpent = row.createCell(11)
sumTotalManHourSpent.apply {
cellFormula = "SUM(K15:K${rowNum})"
cellFormula = "SUM(L15:L${rowNum})"
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumTotalManHourSpent, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumTotalManHourSpent, "borderBottom", BorderStyle.DOUBLE)

val sumProjectExpenseCell = row.createCell(11)
val sumProjectExpenseCell = row.createCell(12)
sumProjectExpenseCell.apply {
cellFormula = "SUM(L15:L${rowNum})"
cellFormula = "SUM(M15:M${rowNum})"
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumProjectExpenseCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumProjectExpenseCell, "borderBottom", BorderStyle.DOUBLE)

val sumBudgetVCell = row.createCell(12)
val sumBudgetVCell = row.createCell(13)
sumBudgetVCell.apply {
cellFormula = "SUM(M15:M${rowNum})"
cellFormula = "SUM(N15:N${rowNum})"
cellStyle = boldFontCellStyle
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumBudgetVCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumBudgetVCell, "borderBottom", BorderStyle.DOUBLE)

val sumIInvoiceCell = row.createCell(13)
val sumIInvoiceCell = row.createCell(14)
sumIInvoiceCell.apply {
cellFormula = "SUM(N15:N${rowNum})"
cellFormula = "SUM(O15:O${rowNum})"
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumIInvoiceCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumIInvoiceCell, "borderBottom", BorderStyle.DOUBLE)

val sumUInvoiceCell = row.createCell(14)
val sumUInvoiceCell = row.createCell(15)
sumUInvoiceCell.apply {
// cellFormula = "IF(H${rowNum+1}-N${rowNum+1}<0,0,H${rowNum+1}-N${rowNum+1})"
cellFormula = " H${rowNum+1}-N${rowNum+1} "
cellFormula = " I${rowNum+1}-O${rowNum+1} "
cellStyle = boldFontCellStyle
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumUInvoiceCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumUInvoiceCell, "borderBottom", BorderStyle.DOUBLE)

val lastCpiCell = row.createCell(15)
val lastCpiCell = row.createCell(16)
lastCpiCell.apply {
cellFormula = "IF(J${rowNum+1}=0,0,N${rowNum+1}/J${rowNum+1})"
cellFormula = "IF(K${rowNum+1}=0,0,O${rowNum+1}/K${rowNum+1})"
cellStyle = boldFontCellStyle
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(lastCpiCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(lastCpiCell, "borderBottom", BorderStyle.DOUBLE)

val lastPCpiCell = row.createCell(16)
val lastPCpiCell = row.createCell(17)
lastPCpiCell.apply {
cellFormula = "IF(J${rowNum+1}=0,0,H${rowNum+1}/J${rowNum+1})"
cellFormula = "IF(K${rowNum+1}=0,0,I${rowNum+1}/K${rowNum+1})"
cellStyle = boldFontCellStyle
cellStyle.dataFormat = accountingStyle
}
@@ -748,17 +751,17 @@ open class ReportService(
CellUtil.setCellStyleProperty(lastPCpiCell, "borderBottom", BorderStyle.DOUBLE)


val sumRAmountCell = row.createCell(17)
val sumRAmountCell = row.createCell(18)
sumRAmountCell.apply {
cellFormula = "SUM(R15:R${rowNum})"
cellFormula = "SUM(S15:S${rowNum})"
cellStyle.dataFormat = accountingStyle
}
CellUtil.setCellStyleProperty(sumRAmountCell, "borderTop", BorderStyle.THIN)
CellUtil.setCellStyleProperty(sumRAmountCell, "borderBottom", BorderStyle.DOUBLE)

val sumUnSettleCell = row.createCell(18)
val sumUnSettleCell = row.createCell(19)
sumUnSettleCell.apply {
cellFormula = "SUM(S15:S${rowNum})"
cellFormula = "SUM(T15:T${rowNum})"
cellStyle = boldFontCellStyle
cellStyle.dataFormat = accountingStyle
}
@@ -778,7 +781,7 @@ open class ReportService(
row2Cell.setCellValue("All")
} else {
row2Cell.apply {
cellFormula = "E16"
cellFormula = "E17"
}
}

@@ -796,7 +799,7 @@ open class ReportService(
val row5: Row = sheet.getRow(rowNum)
val cell1 = row5.createCell(2)
cell1.apply {
cellFormula = "I${lastRowNum}"
cellFormula = "J${lastRowNum}"
cellStyle.dataFormat = accountingStyle
}

@@ -804,7 +807,7 @@ open class ReportService(
val row6: Row = sheet.getRow(rowNum)
val cell2 = row6.createCell(2)
cell2.apply {
cellFormula = "J${lastRowNum}"
cellFormula = "K${lastRowNum}"
cellStyle.dataFormat = accountingStyle
}

@@ -812,7 +815,7 @@ open class ReportService(
val row7: Row = sheet.getRow(rowNum)
val cell3 = row7.createCell(2)
cell3.apply {
cellFormula = "M${lastRowNum}"
cellFormula = "N${lastRowNum}"
cellStyle.dataFormat = accountingStyle
}

@@ -820,7 +823,7 @@ open class ReportService(
val row8: Row = sheet.getRow(rowNum)
val cell4 = row8.createCell(2)
cell4.apply {
cellFormula = "N${lastRowNum}"
cellFormula = "O${lastRowNum}"
cellStyle.dataFormat = accountingStyle
}

@@ -828,7 +831,7 @@ open class ReportService(
val row9: Row = sheet.getRow(rowNum)
val cell5 = row9.createCell(2)
cell5.apply {
cellFormula = "O${lastRowNum}"
cellFormula = "P${lastRowNum}"
cellStyle.dataFormat = accountingStyle
}

@@ -836,7 +839,7 @@ open class ReportService(
val row10: Row = sheet.getRow(rowNum)
val cell6 = row10.createCell(2)
cell6.apply {
cellFormula = "R${lastRowNum}"
cellFormula = "S${lastRowNum}"
cellStyle.dataFormat = accountingStyle
}

@@ -844,7 +847,7 @@ open class ReportService(
val row11: Row = sheet.getRow(rowNum)
val cell7 = row11.createCell(2)
cell7.apply {
cellFormula = "S${lastRowNum}"
cellFormula = "T${lastRowNum}"
cellStyle.dataFormat = accountingStyle
}

@@ -2262,6 +2265,7 @@ open class ReportService(
+ " group by p.id"
+ " ) "
+ " select p.code, p.name, p.description, c.name as client, IFNULL(s2.name, \"N/A\") as subsidiary, concat(t.code, \' - \', t.name) as teamLead, "
+ " concat(t.code, \' - \', s.staffId, \' - \', s.name) as subTeamLead,"
+ " p.planStart , p.planEnd ,"
+ " IFNULL(cte_f.expectedTotalFee, 0) as expectedTotalFee, ifnull(p.subContractFee, 0) as subContractFee, "
+ " IFNULL(cte_i.sumIssuedAmount, 0) as sumIssuedAmount, IFNULL(cte_ri.sumPaidAmount, 0) as sumPaidAmount"
@@ -2272,6 +2276,8 @@ open class ReportService(
+ " left join customer_subsidiary cs on cs.id = p.customerSubsidiaryId"
+ " left join subsidiary s2 on s2.id = cs.subsidiaryId "
+ " left join tsmsdb.team t on t.teamLead = p.teamLead"
+ " left join staff s on s.id = p.subTeamLead"
+ " left join team st on st.id = s.teamId"
+ " left join cte_invoice cte_i on cte_i.code = p.code"
+ " left join cte_rinvoice cte_ri on cte_ri.code = p.code"
+ " left join cte_expense cte_e on cte_e.projectId = p.id "
@@ -2580,7 +2586,7 @@ open class ReportService(
// }

private fun updateInfo(info: MutableMap<String, Any?>, item: Map<String, Any>) {
val simpleFields = listOf("teamLead", "client", "code", "description")
val simpleFields = listOf("teamLead", "subTeamLead", "subsidiary", "client", "code", "description")
val conditionalFields = mapOf(
"paidAmount" to "sumPaidAmount",
"subsidiary" to "subsidiary",
@@ -2655,6 +2661,7 @@ open class ReportService(
+ " and (DATE_FORMAT(pe.issueDate, '%Y-%m') >= :startMonth and DATE_FORMAT(pe.issueDate, '%Y-%m') <= :endMonth) "
+ " ) "
+ " select p.code, p.description, c.name as client, IFNULL(s2.name, \"N/A\") as subsidiary, concat(t.code, \" - \", t.name) as teamLead,"
+ " concat(stlt.code, \" - \", stl.staffId, \" - \", stl.name) as subTeamLead,"
+ " 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, "
+ " (p.expectedTotalFee - IFNULL(cte_Ii.sumIssuedAmount, 0)) as expectedTotalFee, "
@@ -2665,6 +2672,8 @@ open class ReportService(
+ " left join cte_timesheet_sum cte_tss on p.code = cte_tss.code"
+ " left join customer c on c.id = p.customerId"
+ " left join tsmsdb.team t on t.teamLead = p.teamLead"
+ " left join staff stl on stl.id = p.subTeamLead"
+ " left join team stlt on stlt.id = stl.teamId"
+ " left join cte_Iinvoice cte_Ii on cte_Ii.code = p.code"
+ " left join cte_Rinvoice cte_Ri on cte_Ri.code = p.code"
+ " left join staff s on s.id = cte_ts.staffId"
@@ -2705,7 +2714,7 @@ open class ReportService(
val manHoursSpent = jdbcDao.queryForList(sql.toString(), args)

val projectCodeSql = StringBuilder(
"select p.code, p.description from project p where p.deleted = false and p.id = :projectId"
"select p.name, p.code, p.description from project p where p.deleted = false and p.id = :projectId"
)

val projectExpenseSql = StringBuilder(
@@ -2729,6 +2738,7 @@ open class ReportService(
"startMonth" to startMonth,
"endMonth" to endMonth,
"code" to projectsCode["code"],
"name" to projectsCode["name"],
"description" to projectsCode["description"],
"projectExpense" to projectExpense["amount"]
)
@@ -3140,6 +3150,11 @@ open class ReportService(
val row6Cell = row6.getCell(1)
row6Cell.setCellValue("-")

rowNum = 7
val row7: Row = sheet.getRow(rowNum)
val row7Cell = row6.getCell(1)
row7Cell.setCellValue("-")

return workbook
}

@@ -3163,7 +3178,7 @@ open class ReportService(
rowNum = 4
val row4: Row = sheet.getRow(rowNum)
val row4Cell = row4.getCell(1)
row4Cell.setCellValue(info.getValue("description").toString())
row4Cell.setCellValue(info.getValue("name").toString())

rowNum = 5
val row5: Row = sheet.getRow(rowNum)
@@ -3173,52 +3188,57 @@ open class ReportService(
rowNum = 6
val row6: Row = sheet.getRow(rowNum)
val row6Cell = row6.getCell(1)
row6Cell.setCellValue(info.getOrDefault("subTeamLead", "N/A").toString())

rowNum = 7
val row7: Row = sheet.getRow(rowNum)
val row7Cell = row7.getCell(1)
val clientSubsidiary = if (info.getValue("subsidiary").toString() != "N/A") {
info.getValue("subsidiary").toString()
} else {
info.getValue("client").toString()
}
row6Cell.setCellValue(clientSubsidiary)
row7Cell.setCellValue(clientSubsidiary)

// Average Hourly Rate by Pay Scale Point
rowNum = 8
val row8: Row = sheet.getRow(rowNum) ?: sheet.createRow(rowNum)
rowNum = 9
val row9: Row = sheet.getRow(rowNum) ?: sheet.createRow(rowNum)
sheet.addMergedRegion(CellRangeAddress(rowNum, rowNum, 2, (financialYears.size + 1) * 2 - 1))
val row8Cell = row8.getCell(2) ?: row8.createCell(2)
row8Cell.apply {
val row9Cell = row9.getCell(2) ?: row9.createCell(2)
row9Cell.apply {
setCellValue("Average Hourly Rate by Pay Scale Point")
}
CellUtil.setAlignment(row8Cell, HorizontalAlignment.CENTER);
CellUtil.setVerticalAlignment(row8Cell, VerticalAlignment.CENTER);
CellUtil.setCellStyleProperty(row8Cell, CellUtil.WRAP_TEXT, true)
CellUtil.setAlignment(row9Cell, HorizontalAlignment.CENTER);
CellUtil.setVerticalAlignment(row9Cell, VerticalAlignment.CENTER);
CellUtil.setCellStyleProperty(row9Cell, CellUtil.WRAP_TEXT, true)


// Need to be updated to financial year
// Base on the searching criteria
rowNum = 9
val row9: Row = sheet.getRow(rowNum) ?: sheet.createRow(rowNum)
rowNum = 10
val row10: Row = sheet.getRow(rowNum) ?: sheet.createRow(rowNum)
var column = 2
financialYears.indices.forEach { i ->
val row9Cell = row9.getCell(column) ?: row9.createCell(column)
val row9Cell2 = row9.getCell(column + 1) ?: row9.createCell(column + 1)
val row10Cell = row10.getCell(column) ?: row10.createCell(column)
val row10Cell2 = row10.getCell(column + 1) ?: row10.createCell(column + 1)
sheet.addMergedRegion(CellRangeAddress(rowNum, rowNum, column, column + 1))
row9Cell.setCellValue(
row10Cell.setCellValue(
"${financialYears[i].start.format(monthFormat)} - ${
financialYears[i].end.format(
monthFormat
)
}"
)
CellUtil.setAlignment(row9Cell, HorizontalAlignment.CENTER);
CellUtil.setVerticalAlignment(row9Cell, VerticalAlignment.CENTER);
CellUtil.setCellStyleProperty(row9Cell, "borderBottom", BorderStyle.THIN)
CellUtil.setCellStyleProperty(row9Cell2, "borderBottom", BorderStyle.THIN)
CellUtil.setAlignment(row10Cell, HorizontalAlignment.CENTER);
CellUtil.setVerticalAlignment(row10Cell, VerticalAlignment.CENTER);
CellUtil.setCellStyleProperty(row10Cell, "borderBottom", BorderStyle.THIN)
CellUtil.setCellStyleProperty(row10Cell2, "borderBottom", BorderStyle.THIN)
column = column.plus(2)
}



rowNum = 10
rowNum = 11
for (staff in staffInfoList) {
// val row: Row = sheet.getRow(rowNum++) ?: sheet.createRow(rowNum++)
val row: Row = sheet.getRow(rowNum) ?: sheet.createRow(rowNum)


BIN
src/main/resources/templates/report/AR07_Project P&L Report v02.xlsx View File


BIN
src/main/resources/templates/report/EX01_Financial Status Report.xlsx View File


Loading…
Cancel
Save