import and export Salary Templatetags/Baseline_30082024_BACKEND_UAT
| @@ -6,6 +6,8 @@ import jakarta.persistence.Entity; | |||||
| import jakarta.persistence.Table; | import jakarta.persistence.Table; | ||||
| import jakarta.validation.constraints.NotNull; | import jakarta.validation.constraints.NotNull; | ||||
| import java.math.BigDecimal; | |||||
| @Entity | @Entity | ||||
| @Table(name = "salary") | @Table(name = "salary") | ||||
| public class Salary extends IdEntity<Long> { | public class Salary extends IdEntity<Long> { | ||||
| @@ -25,6 +27,9 @@ public class Salary extends IdEntity<Long> { | |||||
| @Column(name = "increment") | @Column(name = "increment") | ||||
| private Integer increment; | private Integer increment; | ||||
| @Column(name = "hourlyRate") | |||||
| private BigDecimal hourlyRate; | |||||
| public Integer getIncrement() { | public Integer getIncrement() { | ||||
| return increment; | return increment; | ||||
| } | } | ||||
| @@ -56,4 +61,12 @@ public class Salary extends IdEntity<Long> { | |||||
| public Integer getSalaryPoint() { | public Integer getSalaryPoint() { | ||||
| return salaryPoint; | return salaryPoint; | ||||
| } | } | ||||
| public BigDecimal getHourlyRate() { | |||||
| return hourlyRate; | |||||
| } | |||||
| public void setHourlyRate(BigDecimal hourlyRate) { | |||||
| this.hourlyRate = hourlyRate; | |||||
| } | |||||
| } | } | ||||
| @@ -1,5 +1,7 @@ | |||||
| package com.ffii.tsms.modules.data.entity.projections; | package com.ffii.tsms.modules.data.entity.projections; | ||||
| import java.math.BigDecimal; | |||||
| /** | /** | ||||
| * Projection for {@link com.ffii.tsms.modules.data.entity.Salary} | * Projection for {@link com.ffii.tsms.modules.data.entity.Salary} | ||||
| */ | */ | ||||
| @@ -8,5 +10,5 @@ public interface SalarySearchInfo { | |||||
| Integer getSalaryPoint(); | Integer getSalaryPoint(); | ||||
| Integer getLowerLimit(); | Integer getLowerLimit(); | ||||
| Integer getUpperLimit(); | Integer getUpperLimit(); | ||||
| BigDecimal getHourlyRate(); | |||||
| } | } | ||||
| @@ -3,12 +3,15 @@ package com.ffii.tsms.modules.data.service | |||||
| import com.ffii.core.support.AbstractBaseEntityService | import com.ffii.core.support.AbstractBaseEntityService | ||||
| import com.ffii.core.support.AbstractIdEntityService | import com.ffii.core.support.AbstractIdEntityService | ||||
| import com.ffii.core.support.JdbcDao | import com.ffii.core.support.JdbcDao | ||||
| import com.ffii.tsms.modules.data.entity.Department | |||||
| import com.ffii.tsms.modules.data.entity.DepartmentRepository | |||||
| import com.ffii.core.utils.ExcelUtils | |||||
| import com.ffii.tsms.modules.data.entity.Salary | import com.ffii.tsms.modules.data.entity.Salary | ||||
| import com.ffii.tsms.modules.data.entity.SalaryRepository | import com.ffii.tsms.modules.data.entity.SalaryRepository | ||||
| import com.ffii.tsms.modules.data.entity.projections.SalarySearchInfo | import com.ffii.tsms.modules.data.entity.projections.SalarySearchInfo | ||||
| import org.apache.poi.ss.usermodel.Sheet | |||||
| import org.apache.poi.ss.usermodel.Workbook | |||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
| import org.springframework.transaction.annotation.Transactional | |||||
| import java.math.BigDecimal | |||||
| @Service | @Service | ||||
| open class SalaryService( | open class SalaryService( | ||||
| @@ -28,4 +31,45 @@ open class SalaryService( | |||||
| ) | ) | ||||
| return jdbcDao.queryForList(sql.toString(), args) | return jdbcDao.queryForList(sql.toString(), args) | ||||
| } | } | ||||
| @Transactional(rollbackFor = [Exception::class]) | |||||
| open fun importFile(workbook: Workbook?): String { | |||||
| if (workbook == null) { | |||||
| return "No Excel import" // if workbook is null | |||||
| } | |||||
| val deleteDataInSalary = StringBuilder( | |||||
| "DELETE FROM salary" | |||||
| ) | |||||
| val disableForeignKeyChecks = StringBuilder( | |||||
| "SET FOREIGN_KEY_CHECKS = 0" | |||||
| ) | |||||
| val enableForeignKeyChecks = StringBuilder( | |||||
| "SET FOREIGN_KEY_CHECKS = 1" | |||||
| ) | |||||
| jdbcDao.executeUpdate(disableForeignKeyChecks.toString()) | |||||
| jdbcDao.executeUpdate(deleteDataInSalary.toString()) | |||||
| val sheet: Sheet = workbook.getSheetAt(0) | |||||
| // val sheetValues: MutableList<Map<String, Any>> = ArrayList() | |||||
| for (i in 2..sheet.lastRowNum){ | |||||
| val salary = Salary().apply { | |||||
| salaryPoint = ExcelUtils.getIntValue(ExcelUtils.getCell(sheet, i, 0)) | |||||
| lowerLimit = ExcelUtils.getIntValue(ExcelUtils.getCell(sheet, i, 1)) | |||||
| upperLimit = ExcelUtils.getIntValue(ExcelUtils.getCell(sheet, i, 2)) | |||||
| increment = ExcelUtils.getIntValue(ExcelUtils.getCell(sheet, i, 3)) | |||||
| hourlyRate = ExcelUtils.getDecimalValue(ExcelUtils.getCell(sheet, i, 4)) | |||||
| } | |||||
| saveAndFlush(salary) | |||||
| // println("Lower Limit: " + ExcelUtils.getIntValue(ExcelUtils.getCell(sheet, i, 1))) | |||||
| } | |||||
| jdbcDao.executeUpdate(enableForeignKeyChecks.toString()) | |||||
| return "OK" | |||||
| } | |||||
| } | } | ||||
| @@ -5,17 +5,27 @@ import com.ffii.core.utils.CriteriaArgsBuilder | |||||
| import com.ffii.tsms.modules.data.entity.projections.SalarySearchInfo | import com.ffii.tsms.modules.data.entity.projections.SalarySearchInfo | ||||
| import com.ffii.tsms.modules.data.service.DepartmentService | import com.ffii.tsms.modules.data.service.DepartmentService | ||||
| import com.ffii.tsms.modules.data.service.SalaryService | import com.ffii.tsms.modules.data.service.SalaryService | ||||
| import com.ffii.tsms.modules.report.service.ReportService | |||||
| import com.ffii.tsms.modules.report.web.model.ProjectCashFlowReportRequest | |||||
| import jakarta.servlet.http.HttpServletRequest | import jakarta.servlet.http.HttpServletRequest | ||||
| import jakarta.validation.Valid | |||||
| import org.apache.poi.ss.usermodel.Workbook | |||||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook | |||||
| import org.springframework.core.io.ByteArrayResource | |||||
| import org.springframework.core.io.Resource | |||||
| import org.springframework.http.ResponseEntity | |||||
| 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.RequestMapping | |||||
| import org.springframework.web.bind.annotation.RestController | |||||
| import org.springframework.web.bind.annotation.* | |||||
| import org.springframework.web.multipart.MultipartHttpServletRequest | |||||
| import java.io.IOException | |||||
| import java.time.LocalDate | |||||
| @RestController | @RestController | ||||
| @RequestMapping("/salarys") | @RequestMapping("/salarys") | ||||
| class SalaryController( | class SalaryController( | ||||
| private val salaryService: SalaryService | |||||
| private val salaryService: SalaryService, | |||||
| private val excelReportService: ReportService | |||||
| ) { | ) { | ||||
| @GetMapping | @GetMapping | ||||
| @@ -34,4 +44,33 @@ class SalaryController( | |||||
| ) | ) | ||||
| ) | ) | ||||
| } | } | ||||
| @PostMapping("/import") | |||||
| fun importFile(request: HttpServletRequest): ResponseEntity<*> { | |||||
| var workbook: Workbook? = null | |||||
| try { | |||||
| val multipartFile = (request as MultipartHttpServletRequest).getFile("multipartFileList") | |||||
| if (multipartFile != null) { | |||||
| workbook = XSSFWorkbook(multipartFile.inputStream) | |||||
| } | |||||
| } catch (e: Exception) { | |||||
| println("Excel Wrong") | |||||
| println(e) | |||||
| } | |||||
| return ResponseEntity.ok(salaryService.importFile(workbook)) | |||||
| } | |||||
| @PostMapping("/export") | |||||
| @Throws(ServletRequestBindingException::class, IOException::class) | |||||
| fun exportSalaryList(): ResponseEntity<Resource> { | |||||
| val reportResult: ByteArray = excelReportService.exportSalaryList() | |||||
| // val mediaType: MediaType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") | |||||
| return ResponseEntity.ok() | |||||
| // .contentType(mediaType) | |||||
| .header("filename", "Salary Point List - " + LocalDate.now() + ".xlsx") | |||||
| .body(ByteArrayResource(reportResult)) | |||||
| } | |||||
| } | } | ||||
| @@ -19,6 +19,7 @@ open class ReportService { | |||||
| private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER) | private val FORMATTED_TODAY = LocalDate.now().format(DATE_FORMATTER) | ||||
| private val PROJECT_CASH_FLOW_REPORT = "templates/report/EX02_Project Cash Flow Report.xlsx" | private val PROJECT_CASH_FLOW_REPORT = "templates/report/EX02_Project Cash Flow Report.xlsx" | ||||
| private val SALART_LIST_TEMPLATE = "templates/report/Salary Template.xlsx" | |||||
| // ==============================|| GENERATE REPORT ||============================== // | // ==============================|| GENERATE REPORT ||============================== // | ||||
| @Throws(IOException::class) | @Throws(IOException::class) | ||||
| @@ -34,6 +35,19 @@ open class ReportService { | |||||
| return outputStream.toByteArray() | return outputStream.toByteArray() | ||||
| } | } | ||||
| @Throws(IOException::class) | |||||
| fun exportSalaryList(): ByteArray { | |||||
| // Generate the Excel report with query results | |||||
| val workbook: Workbook = createSalaryList(SALART_LIST_TEMPLATE) | |||||
| // Write the workbook to a ByteArrayOutputStream | |||||
| val outputStream: ByteArrayOutputStream = ByteArrayOutputStream() | |||||
| workbook.write(outputStream) | |||||
| workbook.close() | |||||
| return outputStream.toByteArray() | |||||
| } | |||||
| // ==============================|| CREATE REPORT ||============================== // | // ==============================|| CREATE REPORT ||============================== // | ||||
| @Throws(IOException::class) | @Throws(IOException::class) | ||||
| private fun createProjectCashFlowReport( | private fun createProjectCashFlowReport( | ||||
| @@ -157,4 +171,18 @@ open class ReportService { | |||||
| return workbook | return workbook | ||||
| } | } | ||||
| @Throws(IOException::class) | |||||
| private fun createSalaryList( | |||||
| templatePath: String, | |||||
| ): Workbook { | |||||
| val resource = ClassPathResource(templatePath) | |||||
| val templateInputStream = resource.inputStream | |||||
| val workbook: Workbook = XSSFWorkbook(templateInputStream) | |||||
| val sheet: Sheet = workbook.getSheetAt(0) | |||||
| return workbook | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,4 @@ | |||||
| -- liquibase formatted sql | |||||
| -- changeset jasonT:hourlyRate | |||||
| ALTER TABLE tsmsdb.salary ADD hourlyRate DECIMAL(5,2) NULL; | |||||