| @@ -36,20 +36,22 @@ open class ClaimService( | |||||
| private val fileRepository: FileRepository, | private val fileRepository: FileRepository, | ||||
| private val userRepository: UserRepository, | private val userRepository: UserRepository, | ||||
| private val staffsService: StaffsService, | private val staffsService: StaffsService, | ||||
| ) : AbstractBaseEntityService<Claim, Long, ClaimRepository>(jdbcDao, claimRepository) { | |||||
| ) : AbstractBaseEntityService<Claim, Long, ClaimRepository>(jdbcDao, claimRepository) { | |||||
| open fun allClaims(): List<Map<String, Any>> { | open fun allClaims(): List<Map<String, Any>> { | ||||
| val sql = StringBuilder("select " + | |||||
| "c.id, " + | |||||
| "c.created, " + | |||||
| "c.code, " + | |||||
| "sum(cd.amount) as amount, " + | |||||
| "c.type, " + | |||||
| "c.status, " + | |||||
| "c.remark " + | |||||
| "from claim c " + | |||||
| "left join claim_detail cd on cd.claimId = c.id " + | |||||
| "where c.deleted = false " + | |||||
| "group by c.id") | |||||
| val sql = StringBuilder( | |||||
| "select " + | |||||
| "c.id, " + | |||||
| "c.created, " + | |||||
| "c.code, " + | |||||
| "sum(cd.amount) as amount, " + | |||||
| "c.type, " + | |||||
| "c.status, " + | |||||
| "c.remark " + | |||||
| "from claim c " + | |||||
| "left join claim_detail cd on cd.claimId = c.id " + | |||||
| "where c.deleted = false " + | |||||
| "group by c.id" | |||||
| ) | |||||
| return jdbcDao.queryForList(sql.toString()) | return jdbcDao.queryForList(sql.toString()) | ||||
| } | } | ||||
| @@ -14,6 +14,7 @@ import org.apache.logging.log4j.core.config.plugins.validation.constraints.Requi | |||||
| import org.springframework.web.bind.ServletRequestBindingException | import org.springframework.web.bind.ServletRequestBindingException | ||||
| import org.springframework.web.bind.annotation.GetMapping | import org.springframework.web.bind.annotation.GetMapping | ||||
| import org.springframework.web.bind.annotation.ModelAttribute | import org.springframework.web.bind.annotation.ModelAttribute | ||||
| import org.springframework.web.bind.annotation.PathVariable | |||||
| import org.springframework.web.bind.annotation.PostMapping | import org.springframework.web.bind.annotation.PostMapping | ||||
| import org.springframework.web.bind.annotation.RequestBody | import org.springframework.web.bind.annotation.RequestBody | ||||
| import org.springframework.web.bind.annotation.RequestMapping | import org.springframework.web.bind.annotation.RequestMapping | ||||
| @@ -34,6 +35,11 @@ class ClaimController(private val claimService: ClaimService) { | |||||
| return claimService.allClaims() | return claimService.allClaims() | ||||
| } | } | ||||
| @GetMapping("/{id}") | |||||
| fun findClaim(@PathVariable id: Long?): List<Map<String, Any>> { | |||||
| return claimService.allClaims() | |||||
| } | |||||
| @PostMapping("/save") | @PostMapping("/save") | ||||
| fun saveClaim( | fun saveClaim( | ||||
| @RequestParam(required = false) id: Long?, | @RequestParam(required = false) id: Long?, | ||||
| @@ -0,0 +1,97 @@ | |||||
| package com.ffii.tsms.modules.common.service | |||||
| import com.ffii.tsms.modules.project.entity.Project | |||||
| import org.apache.poi.ss.usermodel.Cell | |||||
| import org.apache.poi.ss.usermodel.CellStyle | |||||
| import org.apache.poi.ss.usermodel.HorizontalAlignment | |||||
| import org.apache.poi.ss.usermodel.Row | |||||
| import org.apache.poi.ss.usermodel.Sheet | |||||
| import org.apache.poi.ss.usermodel.Workbook | |||||
| import org.apache.poi.ss.util.CellRangeAddress | |||||
| import org.apache.poi.ss.util.CellUtil | |||||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook | |||||
| import org.springframework.core.io.ClassPathResource | |||||
| import org.springframework.stereotype.Service | |||||
| import java.io.ByteArrayOutputStream | |||||
| import java.io.IOException | |||||
| import java.time.LocalDate | |||||
| import java.time.LocalDateTime | |||||
| import java.time.format.DateTimeFormatter | |||||
| @Service | |||||
| open class ExcelReportService { | |||||
| private val DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd") | |||||
| private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER) | |||||
| private val EX02_PROJECT_CASH_FLOW_REPORT = "templates/report/EX02_Project Cash Flow Report.xlsx" | |||||
| // ==============================|| GENERATE REPORT ||============================== // | |||||
| @Throws(IOException::class) | |||||
| fun generateEX02ProjectCashFlowReport(project: Project): ByteArray { | |||||
| // Generate the Excel report with query results | |||||
| val workbook: Workbook = createEX02ProjectCashFlowReport(project, EX02_PROJECT_CASH_FLOW_REPORT) | |||||
| // Write the workbook to a ByteArrayOutputStream | |||||
| val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() | |||||
| workbook.write(outputStream) | |||||
| workbook.close() | |||||
| return outputStream.toByteArray() | |||||
| } | |||||
| // ==============================|| CREATE REPORT ||============================== // | |||||
| @Throws(IOException::class) | |||||
| private fun createEX02ProjectCashFlowReport( | |||||
| project: Project, | |||||
| templatePath: String, | |||||
| ): Workbook { | |||||
| // please create a new function for each report template | |||||
| val resource = ClassPathResource(templatePath) | |||||
| val templateInputStream = resource.inputStream | |||||
| val workbook: Workbook = XSSFWorkbook(templateInputStream) | |||||
| val sheet: Sheet = workbook.getSheetAt(0) | |||||
| // val alignLeftStyle: CellStyle = workbook.createCellStyle().apply { | |||||
| // alignment = HorizontalAlignment.LEFT // Set the alignment to left | |||||
| // } | |||||
| // | |||||
| // val alignRightStyle: CellStyle = workbook.createCellStyle().apply { | |||||
| // alignment = HorizontalAlignment.RIGHT // Set the alignment to right | |||||
| // } | |||||
| var rowIndex = 1 // Assuming the location is in (1,2), which is the report date field | |||||
| var columnIndex = 2 | |||||
| sheet.getRow(rowIndex).getCell(columnIndex).apply { | |||||
| setCellValue(FORMATTED_TODAY) | |||||
| } | |||||
| rowIndex = 2 | |||||
| sheet.getRow(rowIndex).getCell(columnIndex).apply { | |||||
| setCellValue(project.code) | |||||
| } | |||||
| rowIndex = 3 | |||||
| sheet.getRow(rowIndex).getCell(columnIndex).apply { | |||||
| setCellValue(project.name) | |||||
| } | |||||
| rowIndex = 4 | |||||
| sheet.getRow(rowIndex).getCell(columnIndex).apply { | |||||
| setCellValue(if (project.customer?.name == null) "N/A" else project.customer?.name) | |||||
| } | |||||
| rowIndex = 5 | |||||
| sheet.getRow(rowIndex).getCell(columnIndex).apply { | |||||
| setCellValue(if (project.teamLead?.team?.name == null) "N/A" else project.teamLead?.team?.name) | |||||
| } | |||||
| rowIndex = 9 | |||||
| sheet.getRow(rowIndex).apply { | |||||
| getCell(1).setCellValue(project.expectedTotalFee!! * 0.8) | |||||
| getCell(2).setCellValue(project.expectedTotalFee!!) | |||||
| } | |||||
| return workbook | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| package com.ffii.tsms.modules.report.web | |||||
| import com.ffii.tsms.modules.common.service.ExcelReportService | |||||
| import com.ffii.tsms.modules.project.entity.ProjectRepository | |||||
| import com.ffii.tsms.modules.report.web.model.EX02ProjectCashFlowReportRequest | |||||
| import jakarta.validation.Valid | |||||
| import org.springframework.core.io.ByteArrayResource | |||||
| import org.springframework.core.io.Resource | |||||
| import org.springframework.http.MediaType | |||||
| import org.springframework.http.ResponseEntity | |||||
| import org.springframework.web.bind.ServletRequestBindingException | |||||
| 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.RestController | |||||
| import java.io.IOException | |||||
| import java.time.LocalDate | |||||
| @RestController | |||||
| @RequestMapping("/reports") | |||||
| class ReportController(private val excelReportService: ExcelReportService, private val projectRepository: ProjectRepository) { | |||||
| @PostMapping("/EX02-ProjectCashFlowReport") | |||||
| @Throws(ServletRequestBindingException::class, IOException::class) | |||||
| fun getEx02ProjectCashFlowReport(@RequestBody @Valid request: EX02ProjectCashFlowReportRequest): ResponseEntity<Resource> { | |||||
| val project = projectRepository.findById(request.projectId).orElseThrow() | |||||
| val reportResult: ByteArray = excelReportService.generateEX02ProjectCashFlowReport(project) | |||||
| return ResponseEntity.ok() | |||||
| .header("filename", "EX02 - Project Cash Flow Report" + LocalDate.now() + ".xlsx") | |||||
| .body(ByteArrayResource(reportResult)) | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,5 @@ | |||||
| package com.ffii.tsms.modules.report.web.model | |||||
| data class EX02ProjectCashFlowReportRequest ( | |||||
| val projectId: Long | |||||
| ) | |||||