1. CashReport - filter deleted Invoice 2. Invoice - add delete and filter deleted Invoicetags/Baseline_30082024_BACKEND_UAT
| @@ -16,5 +16,5 @@ interface InvoiceRepository : AbstractRepository<Invoice, Long> { | |||
| fun findByInvoiceNo(invoiceNo: String): Invoice | |||
| fun findAllByProjectCodeAndPaidAmountIsNotNull(projectCode: String): List<Invoice> | |||
| fun findAllByProjectCodeAndPaidAmountIsNotNullAndDeletedFalse(projectCode: String): List<Invoice> | |||
| } | |||
| @@ -334,14 +334,15 @@ open class InvoiceService( | |||
| open fun allInvoiceV3(): List<Map<String, Any>>{ | |||
| val sql = StringBuilder( | |||
| "select i.id, i.invoiceNo, i.projectCode, " + | |||
| "p.name as projectName, t.code as team, i.invoiceDate, " + | |||
| " select i.id, i.invoiceNo, i.projectCode, " + | |||
| " p.name as projectName, t.code as team, i.invoiceDate, " + | |||
| " concat(t.code, ' - ', t.name) as teamCodeName, " + | |||
| "i.receiptDate, i.issueAmount , i.paidAmount " + | |||
| "from invoice i " + | |||
| "left join project p on i.projectCode = p.code " + | |||
| "left join team t on t.id = p.teamLead " + | |||
| "order by i.invoiceDate " | |||
| " i.receiptDate, i.issueAmount , i.paidAmount " + | |||
| " from invoice i " + | |||
| " left join project p on i.projectCode = p.code " + | |||
| " left join team t on t.id = p.teamLead " + | |||
| " where i.deleted = false " + | |||
| " order by i.invoiceDate " | |||
| ) | |||
| return jdbcDao.queryForList(sql.toString()); | |||
| } | |||
| @@ -721,4 +722,10 @@ open class InvoiceService( | |||
| } | |||
| } | |||
| open fun markDeleted(id: Long) { | |||
| invoiceRepository.save(invoiceRepository.findById(id).orElseThrow().apply { | |||
| deleted = true | |||
| }) | |||
| } | |||
| } | |||
| @@ -15,14 +15,9 @@ import net.sf.jasperreports.engine.JasperExportManager | |||
| import net.sf.jasperreports.engine.JasperPrint | |||
| import org.apache.poi.ss.usermodel.Workbook | |||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook | |||
| import org.springframework.http.HttpStatus | |||
| import org.springframework.http.ResponseEntity | |||
| import org.springframework.web.bind.annotation.GetMapping | |||
| import org.springframework.web.bind.annotation.PathVariable | |||
| import org.springframework.web.bind.annotation.PostMapping | |||
| import org.springframework.web.bind.annotation.RequestBody | |||
| import org.springframework.web.bind.annotation.RequestMapping | |||
| import org.springframework.web.bind.annotation.RequestParam | |||
| import org.springframework.web.bind.annotation.RestController | |||
| import org.springframework.web.bind.annotation.* | |||
| import org.springframework.web.multipart.MultipartHttpServletRequest | |||
| import java.io.OutputStream | |||
| @@ -145,4 +140,10 @@ class InvoiceController( | |||
| fun updateInvoiceDetail(@RequestBody req: EditInvoiceRequest): EditInvoiceResponse { | |||
| return invoiceService.updateInvoiceDetail(req) | |||
| } | |||
| @DeleteMapping("/{id}") | |||
| @ResponseStatus(HttpStatus.NO_CONTENT) | |||
| fun deleteProject(@PathVariable id: Long) { | |||
| invoiceService.markDeleted(id) | |||
| } | |||
| } | |||
| @@ -3903,6 +3903,7 @@ open class ReportService( | |||
| return workbook | |||
| } | |||
| // Use to Calculate cummunlative expenditure | |||
| // TO DO: Add isCrossTeam | |||
| data class TimesheetData( | |||
| val normalConsumed: Double, | |||
| val otConsumed: Double, | |||
| @@ -3913,6 +3914,7 @@ open class ReportService( | |||
| val projectCode: String, | |||
| val planStart: LocalDate, | |||
| val planEnd: LocalDate | |||
| // val isCrossTeam: Boolean | |||
| ) | |||
| data class SalaryEffectiveInfo( | |||
| @@ -3947,6 +3949,12 @@ open class ReportService( | |||
| fun getManHoursSpentByTeam(teamLeadId: Long?): List<TimesheetData>{ | |||
| 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 | |||
| // + ",CASE" | |||
| // + " when s.teamId is NUll then null" | |||
| // + " when s.teamId = p.teamLead then 1" | |||
| // + " else 0" | |||
| // + " END as IsCrossTeam" | |||
| + " from timesheet t" | |||
| + " left join project p on t.projectId = p.id" | |||
| + " left join staff s on t.staffId = s.id" | |||
| @@ -4070,6 +4078,9 @@ open class ReportService( | |||
| // } | |||
| fun calculateProjectExpenditures(timesheetDataList: List<TimesheetData>): Map<String, BigDecimal> { | |||
| val otFactor = BigDecimal(1.0) | |||
| // For cross Team Calculation | |||
| // val crossTeamCharge = BigDecimal(1.15) | |||
| // If isCrossTeam is true, normal an ot expenditure will times the cross team charge | |||
| return timesheetDataList | |||
| .groupBy { it.projectCode } | |||
| .mapValues { (_, projectTimesheets) -> | |||
| @@ -4084,6 +4095,7 @@ open class ReportService( | |||
| // Update timesheet data with salary effective data, then group by project code, group by staff Id and group by Year Month | |||
| // Used for checking data | |||
| // Data foramt: | |||
| // "M-0976": { | |||
| // "184": { | |||
| @@ -4108,13 +4120,16 @@ open class ReportService( | |||
| fun sumTimesheetDataByMonth(timesheetDataList: List<TimesheetData>): Map<String, ProjectSummary> { | |||
| return timesheetDataList | |||
| .groupBy { it.projectCode } | |||
| .groupBy { it.projectCode } // Group timesheet data by project code | |||
| .mapValues { (_, projectTimesheets) -> | |||
| val staffData = projectTimesheets.groupBy { it.staffId } | |||
| // Process each project's timesheet data | |||
| val staffData = projectTimesheets.groupBy { it.staffId } // Group by staff ID | |||
| .mapValues { (_, staffTimesheets) -> | |||
| // Process each staff member's timesheet data | |||
| val monthlyData = staffTimesheets.groupBy { timesheet -> | |||
| YearMonth.from(timesheet.recordDate) | |||
| YearMonth.from(timesheet.recordDate) // Group by month | |||
| }.mapValues { (_, monthTimesheets) -> | |||
| // Calculate monthly summary for each staff member | |||
| MonthSummary( | |||
| hourlyRate = monthTimesheets.maxByOrNull { it.recordDate }?.hourlyRate ?: BigDecimal.ZERO, | |||
| salaryPoint = monthTimesheets.maxByOrNull { it.recordDate }?.salaryPoint ?: 0, | |||
| @@ -86,7 +86,7 @@ class ReportController( | |||
| val project = projectRepository.findById(request.projectId).orElseThrow() | |||
| val projectTasks = projectTaskRepository.findAllByProject(project) | |||
| // val invoices = invoiceService.findAllByProjectAndPaidAmountIsNotNull(project) | |||
| val invoices = invoiceRepository.findAllByProjectCodeAndPaidAmountIsNotNull(project.code!!) | |||
| val invoices = invoiceRepository.findAllByProjectCodeAndPaidAmountIsNotNullAndDeletedFalse(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()) | |||