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()) | |||