Преглед изворни кода

update Overconsumption report

tags/Baseline_30082024_BACKEND_UAT
MSI\derek пре 1 година
родитељ
комит
4e2a6df392
4 измењених фајлова са 65 додато и 44 уклоњено
  1. +47
    -30
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  2. +15
    -12
      src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt
  3. +3
    -2
      src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt
  4. BIN
      src/main/resources/templates/report/AR03_Resource Overconsumption.xlsx

+ 47
- 30
src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt Прегледај датотеку

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

import com.ffii.core.support.JdbcDao
import com.ffii.tsms.modules.data.entity.Customer
import com.ffii.tsms.modules.data.entity.Salary
import com.ffii.tsms.modules.data.entity.Staff
import com.ffii.tsms.modules.data.entity.Team
import com.ffii.tsms.modules.data.entity.Customer
import com.ffii.tsms.modules.project.entity.Invoice
import com.ffii.tsms.modules.project.entity.Project
import com.ffii.tsms.modules.timesheet.entity.Timesheet
@@ -151,13 +151,15 @@ open class ReportService(
fun generateProjectResourceOverconsumptionReport(
team: String,
customer: String,
result: List<Map<String, Any>>
result: List<Map<String, Any>>,
lowerLimit: Double
): ByteArray {
// Generate the Excel report with query results
val workbook: Workbook = createProjectResourceOverconsumptionReport(
team,
customer,
result,
lowerLimit,
RESOURCE_OVERCONSUMPTION_REPORT
)
// Write the workbook to a ByteArrayOutputStream
@@ -1059,6 +1061,7 @@ open class ReportService(
team: String,
customer: String,
result: List<Map<String, Any>>,
lowerLimit: Double,
templatePath: String
):Workbook {
val resource = ClassPathResource(templatePath)
@@ -1089,11 +1092,11 @@ open class ReportService(
rowIndex = 6
columnIndex = 0
result.forEachIndexed { index, obj ->
tempCell = sheet.getRow(rowIndex).getCell(columnIndex)
tempCell = sheet.getRow(rowIndex).createCell(columnIndex)
tempCell.setCellValue((index + 1).toDouble())
val keys = obj.keys.toList()
keys.forEachIndexed { keyIndex, key ->
tempCell = sheet.getRow(rowIndex).getCell(columnIndex + keyIndex + 1)
tempCell = sheet.getRow(rowIndex).getCell(columnIndex + keyIndex + 1) ?: sheet.getRow(rowIndex).createCell(columnIndex + keyIndex + 1)
when (obj[key]) {
is Double -> tempCell.setCellValue(obj[key] as Double)
else -> tempCell.setCellValue(obj[key] as String )
@@ -1101,8 +1104,21 @@ open class ReportService(
}
rowIndex++
}
// tempCell = sheet.getRow(rowIndex).getCell(columnIndex)
// tempCell.setCellValue()

val sheetCF = sheet.sheetConditionalFormatting
val rule1 = sheetCF.createConditionalFormattingRule("AND(J7 >= $lowerLimit, J7 <= 1)")
val rule2 = sheetCF.createConditionalFormattingRule("J7 > 1")
var fillOrange = rule1.createPatternFormatting()
fillOrange.setFillBackgroundColor(IndexedColors.LIGHT_ORANGE.index);
fillOrange.setFillPattern(PatternFormatting.SOLID_FOREGROUND)

var fillRed = rule2.createPatternFormatting()
fillRed.setFillBackgroundColor(IndexedColors.ROSE.index);
fillRed.setFillPattern(PatternFormatting.SOLID_FOREGROUND)

val cfRules = arrayOf(rule1, rule2)
val regions = arrayOf(CellRangeAddress.valueOf("\$J7:\$K${rowIndex+1}"))
sheetCF.addConditionalFormatting(regions, cfRules);

return workbook
}
@@ -1256,26 +1272,25 @@ open class ReportService(
open fun getProjectResourceOverconsumptionReport(args: Map<String, Any>): List<Map<String, Any>> {
val sql = StringBuilder("WITH teamNormalConsumed AS ("
+ " SELECT "
+ " s.teamId, "
+ " s.teamId, "
+ " pt.project_id, "
+ " SUM(tns.totalConsumed) AS totalConsumed "
+ " FROM ( "
+ " SELECT "
+ " t.staffId, "
+ " FROM ( "
+ " SELECT "
+ " t.staffId, "
+ " sum(t.normalConsumed + COALESCE(t.otConsumed, 0)) as totalConsumed, "
+ " t.projectTaskId AS taskId "
+ " FROM timesheet t "
+ " LEFT JOIN staff s ON t.staffId = s.id "
+ " GROUP BY t.staffId, t.projectTaskId "
+ " FROM timesheet t "
+ " LEFT JOIN staff s ON t.staffId = s.id "
+ " GROUP BY t.staffId, t.projectTaskId "
+ " ) AS tns "
+ " INNER JOIN project_task pt ON tns.taskId = pt.id "
+ " JOIN staff s ON tns.staffId = s.id "
+ " JOIN team t ON s.teamId = t.id "
+ " GROUP BY teamId, project_id "
+ " INNER JOIN project_task pt ON tns.taskId = pt.id "
+ " JOIN staff s ON tns.staffId = s.id "
+ " JOIN team t ON s.teamId = t.id "
+ " GROUP BY teamId, project_id "
+ " ) "
+ " SELECT "
+ " p.code, "
+ " -- p.status, "
+ " p.name, "
+ " t.code as team, "
+ " c.code as client, "
@@ -1286,8 +1301,8 @@ open class ReportService(
+ " (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) as budgetConsumptionRate, "
+ " (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) as manhourConsumptionRate, "
+ " CASE "
+ " when (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= 0.9 and (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) <= 1 "
+ " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 0.9 and (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) <= 1 "
+ " 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 "
+ " or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 1 "
@@ -1311,16 +1326,18 @@ open class ReportService(
sql.append("and c.id = :custId")
if (args.containsKey("status"))
statusFilter = when (args.get("status")) {
"Potential Overconsumption" -> " ( and " +
"((COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= 0.9 " +
"and (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) <= 1 " +
"or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 0.9 " +
"and (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) <= 1)" +
" ) "
"Overconsumption" -> " ( and " +
"((COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= 1 " +
"or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 1)" +
" ) "
"Potential Overconsumption" -> "and " +
" ((COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= 0.9 " +
" and (COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) <= 1 " +
" or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 0.9 " +
" and (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) <= 1)"
"Overconsumption" -> "and " +
" ((COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) >= 1 " +
" or (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) >= 1) "
"Within Budget" -> "and " +
" ((COALESCE((tns.totalConsumed * sa.hourlyRate), 0) / p.expectedTotalFee) < 0.9 " +
" and " +
" (COALESCE(tns.totalConsumed, 0) / COALESCE(p.totalManhour, 0)) <= 0.9 "
else -> ""
}
sql.append(statusFilter)


+ 15
- 12
src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt Прегледај датотеку

@@ -115,20 +115,23 @@ class ReportController(
@PostMapping("/ProjectResourceOverconsumptionReport")
@Throws(ServletRequestBindingException::class, IOException::class)
fun ProjectResourceOverconsumptionReport(@RequestBody @Valid request: ProjectResourceOverconsumptionReport): ResponseEntity<Resource> {
// val staff = staffRepository.findById(request.id).orElseThrow()
val args: Map<String, Any> = mutableMapOf(
"teamId" to request.teamId,
"custId" to request.custId,
"status" to request.status
val lowerLimit = request.lowerLimit
var team: String = "All"
var customer: String = "All"
val args: MutableMap<String, Any> = mutableMapOf(
"status" to request.status,
"lowerLimit" to lowerLimit
)
val team: String = teamService.find(request.teamId).orElseThrow().name
val customer: String = customerService.find(request.custId).orElseThrow().name
if (request.teamId != null) {
args["teamId"] = request.teamId
team = teamService.find(request.teamId).orElseThrow().name
}
if (request.custId != null) {
args["custId"] = request.custId
customer = customerService.find(request.custId).orElseThrow().name
}
val result: List<Map<String, Any>> = excelReportService.getProjectResourceOverconsumptionReport(args);
// val obj: ProjectResourceReport = mapper.readValue(mapper.writeValueAsBytes(result))


val reportResult: ByteArray = excelReportService.generateProjectResourceOverconsumptionReport(team, customer, result)
val reportResult: ByteArray = excelReportService.generateProjectResourceOverconsumptionReport(team, customer, result, lowerLimit)
// val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
return ResponseEntity.ok()
// .contentType(mediaType)


+ 3
- 2
src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt Прегледај датотеку

@@ -25,7 +25,8 @@ data class LateStartReportRequest (
val reportDate: LocalDate
)
data class ProjectResourceOverconsumptionReport (
val teamId: Long,
val custId: Long,
val teamId: Long?,
val custId: Long?,
val status: String,
val lowerLimit: Double
)

BIN
src/main/resources/templates/report/AR03_Resource Overconsumption.xlsx Прегледај датотеку


Loading…
Откажи
Сачувај