Преглед на файлове

Update export Staff Info, Update Financial status report

master
MSI\2Fi преди 3 месеца
родител
ревизия
6cdf5b6519
променени са 6 файла, в които са добавени 127 реда и са изтрити 38 реда
  1. +14
    -0
      src/main/java/com/ffii/tsms/modules/data/service/StaffsService.kt
  2. +5
    -0
      src/main/java/com/ffii/tsms/modules/data/web/StaffsController.kt
  3. +95
    -31
      src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt
  4. +10
    -6
      src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt
  5. +3
    -1
      src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt
  6. Двоични данни
      src/main/resources/templates/report/EX01_Financial Status Report.xlsx

+ 14
- 0
src/main/java/com/ffii/tsms/modules/data/service/StaffsService.kt Целия файл

@@ -22,6 +22,7 @@ import java.util.*
import kotlin.jvm.optionals.getOrNull



@Service
open class StaffsService(
private val staffRepository: StaffRepository,
@@ -426,4 +427,17 @@ open class StaffsService(

return jdbcDao.queryForList(sql.toString(), mapOf("ids" to args))
}

open fun manuelUpdateSalaryEffectiveDate() {
val staffIds = findAll().get().filter { it.departDate == null || it.departDate < LocalDate.now() }.map { it.id }
println(staffIds)
val salaryEffectiveInfo = salaryEffectiveRepository.findSalaryEffectiveInfoByStaffIdInOrderByStaffId(staffIds)
staffIds.forEach { id ->
val filteredSalaryEffective = salaryEffectiveInfo.filter { it.idInStaff == id }
val updatedSalaryEffectiveInfo = filteredSalaryEffective.map { it -> SalaryEffectiveInfo(it.idInStaff, it.salary.salaryPoint.toLong(), it.date ) }
val delSalaryEffectiveInfo = filteredSalaryEffective.map { it.id!! }
salaryEffectiveService.updateSalaryEffective(id!!, updatedSalaryEffectiveInfo.sortedBy { it.date }, delSalaryEffectiveInfo)
}

}
}

+ 5
- 0
src/main/java/com/ffii/tsms/modules/data/web/StaffsController.kt Целия файл

@@ -78,4 +78,9 @@ class StaffsController(private val staffsService: StaffsService) {
fun saveStaff(@Valid @RequestBody newStaff: NewStaffRequest): NewStaffResponse {
return staffsService.saveOrUpdate(newStaff)
}

@GetMapping("/manuelUpdate")
fun manualUpdate(){
staffsService.manuelUpdateSalaryEffectiveDate()
}
}

+ 95
- 31
src/main/java/com/ffii/tsms/modules/report/service/ReportService.kt Целия файл

@@ -193,10 +193,10 @@ open class ReportService(
return rowIndex
}

