From 01c738b8e7a3094e38fa9407e161938f8c42e0f1 Mon Sep 17 00:00:00 2001 From: "cyril.tsui" Date: Thu, 8 Aug 2024 18:19:37 +0800 Subject: [PATCH] update settings, report (salary effective) --- .../data/service/SalaryEffectiveService.kt | 40 +++ .../data/web/SalaryEffectiveController.kt | 10 +- .../modules/report/service/ReportService.kt | 229 ++++++++++++------ .../modules/report/web/ReportController.kt | 10 +- .../settings/entity/SettingsRepository.java | 3 + .../settings/service/SettingsService.java | 5 + 6 files changed, 214 insertions(+), 83 deletions(-) diff --git a/src/main/java/com/ffii/tsms/modules/data/service/SalaryEffectiveService.kt b/src/main/java/com/ffii/tsms/modules/data/service/SalaryEffectiveService.kt index efda40a..5b9cf60 100644 --- a/src/main/java/com/ffii/tsms/modules/data/service/SalaryEffectiveService.kt +++ b/src/main/java/com/ffii/tsms/modules/data/service/SalaryEffectiveService.kt @@ -6,10 +6,13 @@ import com.ffii.tsms.modules.data.entity.Salary import com.ffii.tsms.modules.data.entity.SalaryEffective import com.ffii.tsms.modules.data.entity.SalaryEffectiveRepository import com.ffii.tsms.modules.data.entity.SalaryRepository +import com.ffii.tsms.modules.data.entity.Staff import com.ffii.tsms.modules.data.entity.StaffRepository import org.springframework.stereotype.Service import java.math.BigDecimal import java.time.LocalDate +import java.time.LocalDateTime +import java.time.temporal.ChronoUnit @Service open class SalaryEffectiveService( @@ -90,4 +93,41 @@ open class SalaryEffectiveService( // println(salaryEffectiveLists) return salaryEffectiveLists } + + data class MonthlyStaffSalaryData( + val staff: Staff, + val date: LocalDate, + val hourlyRate: Double, + ) + + open fun getMonthlyStaffSalaryData(startDate: LocalDate, endDate: LocalDate): List { + val salaryEffective = salaryEffectiveRepository.findAll() + .groupBy { Pair(it.date.year, it.date.month) } + .map { (_, se) -> se.maxByOrNull { it.date }!!} + salaryEffective.sortedWith(compareBy({it.staff.staffId}, {it.date})) + + val staffs = staffRepository.findAll().sortedBy { it.staffId }.filter { it.deleted == false } + + val result = mutableListOf() + val dateList = (0..ChronoUnit.MONTHS.between(startDate, endDate)).map { startDate.withDayOfMonth(1).plusMonths(it) } + + staffs.forEach { staff -> + dateList.forEach{ date -> + val staffSalaryEffective = salaryEffective.filter { it.staff.staffId.equals(staff.staffId) } + var currentHourlyRate = staffSalaryEffective.filter { date.isEqual(it.date.withDayOfMonth(1)) || date.isAfter(it.date.withDayOfMonth(1)) }.minByOrNull { it.date } + + if (currentHourlyRate == null) { + currentHourlyRate = staffSalaryEffective.minByOrNull { it.date } + } + + result += MonthlyStaffSalaryData( + staff = staff, + date = date, + hourlyRate = currentHourlyRate?.salary?.hourlyRate?.toDouble() ?: staff?.salary?.hourlyRate?.toDouble() ?: 0.0 + ) + } + } + + return result + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/tsms/modules/data/web/SalaryEffectiveController.kt b/src/main/java/com/ffii/tsms/modules/data/web/SalaryEffectiveController.kt index e889545..7c97b2b 100644 --- a/src/main/java/com/ffii/tsms/modules/data/web/SalaryEffectiveController.kt +++ b/src/main/java/com/ffii/tsms/modules/data/web/SalaryEffectiveController.kt @@ -4,16 +4,20 @@ import com.ffii.core.response.RecordsRes import com.ffii.core.utils.CriteriaArgsBuilder import com.ffii.tsms.modules.data.service.SalaryEffectiveService import jakarta.servlet.http.HttpServletRequest +import jakarta.validation.Valid import org.springframework.web.bind.ServletRequestBindingException -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* +import java.time.LocalDate @RestController @RequestMapping("/salaryEffective") class SalaryEffectiveController(private val salaryEffectiveService: SalaryEffectiveService) { + @GetMapping("/test") + fun test(@RequestParam startDate: LocalDate, @RequestParam endDate: LocalDate): List { + return salaryEffectiveService.getMonthlyStaffSalaryData(startDate, endDate) + } // @GetMapping("/combo") // @Throws(ServletRequestBindingException::class) // fun combo(request: HttpServletRequest?): RecordsRes> { diff --git a/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt b/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt index 44f7352..3778cc0 100644 --- a/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt +++ b/src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt @@ -3,6 +3,7 @@ package com.ffii.tsms.modules.report.service import com.ffii.core.support.JdbcDao import com.ffii.tsms.modules.data.entity.* import com.ffii.tsms.modules.data.service.SalaryEffectiveService +import com.ffii.tsms.modules.data.service.SalaryEffectiveService.MonthlyStaffSalaryData import com.ffii.tsms.modules.project.entity.Invoice import com.ffii.tsms.modules.project.entity.Milestone import com.ffii.tsms.modules.project.entity.Project @@ -186,11 +187,19 @@ open class ReportService( project: Project, invoices: List, timesheets: List, + monthlyStaffSalaryEffective: List, dateType: String ): ByteArray { // Generate the Excel report with query results val workbook: Workbook = - createProjectCashFlowReport(project, invoices, timesheets, dateType, PROJECT_CASH_FLOW_REPORT) + createProjectCashFlowReport( + project, + invoices, + timesheets, + monthlyStaffSalaryEffective, + dateType, + PROJECT_CASH_FLOW_REPORT + ) // Write the workbook to a ByteArrayOutputStream val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() @@ -349,11 +358,20 @@ open class ReportService( timesheets: List, teams: List, grades: List, + monthlyStaffSalaryEffective: List, teamId: String, ): ByteArray { // Generate the Excel report with query results val workbook: Workbook = - createCrossTeamChargeReport(month, timesheets, teams, grades, teamId, CROSS_TEAM_CHARGE_REPORT) + createCrossTeamChargeReport( + month, + timesheets, + teams, + grades, + monthlyStaffSalaryEffective, + teamId, + CROSS_TEAM_CHARGE_REPORT + ) // Write the workbook to a ByteArrayOutputStream val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() @@ -461,7 +479,9 @@ open class ReportService( endDateCell.setCellValue(if (item["planEnd"] != null) item.getValue("planEnd").toString() else "N/A") val totalFeeCell = row.createCell(7) - val totalFee = (item["expectedTotalFee"]?.let { it as Double } ?: 0.0) - (item["subContractFee"]?.let { it as Double } ?: 0.0) + val totalFee = + (item["expectedTotalFee"]?.let { it as Double } ?: 0.0) - (item["subContractFee"]?.let { it as Double } + ?: 0.0) totalFeeCell.apply { setCellValue(totalFee) cellStyle.dataFormat = accountingStyle @@ -722,6 +742,7 @@ open class ReportService( project: Project, invoices: List, timesheets: List, + monthlyStaffSalaryEffective: List, dateType: String, templatePath: String, ): Workbook { @@ -792,8 +813,10 @@ open class ReportService( rowIndex = 11 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)) +// timesheet.staff!!.salary.hourlyRate.toDouble() * ((timesheet.normalConsumed ?: 0.0) + (timesheet.otConsumed ?: 0.0)) + (monthlyStaffSalaryEffective.find { + it.staff.staffId == timesheet.staff?.staffId && it.date.year == timesheet.recordDate?.year && it.date.month == timesheet.recordDate?.month + }?.hourlyRate ?: 0.0) * ((timesheet.normalConsumed ?: 0.0) + (timesheet.otConsumed ?: 0.0)) } sheet.getRow(rowIndex).apply { createCell(1).apply { @@ -834,10 +857,16 @@ open class ReportService( timesheetEntries.map { timesheet -> if (timesheet.normalConsumed != null) { timesheet.normalConsumed!!.plus(timesheet.otConsumed ?: 0.0) - .times(timesheet.staff!!.salary.hourlyRate.toDouble()) +// .times(timesheet.staff!!.salary.hourlyRate.toDouble()) + .times(monthlyStaffSalaryEffective.find { + it.staff.staffId == timesheet.staff?.staffId && it.date.year == timesheet.recordDate?.year && it.date.month == timesheet.recordDate?.month + }?.hourlyRate ?: 0.0) } else if (timesheet.otConsumed != null) { timesheet.otConsumed!!.plus(timesheet.normalConsumed ?: 0.0) - .times(timesheet.staff!!.salary.hourlyRate.toDouble()) +// .times(timesheet.staff!!.salary.hourlyRate.toDouble()) + .times(monthlyStaffSalaryEffective.find { + it.staff.staffId == timesheet.staff?.staffId && it.date.year == timesheet.recordDate?.year && it.date.month == timesheet.recordDate?.month + }?.hourlyRate ?: 0.0) } else { 0.0 } @@ -2302,7 +2331,13 @@ open class ReportService( for (item in manHoursSpent) { updateInfo(info, item) - val hourlyRate = getSalaryForMonth(item.getValue("recordDate") as String, item.getValue("staffId") as String, staffSalaryLists, queryStartMonth, queryEndMonth) ?: (item.getValue("hourlyRate") as BigDecimal).toDouble() + val hourlyRate = getSalaryForMonth( + item.getValue("recordDate") as String, + item.getValue("staffId") as String, + staffSalaryLists, + queryStartMonth, + queryEndMonth + ) ?: (item.getValue("hourlyRate") as BigDecimal).toDouble() if (!staffInfoList.any { it["staffId"] == item["staffId"] && it["name"] == item["name"] }) { @@ -2374,7 +2409,13 @@ open class ReportService( return tempList } - fun getSalaryForMonth(recordDate: String, staffId: String, staffSalaryLists: List, start: YearMonth, end: YearMonth): Double? { + fun getSalaryForMonth( + recordDate: String, + staffId: String, + staffSalaryLists: List, + start: YearMonth, + end: YearMonth + ): Double? { val formatter = DateTimeFormatter.ofPattern("yyyy-MM") val monthDate = YearMonth.parse(recordDate, formatter) @@ -2383,7 +2424,12 @@ open class ReportService( return findSalaryForMonth(staffSalaryData, monthDate, start, end) } - private fun findSalaryForMonth(salaryDataList: List, targetMonth: YearMonth, start: YearMonth, end: YearMonth): Double? { + private fun findSalaryForMonth( + salaryDataList: List, + targetMonth: YearMonth, + start: YearMonth, + end: YearMonth + ): Double? { if (salaryDataList.isEmpty()) return null val periodStartMonth = 10 @@ -2416,23 +2462,27 @@ open class ReportService( val staffSalaryData = staffSalaryDataList.find { it.staffId == staffId } // if (staffSalaryData != null) { - val updatedFinancialYears = (staffInfo["financialYears"] as List).map { financialYear -> - updateFinancialYear(financialYear, staffSalaryData?.salaryData, staffInfo) - } + val updatedFinancialYears = (staffInfo["financialYears"] as List).map { financialYear -> + updateFinancialYear(financialYear, staffSalaryData?.salaryData, staffInfo) + } - val updatedStaffInfo = staffInfo.toMutableMap().apply { - this["financialYears"] = updatedFinancialYears - } + val updatedStaffInfo = staffInfo.toMutableMap().apply { + this["financialYears"] = updatedFinancialYears + } - staffInfoList[index] = updatedStaffInfo + staffInfoList[index] = updatedStaffInfo // } } } - fun updateFinancialYear(financialYear: FinancialYear, salaryDataList: List?, staffInfo: Map): FinancialYear { + fun updateFinancialYear( + financialYear: FinancialYear, + salaryDataList: List?, + staffInfo: Map + ): FinancialYear { println("====================== staffInfo: $staffInfo ===============================") - if(salaryDataList == null){ + if (salaryDataList == null) { return financialYear.copy( hourlyRate = (staffInfo["hourlyRate"] as BigDecimal).toDouble(), salaryPoint = (staffInfo["salaryPoint"] as Long).toInt() @@ -2457,13 +2507,17 @@ open class ReportService( println("====================== staffInfo: $staffInfo ===============================") return financialYear.copy( - hourlyRate = previousHourlyRate?.toDouble() ?: financialYear.hourlyRate, - salaryPoint = previousSalaryPoint ?: financialYear.salaryPoint + hourlyRate = previousHourlyRate?.toDouble() ?: (staffInfo["hourlyRate"] as BigDecimal).toDouble(), + salaryPoint = previousSalaryPoint ?: (staffInfo["salaryPoint"] as Long).toInt() ) } } - fun findPreviousValue(salaryDataList: List, currentStart: YearMonth, valueSelector: (SalaryEffectiveService.SalaryData) -> T): T? { + fun findPreviousValue( + salaryDataList: List, + currentStart: YearMonth, + valueSelector: (SalaryEffectiveService.SalaryData) -> T + ): T? { return salaryDataList .filter { YearMonth.from(it.financialYear) < currentStart } .maxByOrNull { it.financialYear } @@ -2486,10 +2540,11 @@ open class ReportService( } // For Calculating the Financial Year - data class FinancialYear(val start: YearMonth, val end: YearMonth, var hourlyRate: Double, var salaryPoint: Int){ - fun isYearMonthInFinancialYear(salaryEffectiveMonth: YearMonth) :Boolean{ + data class FinancialYear(val start: YearMonth, val end: YearMonth, var hourlyRate: Double, var salaryPoint: Int) { + fun isYearMonthInFinancialYear(salaryEffectiveMonth: YearMonth): Boolean { if ((salaryEffectiveMonth.isAfter(start) || salaryEffectiveMonth.equals(start)) && - (salaryEffectiveMonth.isBefore(end) || salaryEffectiveMonth.equals(end))){ + (salaryEffectiveMonth.isBefore(end) || salaryEffectiveMonth.equals(end)) + ) { return true } return false @@ -2588,12 +2643,13 @@ open class ReportService( return financialYearDates } - private fun getOrCreateRow(sheet: Sheet, startRow: Int): Row{ + + private fun getOrCreateRow(sheet: Sheet, startRow: Int): Row { val row: Row = sheet.getRow(startRow) ?: sheet.createRow(startRow) return row } - private fun getOrCreateCell(row: Row, columnIndex: Int): Cell{ + private fun getOrCreateCell(row: Row, columnIndex: Int): Cell { val cell: Cell = row.getCell(columnIndex) ?: row.createCell(columnIndex) return cell } @@ -2733,7 +2789,7 @@ open class ReportService( // Average Hourly Rate by Pay Scale Point rowNum = 8 val row8: Row = sheet.getRow(rowNum) ?: sheet.createRow(rowNum) - sheet.addMergedRegion(CellRangeAddress(rowNum, rowNum, 2, (financialYears.size+1)*2-1)) + sheet.addMergedRegion(CellRangeAddress(rowNum, rowNum, 2, (financialYears.size + 1) * 2 - 1)) val row8Cell = row8.getCell(2) ?: row8.createCell(2) row8Cell.apply { setCellValue("Average Hourly Rate by Pay Scale Point") @@ -2750,9 +2806,15 @@ open class ReportService( 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 row9Cell2 = row9.getCell(column + 1) ?: row9.createCell(column + 1) sheet.addMergedRegion(CellRangeAddress(rowNum, rowNum, column, column + 1)) - row9Cell.setCellValue("${financialYears[i].start.format(monthFormat)} - ${financialYears[i].end.format(monthFormat)}") + row9Cell.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) @@ -2786,7 +2848,7 @@ open class ReportService( var salaryColumn = 2 for (year in years) { val salaryPointCell = row.getCell(salaryColumn) ?: row.createCell(salaryColumn) - sheet.addMergedRegion(CellRangeAddress(rowNum, rowNum, salaryColumn, salaryColumn+1)) + sheet.addMergedRegion(CellRangeAddress(rowNum, rowNum, salaryColumn, salaryColumn + 1)) salaryPointCell.apply { setCellValue("${year.salaryPoint} (${year.hourlyRate})") } @@ -3300,6 +3362,7 @@ open class ReportService( timesheets: List, teams: List, grades: List, + monthlyStaffSalaryEffective: List, teamId: String, templatePath: String, ): Workbook { @@ -3374,13 +3437,19 @@ open class ReportService( mutableMapOf().apply { this["manHour"] = timesheet.normalConsumed!!.plus(timesheet.otConsumed ?: 0.0) this["salary"] = timesheet.normalConsumed!!.plus(timesheet.otConsumed ?: 0.0) - .times(timesheet.staff!!.salary.hourlyRate.toDouble()) +// .times(timesheet.staff!!.salary.hourlyRate.toDouble()) + .times(monthlyStaffSalaryEffective.find { + it.staff.staffId == timesheet.staff?.staffId && it.date.year == timesheet.recordDate?.year && it.date.month == timesheet.recordDate?.month + }?.hourlyRate ?: 0.0) } } else if (timesheet.otConsumed != null) { mutableMapOf().apply { this["manHour"] = timesheet.otConsumed!!.plus(timesheet.normalConsumed ?: 0.0) this["salary"] = timesheet.otConsumed!!.plus(timesheet.normalConsumed ?: 0.0) - .times(timesheet.staff!!.salary.hourlyRate.toDouble()) +// .times(timesheet.staff!!.salary.hourlyRate.toDouble()) + .times(monthlyStaffSalaryEffective.find { + it.staff.staffId == timesheet.staff?.staffId && it.date.year == timesheet.recordDate?.year && it.date.month == timesheet.recordDate?.month + }?.hourlyRate ?: 0.0) } } else { mutableMapOf().apply { @@ -3626,13 +3695,19 @@ open class ReportService( mutableMapOf().apply { this["manHour"] = timesheet.normalConsumed!!.plus(timesheet.otConsumed ?: 0.0) this["salary"] = timesheet.normalConsumed!!.plus(timesheet.otConsumed ?: 0.0) - .times(timesheet.staff!!.salary.hourlyRate.toDouble()) +// .times(timesheet.staff!!.salary.hourlyRate.toDouble()) + .times(monthlyStaffSalaryEffective.find { + it.staff.staffId == timesheet.staff?.staffId && it.date.year == timesheet.recordDate?.year && it.date.month == timesheet.recordDate?.month + }?.hourlyRate ?: 0.0) } } else if (timesheet.otConsumed != null) { mutableMapOf().apply { this["manHour"] = timesheet.otConsumed!!.plus(timesheet.normalConsumed ?: 0.0) this["salary"] = timesheet.otConsumed!!.plus(timesheet.normalConsumed ?: 0.0) - .times(timesheet.staff!!.salary.hourlyRate.toDouble()) +// .times(timesheet.staff!!.salary.hourlyRate.toDouble()) + .times(monthlyStaffSalaryEffective.find { + it.staff.staffId == timesheet.staff?.staffId && it.date.year == timesheet.recordDate?.year && it.date.month == timesheet.recordDate?.month + }?.hourlyRate ?: 0.0) } } else { mutableMapOf().apply { @@ -3737,61 +3812,61 @@ open class ReportService( projects.forEach { project: Project -> if (teamId.lowercase() == "all" || teamId.toLong() == project.teamLead?.team?.id || teamId.toLong() == team.id) { // if (team.id == project.teamLead?.team?.id) { - endRow++ - sheet.createRow(rowIndex++).apply { - columnIndex = 0 - createCell(columnIndex++).apply { - setCellValue("${project.code}: ${project.name}") - val cloneStyle = workbook.createCellStyle() - cloneStyle.cloneStyleFrom(normalFontWithBorderStyle) - cellStyle = cloneStyle.apply { - alignment = HorizontalAlignment.LEFT - } + endRow++ + sheet.createRow(rowIndex++).apply { + columnIndex = 0 + createCell(columnIndex++).apply { + setCellValue("${project.code}: ${project.name}") + val cloneStyle = workbook.createCellStyle() + cloneStyle.cloneStyleFrom(normalFontWithBorderStyle) + cellStyle = cloneStyle.apply { + alignment = HorizontalAlignment.LEFT } + } - var totalSalary = 0.0 - staffs.forEach { staff: Staff -> - logger.info("Staff: ${staff.staffId}") - createCell(columnIndex++).apply { - setCellValue( - groupedTimesheetsIndividual[Pair( - project.id, - staff.id, - )]?.sumOf { it.getValue("manHour") } ?: 0.0) - - totalSalary += groupedTimesheetsIndividual[Pair( + var totalSalary = 0.0 + staffs.forEach { staff: Staff -> + logger.info("Staff: ${staff.staffId}") + createCell(columnIndex++).apply { + setCellValue( + groupedTimesheetsIndividual[Pair( project.id, - staff.id - )]?.sumOf { it.getValue("salary") } ?: 0.0 - - val cloneStyle = workbook.createCellStyle() - cloneStyle.cloneStyleFrom(normalFontWithBorderStyle) - cellStyle = cloneStyle.apply { - dataFormat = accountingStyle - } - } - } + staff.id, + )]?.sumOf { it.getValue("manHour") } ?: 0.0) - createCell(columnIndex++).apply { - val lastCellLetter = CellReference.convertNumToColString(this.columnIndex - 1) - cellFormula = "sum(B${this.rowIndex + 1}:${lastCellLetter}${this.rowIndex + 1})" + totalSalary += groupedTimesheetsIndividual[Pair( + project.id, + staff.id + )]?.sumOf { it.getValue("salary") } ?: 0.0 val cloneStyle = workbook.createCellStyle() - cloneStyle.cloneStyleFrom(boldFontWithBorderStyle) + cloneStyle.cloneStyleFrom(normalFontWithBorderStyle) cellStyle = cloneStyle.apply { dataFormat = accountingStyle } } + } - createCell(columnIndex).apply { - setCellValue(totalSalary) - val cloneStyle = workbook.createCellStyle() - cloneStyle.cloneStyleFrom(boldFontWithBorderStyle) - cellStyle = cloneStyle.apply { - dataFormat = accountingStyle - } + createCell(columnIndex++).apply { + val lastCellLetter = CellReference.convertNumToColString(this.columnIndex - 1) + cellFormula = "sum(B${this.rowIndex + 1}:${lastCellLetter}${this.rowIndex + 1})" + + val cloneStyle = workbook.createCellStyle() + cloneStyle.cloneStyleFrom(boldFontWithBorderStyle) + cellStyle = cloneStyle.apply { + dataFormat = accountingStyle } } + + createCell(columnIndex).apply { + setCellValue(totalSalary) + val cloneStyle = workbook.createCellStyle() + cloneStyle.cloneStyleFrom(boldFontWithBorderStyle) + cellStyle = cloneStyle.apply { + dataFormat = accountingStyle + } + } + } // } } } diff --git a/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt b/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt index 8f858ba..33ac778 100644 --- a/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt +++ b/src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt @@ -6,6 +6,7 @@ import com.ffii.tsms.modules.common.SecurityUtils import com.ffii.tsms.modules.data.entity.* //import com.ffii.tsms.modules.data.entity.projections.FinancialStatusReportInfo import com.ffii.tsms.modules.data.service.CustomerService +import com.ffii.tsms.modules.data.service.SalaryEffectiveService import com.ffii.tsms.modules.data.service.StaffsService import com.ffii.tsms.modules.data.service.TeamService import com.ffii.tsms.modules.project.entity.* @@ -60,7 +61,8 @@ class ReportController( private val subsidiaryService: SubsidiaryService, private val invoiceService: InvoiceService, private val gradeAllocationRepository: GradeAllocationRepository, private val subsidiaryRepository: SubsidiaryRepository, private val staffAllocationRepository: StaffAllocationRepository, - private val gradeRepository: GradeRepository + private val gradeRepository: GradeRepository, + private val salaryEffectiveService: SalaryEffectiveService, ) { private val logger: Log = LogFactory.getLog(javaClass) @@ -85,8 +87,9 @@ class ReportController( // val invoices = invoiceService.findAllByProjectAndPaidAmountIsNotNull(project) val invoices = invoiceRepository.findAllByProjectCodeAndPaidAmountIsNotNull(project.code!!) val timesheets = timesheetRepository.findAllByProjectTaskIn(projectTasks) + val monthlyStaffSalaryEffective = salaryEffectiveService.getMonthlyStaffSalaryData(timesheets.minByOrNull { it.recordDate!! }?.recordDate ?: LocalDate.parse("2012-01-01"), timesheets.maxByOrNull { it.recordDate!! }?.recordDate ?: LocalDate.now()) - val reportResult: ByteArray = excelReportService.generateProjectCashFlowReport(project, invoices, timesheets, request.dateType) + val reportResult: ByteArray = excelReportService.generateProjectCashFlowReport(project, invoices, timesheets, monthlyStaffSalaryEffective, request.dateType) // val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") return ResponseEntity.ok() // .contentType(mediaType) @@ -336,8 +339,9 @@ class ReportController( (it.recordDate!!.isEqual(startDate) || it.recordDate!!.isEqual(endDate) || (it.recordDate!!.isAfter(startDate) && it.recordDate!!.isBefore(endDate)))} val teams = teamRepository.findAll().filter { it.deleted == false } val grades = gradeRepository.findAll().filter { it.deleted == false } + val monthlyStaffSalaryEffective = salaryEffectiveService.getMonthlyStaffSalaryData(startDate, endDate) - val reportResult: ByteArray = excelReportService.generateCrossTeamChargeReport(request.month, timesheets, teams, grades, request.teamId) + val reportResult: ByteArray = excelReportService.generateCrossTeamChargeReport(request.month, timesheets, teams, grades, monthlyStaffSalaryEffective, request.teamId) return ResponseEntity.ok() .header("filename", "Cross Team Charge Report - " + LocalDate.now() + ".xlsx") .body(ByteArrayResource(reportResult)) diff --git a/src/main/java/com/ffii/tsms/modules/settings/entity/SettingsRepository.java b/src/main/java/com/ffii/tsms/modules/settings/entity/SettingsRepository.java index fdf27ef..ddf1a19 100644 --- a/src/main/java/com/ffii/tsms/modules/settings/entity/SettingsRepository.java +++ b/src/main/java/com/ffii/tsms/modules/settings/entity/SettingsRepository.java @@ -1,5 +1,6 @@ package com.ffii.tsms.modules.settings.entity; +import java.util.List; import java.util.Optional; import org.springframework.data.repository.query.Param; @@ -9,4 +10,6 @@ import com.ffii.core.support.AbstractRepository; public interface SettingsRepository extends AbstractRepository { Optional findByName(@Param("name") String name); + + List findAllByCategory(@Param("category") String category); } diff --git a/src/main/java/com/ffii/tsms/modules/settings/service/SettingsService.java b/src/main/java/com/ffii/tsms/modules/settings/service/SettingsService.java index c108690..bf01f9a 100644 --- a/src/main/java/com/ffii/tsms/modules/settings/service/SettingsService.java +++ b/src/main/java/com/ffii/tsms/modules/settings/service/SettingsService.java @@ -5,6 +5,7 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.util.List; import java.util.Optional; import org.apache.commons.lang3.StringUtils; @@ -29,6 +30,10 @@ public class SettingsService extends AbstractIdEntityService findAllByCategory(String category) { + return this.repository.findAllByCategory(category); + } + public boolean validateType(String type, String value) { if (StringUtils.isBlank(type)) return true;