From 652612e10cb57048b3d5be681c8704a6613c61fd Mon Sep 17 00:00:00 2001 From: leoho2fi Date: Mon, 20 May 2024 14:54:54 +0800 Subject: [PATCH] report update --- .../data/entity/CustomerRepository.java | 4 +- .../project/entity/ProjectRepository.kt | 5 ++ .../modules/report/service/ReportService.kt | 41 ++++++----- .../modules/report/web/ReportController.kt | 70 ++++++++++++++++--- .../modules/report/web/model/ReportRequest.kt | 10 +++ 5 files changed, 100 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/ffii/tsms/modules/data/entity/CustomerRepository.java b/src/main/java/com/ffii/tsms/modules/data/entity/CustomerRepository.java index 8580704..d075a18 100644 --- a/src/main/java/com/ffii/tsms/modules/data/entity/CustomerRepository.java +++ b/src/main/java/com/ffii/tsms/modules/data/entity/CustomerRepository.java @@ -8,7 +8,7 @@ import org.springframework.data.repository.query.Param; import com.ffii.core.support.AbstractRepository; public interface CustomerRepository extends AbstractRepository { - List findAllByDeletedFalse(); Optional findByCode(@Param("code") String code); -} \ No newline at end of file + Optional findByName(@Param("name") String name); +} diff --git a/src/main/java/com/ffii/tsms/modules/project/entity/ProjectRepository.kt b/src/main/java/com/ffii/tsms/modules/project/entity/ProjectRepository.kt index 10a950c..2e61195 100644 --- a/src/main/java/com/ffii/tsms/modules/project/entity/ProjectRepository.kt +++ b/src/main/java/com/ffii/tsms/modules/project/entity/ProjectRepository.kt @@ -5,6 +5,7 @@ import com.ffii.tsms.modules.project.entity.projections.InvoiceInfoSearchInfo import com.ffii.tsms.modules.project.entity.projections.InvoiceSearchInfo import com.ffii.tsms.modules.project.entity.projections.ProjectSearchInfo import java.io.Serializable +import java.time.LocalDate interface ProjectRepository : AbstractRepository { fun findProjectSearchInfoByOrderByCreatedDesc(): List @@ -16,4 +17,8 @@ interface ProjectRepository : AbstractRepository { fun findInvoiceInfoSearchInfoById(id: Long): List fun findFirstByIsClpProjectAndIdIsNotOrderByIdDesc(isClpProject: Boolean, id: Serializable?): Project? + + fun findAllByPlanStartLessThanEqualAndPlanEndGreaterThanEqual(remainedDateFrom: LocalDate?, remainedDateTo: LocalDate?) + + fun findByDateRange(start: LocalDate, end: LocalDate): List } \ No newline at end of file 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 1194886..2f37049 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,8 @@ package com.ffii.tsms.modules.report.service import com.ffii.core.support.JdbcDao 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.Leave @@ -156,8 +158,16 @@ open class ReportService( } @Throws(IOException::class) - fun generateLateStartReport(project: Project?): ByteArray { - val workbook: Workbook = createLateStartReport(project,LATE_START_REPORT) + fun generateLateStartReport( + team: Team, + customer: Customer, + project: List, + ): ByteArray { + val workbook: Workbook = createLateStartReport( + team, + customer, + project, + LATE_START_REPORT) val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() workbook.write(outputStream) workbook.close() @@ -953,34 +963,27 @@ open class ReportService( return workbook } - +//createLateStartReport private fun createLateStartReport( - project: Project?, + team: Team, + customer: Customer, + project: List, templatePath: String ):Workbook{ - + val resource = ClassPathResource(templatePath) val templateInputStream = resource.inputStream val workbook: Workbook = XSSFWorkbook(templateInputStream) val sheet = workbook.getSheetAt(0) - + // Formatting the current date to "YYYY/MM/DD" and setting it to cell C2 val formattedToday = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) val dateCell = sheet.getRow(1)?.getCell(2) ?: sheet.getRow(1).createCell(2) dateCell.setCellValue(formattedToday) - // // Start populating project data starting at row 7 - // val startRow = 6 // 0-based index for row 7 - // val projectDataRow = sheet.createRow(startRow) - - // // Populate the row with project data - // projectDataRow.createCell(1).setCellValue(project.code) // Column B - // projectDataRow.createCell(2).setCellValue(project.name) // Column C - // projectDataRow.createCell(3).setCellValue(project.teamLead?.name) // Column D - // projectDataRow.createCell(4).setCellValue(project.custLeadName) // Column E - // projectDataRow.createCell(5).setCellValue( - // project.planStart?.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) ?: "N/A" // Column F - // ) + // Start populating project data starting at row 7 + val startRow = 6 // 0-based index for row 7 + val projectDataRow = sheet.createRow(startRow) // Styling for cell A1: Font size 16 and bold val headerFont = workbook.createFont().apply { @@ -992,7 +995,7 @@ open class ReportService( } val headerCell = sheet.getRow(0)?.getCell(0) ?: sheet.getRow(0).createCell(0) headerCell.cellStyle = headerCellStyle - headerCell.setCellValue("Report Title") + //headerCell.setCellValue("Report Title") // Apply styles from A2 to A4 (bold) val boldFont = workbook.createFont().apply { bold = true } 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 4534b57..50fb74c 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 @@ -1,7 +1,7 @@ package com.ffii.tsms.modules.report.web import com.ffii.tsms.modules.data.entity.StaffRepository -import com.ffii.tsms.modules.data.entity.projections.FinancialStatusReportInfo +//import com.ffii.tsms.modules.data.entity.projections.FinancialStatusReportInfo import com.ffii.tsms.modules.data.entity.projections.StaffSearchInfo import com.ffii.tsms.modules.project.entity.* import com.ffii.tsms.modules.report.service.ReportService @@ -9,6 +9,8 @@ import com.ffii.tsms.modules.project.service.InvoiceService import com.ffii.tsms.modules.report.web.model.FinancialStatusReportRequest import com.ffii.tsms.modules.report.web.model.ProjectCashFlowReportRequest import com.ffii.tsms.modules.report.web.model.StaffMonthlyWorkHourAnalysisReportRequest +import com.ffii.tsms.modules.report.web.model.LateStartReportRequest +import com.ffii.tsms.modules.project.entity.ProjectRepository import com.ffii.tsms.modules.timesheet.entity.LeaveRepository import com.ffii.tsms.modules.timesheet.entity.TimesheetRepository import jakarta.validation.Valid @@ -27,6 +29,14 @@ import org.springframework.http.HttpHeaders import org.springframework.http.MediaType import java.io.IOException import java.time.LocalDate +import java.net.URLEncoder +import java.time.format.DateTimeFormatter +import org.springframework.stereotype.Controller +import com.ffii.tsms.modules.data.entity.TeamRepository +import com.ffii.tsms.modules.data.entity.CustomerRepository +import org.springframework.data.jpa.repository.JpaRepository +import com.ffii.tsms.modules.data.entity.Customer +import com.ffii.tsms.modules.project.entity.Project @RestController @RequestMapping("/reports") @@ -37,6 +47,8 @@ class ReportController( private val projectRepository: ProjectRepository, private val timesheetRepository: TimesheetRepository, private val projectTaskRepository: ProjectTaskRepository, + private val teamRepository: TeamRepository, + private val customerRepository: CustomerRepository, private val staffRepository: StaffRepository, private val leaveRepository: LeaveRepository, private val invoiceService: InvoiceService) { @@ -53,7 +65,6 @@ class ReportController( .body(ByteArrayResource(reportResult)) } - @PostMapping("/ProjectCashFlowReport") @Throws(ServletRequestBindingException::class, IOException::class) fun getProjectCashFlowReport(@RequestBody @Valid request: ProjectCashFlowReportRequest): ResponseEntity { @@ -100,18 +111,59 @@ class ReportController( } @PostMapping("/downloadLateStartReport") - fun downloadLateStartReport(): ResponseEntity { - val reportBytes = excelReportService.generateLateStartReport(null) + @Throws(ServletRequestBindingException::class, IOException::class) +// fun downloadLateStartReport(@RequestBody @Valid request: LateStartReportRequest): ResponseEntity { +// //val reportDate = projectRepository.findAllByPlanStartLessThanEqualAndPlanEndGreaterThanEqual().orElseThrow()//to do +// val team = teamRepository.findById(request.teamId).orElseThrow() +// //val customer = customerRepository.findById(request.clientId).orElseThrow() + +// val reportResult: ByteArray = excelReportService.generateLateStartReport(team,customer,reportDate) +// val headers = HttpHeaders() +// val filename = "Late_Start_Report_${LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))}.xlsx" +// headers.add("filename", "${URLEncoder.encode(filename, "UTF-8")}") +// // Logging the filename to ensure it's correctly formatted +// println("Generated filename for download: $filename") + +// return ResponseEntity.ok() +// .headers(headers) +// .contentLength(reportResult.size.toLong()) +// .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) +// .body(ByteArrayResource(reportResult)) +// } + +fun downloadLateStartReport(@RequestBody @Valid request: LateStartReportRequest): ResponseEntity { + val team = teamRepository.findById(request.teamId).orElseThrow { + Exception("Team not found with ID: ${request.teamId}") + } + + val customer = customerRepository.findByName(request.customer).orElseThrow() + // ?: throw Exception("Customer not found with name: ${request.customer}") + + val projects = projectRepository.findAllByDateRange(request.remainedDateFrom, request.remainedDateTo) + if (projects.isEmpty()) { + throw Exception("No projects found for the given date: ${request.reportDate}") + } + + val reportResult: ByteArray = try { + excelReportService.generateLateStartReport(team, customer, projects) + } catch (e: Exception) { + throw Exception("Error generating report", e) + } + val headers = HttpHeaders() - headers.add("Content-Disposition", "attachment; filename=Late_Start_Report_${LocalDate.now()}.xlsx") - + val formattedDate = request.reportDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + val filename = "Late_Start_Report_$formattedDate.xlsx" + headers.add("Content-Disposition", "attachment; filename=${URLEncoder.encode(filename, "UTF-8")}") + + println("Generated filename for download: $filename") + return ResponseEntity.ok() .headers(headers) - .contentLength(reportBytes.size.toLong()) + .contentLength(reportResult.size.toLong()) .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) - .body(ByteArrayResource(reportBytes)) + .body(ByteArrayResource(reportResult)) } - + @GetMapping("/financialReport/{id}") fun getFinancialReport(@PathVariable id: Long): List> { println(excelReportService.genFinancialStatusReport(id)) diff --git a/src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt b/src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt index 94158bc..ee971e7 100644 --- a/src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt +++ b/src/main/java/com/ffii/tsms/modules/report/web/model/ReportRequest.kt @@ -1,5 +1,6 @@ package com.ffii.tsms.modules.report.web.model +import java.time.LocalDate import java.time.YearMonth data class FinancialStatusReportRequest ( @@ -12,4 +13,13 @@ data class ProjectCashFlowReportRequest ( data class StaffMonthlyWorkHourAnalysisReportRequest ( val id: Long, val yearMonth: YearMonth +) + +data class LateStartReportRequest ( + val teamId: Long, + val clientId: Long, + val remainedDateFrom: LocalDate, + val remainedDateTo: LocalDate, + val customer: String, + val reportDate: LocalDate ) \ No newline at end of file