fun genFinancialStatusReport(teamLeadId: Long): ByteArray {
fun genFinancialStatusReport(teamLeadId: Long, startMonth: String, endMonth: String): ByteArray {

val financialStatus: List<Map<String, Any>> = getFinancialStatus(teamLeadId)
val manhoursSpent = getManHoursSpentByTeam(teamLeadId)
val financialStatus: List<Map<String, Any>> = getFinancialStatus(teamLeadId, startMonth, endMonth)
val manhoursSpent = getManHoursSpentByTeam(teamLeadId, startMonth, endMonth)
val salaryEffectiveMap = getSalaryEffectiveByTeamLead(teamLeadId)
val updatedTimesheetData = updateTimesheetDataWithEffectiveSalary(manhoursSpent, salaryEffectiveMap)
val projectsExpenditure = calculateProjectExpenditures(updatedTimesheetData)
@@ -213,7 +213,7 @@ open class ReportService(
}
}

val workbook: Workbook = createFinancialStatusReport(FINANCIAL_STATUS_REPORT, updatedList, teamLeadId)
val workbook: Workbook = createFinancialStatusReport(FINANCIAL_STATUS_REPORT, updatedList, teamLeadId, startMonth, endMonth)

val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
workbook.write(outputStream)
@@ -444,7 +444,9 @@ open class ReportService(
private fun createFinancialStatusReport(
templatePath: String,
projects: List<Map<String, Any>>,
teamLeadId: Long
teamLeadId: Long,
startMonth: String,
endMonth: String,
): Workbook {

val resource = ClassPathResource(templatePath)
@@ -468,7 +470,7 @@ open class ReportService(

val boldFontCellStyle = workbook.createCellStyle()
boldFontCellStyle.setFont(boldFont)
var rowNum = 14
var rowNum = 16

if (projects.isEmpty()) {
// Fill the cell in Row 2-12 with thr calculated sum
@@ -496,10 +498,15 @@ open class ReportService(
setCellValue("$code - $name")
}

rowNum = 4
val row4: Row = sheet.getRow(rowNum)
val row4Cell = row4.createCell(2)
row4Cell.setCellValue(projects.size.toString())
rowNum = 3
val row3: Row = sheet.getRow(rowNum)
val row3Cell = row3.createCell(2)
row3Cell.setCellValue("$startMonth - $endMonth")

rowNum = 4+1
val row5: Row = sheet.getRow(rowNum)
val row5Cell = row5.createCell(2)
row5Cell.setCellValue(projects.size.toString())

return workbook
}
@@ -543,9 +550,11 @@ open class ReportService(
setCellValue(totalFee)
cellStyle.dataFormat = accountingStyle
}
// subContractFee is count in fee
// val fee = (item["expectedTotalFee"]?.let { it as Double } ?: 0.0) - (item["subContractFee"]?.let { it as Double }
// ?: 0.0)

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

val budgetCell = row.createCell(8)
budgetCell.apply {
@@ -759,16 +768,21 @@ open class ReportService(
row2Cell.setCellValue("All")
} else {
row2Cell.apply {
cellFormula = "E15"
cellFormula = "E16"
}
}

rowNum = 4
rowNum = 3
val row3: Row = sheet.getRow(rowNum)
val row3Cell = row3.createCell(2)
row3Cell.setCellValue("$startMonth - $endMonth")

rowNum = 4+1
val row4: Row = sheet.getRow(rowNum)
val row4Cell = row4.createCell(2)
row4Cell.setCellValue(projects.size.toString())

rowNum = 5
rowNum = 5+1
val row5: Row = sheet.getRow(rowNum)
val cell1 = row5.createCell(2)
cell1.apply {
@@ -776,7 +790,7 @@ open class ReportService(
cellStyle.dataFormat = accountingStyle
}

rowNum = 6
rowNum = 6+1
val row6: Row = sheet.getRow(rowNum)
val cell2 = row6.createCell(2)
cell2.apply {
@@ -784,7 +798,7 @@ open class ReportService(
cellStyle.dataFormat = accountingStyle
}

rowNum = 7
rowNum = 7+1
val row7: Row = sheet.getRow(rowNum)
val cell3 = row7.createCell(2)
cell3.apply {
@@ -792,7 +806,7 @@ open class ReportService(
cellStyle.dataFormat = accountingStyle
}

rowNum = 8
rowNum = 8+1
val row8: Row = sheet.getRow(rowNum)
val cell4 = row8.createCell(2)
cell4.apply {
@@ -800,7 +814,7 @@ open class ReportService(
cellStyle.dataFormat = accountingStyle
}

rowNum = 9
rowNum = 9+1
val row9: Row = sheet.getRow(rowNum)
val cell5 = row9.createCell(2)
cell5.apply {
@@ -808,7 +822,7 @@ open class ReportService(
cellStyle.dataFormat = accountingStyle
}

rowNum = 10
rowNum = 10+1
val row10: Row = sheet.getRow(rowNum)
val cell6 = row10.createCell(2)
cell6.apply {
@@ -816,7 +830,7 @@ open class ReportService(
cellStyle.dataFormat = accountingStyle
}

rowNum = 11
rowNum = 11+1
val row11: Row = sheet.getRow(rowNum)
val cell7 = row11.createCell(2)
cell7.apply {
@@ -2179,7 +2193,16 @@ open class ReportService(
}
}

open fun getFinancialStatus(teamLeadId: Long?): List<Map<String, Any>> {
open fun getFinancialStatus(teamLeadId: Long?, startMonth: String, endMonth: String): List<Map<String, Any>> {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val startYearMonth = YearMonth.parse(startMonth)
val startDate = startYearMonth.atDay(1)
val startDateString = startDate.format(formatter)

val endYearMonth = YearMonth.parse(endMonth)
val endDate = endYearMonth.atEndOfMonth()
val endDateString = endDate.format(formatter)

val sql = StringBuilder(
// " with cte_timesheet as ("
// + " Select p.code, s.name as staff, IFNULL(t.normalConsumed, 0) as normalConsumed, IFNULL(t.otConsumed , 0) as otConsumed, s2.hourlyRate"
@@ -2191,21 +2214,46 @@ open class ReportService(
// + " left join team t2 on t2.id = s.teamId"
// + " ),"
" With cte_invoice as ("
+ " select p.code, sum(i.issueAmount) as sumIssuedAmount , sum(i.paidAmount) as sumPaidAmount"
+ " select p.code, sum(i.issueAmount) as sumIssuedAmount "
+ " from invoice i"
+ " left join project p on p.code = i.projectCode"
+ " where i.deleted = false "
+ " and p.deleted = false "
+ " and i.invoiceDate >= :startMonth and i.invoiceDate <= :endMonth "
+ " group by p.code"
+ " ),"
+ " cte_rinvoice as ("
+ " select p.code, sum(i.paidAmount) as sumPaidAmount"
+ " from invoice i"
+ " left join project p on p.code = i.projectCode"
+ " where i.deleted = false "
+ " and p.deleted = false "
+ " and i.receiptDate >= :startMonth and i.receiptDate <= :endMonth "
+ " group by p.code"
+ " ),"
+ " cte_expense as ( "
+ " select IFNULL(sum(pe.amount),0) as amount, pe.projectId "
+ " from project_expense pe "
+ " where pe.deleted = false "
+ " and pe.issueDate >= :startMonth and pe.issueDate <= :endMonth "
+ " group by projectId "
+ " ), "
+ " cte_fee as ( "
+ " select IFNULL(sum(mp.amount),0) as expectedTotalFee, p.id as projectId "
+ " from milestone_payment mp "
+ " left join milestone m on mp.milestoneId = m.id "
+ " left join project p on p.id = m.projectId "
+ " where p.status = 'On-going' "
+ " and p.deleted = false "
+ " and coalesce(p.actualStart, p.planStart) <= :endMonth "
+ " and mp.`date` >= :startMonth and mp.`date` <= :endMonth "
+ " and p.teamLead = :teamLeadId"
+ " 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, p.planStart , p.planEnd , p.expectedTotalFee, ifnull(p.subContractFee, 0) as subContractFee, "
+ " IFNULL(cte_i.sumIssuedAmount, 0) as sumIssuedAmount, IFNULL(cte_i.sumPaidAmount, 0) as sumPaidAmount"
+ " 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, "
+ " 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"
+ " ,0 as totalCumulativeExpenditure, IFNULL(cte_e.amount,0) as projectExpense "
+ " from project p"
// + " left join cte_timesheet cte_ts on p.code = cte_ts.code"
@@ -2214,15 +2262,18 @@ open class ReportService(
+ " left join subsidiary s2 on s2.id = cs.subsidiaryId "
+ " 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_rinvoice cte_ri on cte_ri.code = p.code"
+ " left join cte_expense cte_e on cte_e.projectId = p.id "
+ " left join cte_fee cte_f on cte_f.projectId = p.id "
+ " where p.status = \'On-going\'"
+ " and p.deleted = false "
+ " and coalesce(p.actualStart, p.planStart) <= :endMonth"
)
if (teamLeadId!! > 0) {
sql.append(" and p.teamLead = :teamLeadId ")
}
sql.append(" order by p.code")
val args = mapOf("teamLeadId" to teamLeadId)
val args = mapOf("teamLeadId" to teamLeadId, "startMonth" to startDateString, "endMonth" to endDateString )

return jdbcDao.queryForList(sql.toString(), args)
}
@@ -3437,7 +3488,9 @@ open class ReportService(
"clientId" to clientId,
"teamLeadId" to teamId
)
val manhoursSpent = getManHoursSpentByTeam(teamId)
val formatter = DateTimeFormatter.ofPattern("yyyy-MM")

val manhoursSpent = getManHoursSpentByTeam(teamId, "1970-01", LocalDate.now().format(formatter))
val salaryEffectiveMap = getSalaryEffectiveByTeamLead(teamId)
val updatedTimesheetData = updateTimesheetDataWithEffectiveSalary(manhoursSpent, salaryEffectiveMap)
val projectsExpenditure = calculateProjectExpenditures(updatedTimesheetData)
@@ -5223,7 +5276,16 @@ open class ReportService(
}

// Get all the timesheet data by Team Lead
fun getManHoursSpentByTeam(teamLeadId: Long?): List<TimesheetData>{
fun getManHoursSpentByTeam(teamLeadId: Long?, startMonth: String, endMonth: String): List<TimesheetData>{
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val startYearMonth = YearMonth.parse(startMonth)
val startDate = startYearMonth.atDay(1)
val startDateString = startDate.format(formatter)

val endYearMonth = YearMonth.parse(endMonth)
val endDate = endYearMonth.atEndOfMonth()
val endDateString = endDate.format(formatter)

val sql = StringBuilder(
"select coalesce(t.normalConsumed, 0) as normalConsumed, coalesce(t.otConsumed, 0) as otConsumed, t.recordDate, t.staffId, s2.hourlyRate, s2.salaryPoint, p.code, p.planStart, p.planEnd"
// For later calculating cross team charge
@@ -5236,7 +5298,8 @@ open class ReportService(
+ " left join project p on t.projectId = p.id"
+ " left join staff s on t.staffId = s.id"
+ " left join salary s2 on s.salaryId = s2.salaryPoint"
+ " where t.projectId in"
+ " where t.recordDate >= :startMonth and t.recordDate <= :endMonth "
+ " and t.projectId in"
+ " ("
+ " select p.id from project p"
+ " where p.status = 'On-going'"
@@ -5248,7 +5311,7 @@ open class ReportService(
sql.append(") order by code, recordDate, staffId; ")


val results = jdbcDao.queryForList(sql.toString(), mapOf("teamLeadId" to teamLeadId)).map {
val results = jdbcDao.queryForList(sql.toString(), mapOf("teamLeadId" to teamLeadId, "startMonth" to startDateString, "endMonth" to endDateString )).map {
result ->
TimesheetData(
result["normalConsumed"] as Double,
@@ -5312,7 +5375,8 @@ open class ReportService(

// Find the nearest effective date that is less than or equal to the record date
val nearestEffectiveSalary = effectiveSalaryList
.filter { YearMonth.from(it.effectiveDate) <= YearMonth.from(timesheetData.recordDate) }
// .filter { YearMonth.from(it.effectiveDate) <= YearMonth.from(timesheetData.recordDate) }
.filter{ it.effectiveDate <= timesheetData.recordDate }
.maxByOrNull { it.effectiveDate }

if (nearestEffectiveSalary != null) {


+ 10
- 6
src/main/java/com/ffii/tsms/modules/report/web/ReportController.kt Целия файл

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

println(request.teamLeadId)
val reportResult: ByteArray = excelReportService.genFinancialStatusReport(request.teamLeadId)
println("----- start downloading financial status report -----")
println("teamLeadId: ${request.teamLeadId}")
println("startMonth: ${request.startMonth}")
println("endMonth: ${request.endMonth}")

val reportResult: ByteArray = excelReportService.genFinancialStatusReport(request.teamLeadId, request.startMonth, request.endMonth)

return ResponseEntity.ok()
.header("filename", "Financial Status Report - " + LocalDate.now() + ".xlsx")
@@ -279,10 +283,10 @@ class ReportController(
}

// For API TESTING
@GetMapping("/financialReport/{id}")
fun getFinancialReport(@PathVariable id: Long): List<Map<String, Any>> {
return excelReportService.getFinancialStatus(id)
}
// @GetMapping("/financialReport/{id}")
// fun getFinancialReport(@PathVariable id: Long): List<Map<String, Any>> {
// return excelReportService.getFinancialStatus(id)
// }

// For API TESTING
@GetMapping("/manHoursSpent/{id}")


+ 3
- 1
src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt Целия файл

@@ -4,7 +4,9 @@ import java.time.LocalDate
import java.time.YearMonth

data class FinancialStatusReportRequest (
val teamLeadId: Long
val teamLeadId: Long,
val startMonth: String,
val endMonth: String,
)

data class PandLReportRequest (


Двоични данни
src/main/resources/templates/report/EX01_Financial Status Report.xlsx Целия файл


Зареждане…
Отказ
Запис