diff --git a/src/main/java/com/ffii/fpsms/modules/report/service/ReportService.kt b/src/main/java/com/ffii/fpsms/modules/report/service/ReportService.kt index 84b6483..a579b55 100644 --- a/src/main/java/com/ffii/fpsms/modules/report/service/ReportService.kt +++ b/src/main/java/com/ffii/fpsms/modules/report/service/ReportService.kt @@ -3,8 +3,14 @@ package com.ffii.fpsms.modules.report.service import org.springframework.stereotype.Service import net.sf.jasperreports.engine.* import net.sf.jasperreports.engine.data.JRMapCollectionDataSource +import java.io.ByteArrayOutputStream import java.io.InputStream import com.ffii.core.support.JdbcDao +import org.apache.poi.ss.usermodel.Cell +import org.apache.poi.ss.usermodel.CellType +import org.apache.poi.ss.usermodel.Row +import org.apache.poi.ss.usermodel.Sheet +import org.apache.poi.xssf.usermodel.XSSFWorkbook @Service open class ReportService( @@ -926,6 +932,65 @@ fun searchMaterialStockOutTraceabilityReport( } return jdbcDao.queryForList("$finalSql ORDER BY itemNo, lotNo", args) } + /** + * Builds Stock Balance Report as Excel (.xlsx) from the same data used for the PDF report. + */ + fun createStockBalanceExcel(dataList: List>): ByteArray { + val workbook = XSSFWorkbook() + val sheet: Sheet = workbook.createSheet("Stock Balance") + val columns = listOf( + "itemNo" to "Item No", + "itemName" to "Item Name", + "unitOfMeasure" to "Unit", + "lotNo" to "Lot No", + "expiryDate" to "Expiry Date", + "openingBalance" to "Opening Balance", + "cumStockIn" to "Cum Stock In", + "cumStockOut" to "Cum Stock Out", + "currentBalance" to "Current Balance", + "storeLocation" to "Store Location", + "lastInDate" to "Last In Date", + "lastOutDate" to "Last Out Date", + "lastMovementDate" to "Last Movement Date", + "misInputAndLost" to "Mis Input And Lost", + "defectiveGoods" to "Defective Goods", + "variance" to "Variance", + "cumStockInByPurchaseOrder" to "Cum Stock In (PO)", + "cumStockInByJobOrder" to "Cum Stock In (JO)", + "cumStockInByStockTake" to "Cum Stock In (Stock Take)", + "cumStockInByAdj" to "Cum Stock In (Adj)", + "cumStockOutMissQty" to "Cum Stock Out Miss", + "cumStockOutBadQty" to "Cum Stock Out Bad", + "cumStockOutAdj" to "Cum Stock Out Adj", + "cumStockOutAdjStockTake" to "Cum Stock Out Adj Stock Take", + "cumStockOutStockTake" to "Cum Stock Out Stock Take", + "cumStockOutByDO" to "Cum Stock Out (DO)", + "cumStockOutByJO" to "Cum Stock Out (JO)", + "cumStockOutByConsumable" to "Cum Stock Out (Consumable)" + ) + val headerRow: Row = sheet.createRow(0) + columns.forEachIndexed { index, (_, label) -> + val cell: Cell = headerRow.createCell(index, CellType.STRING) + cell.setCellValue(label) + } + dataList.forEachIndexed { rowIndex, rowData -> + val row: Row = sheet.createRow(rowIndex + 1) + columns.forEachIndexed { colIndex, (key, _) -> + val cell: Cell = row.createCell(colIndex) + val value = rowData[key] + when (value) { + null -> cell.setCellValue("") + is Number -> cell.setCellValue(value.toDouble()) + else -> cell.setCellValue(value.toString()) + } + } + } + columns.indices.forEach { sheet.autoSizeColumn(it) } + val out = ByteArrayOutputStream() + workbook.use { it.write(out) } + return out.toByteArray() + } + /** * Compiles and fills a Jasper Report, returning the PDF as a ByteArray. */ diff --git a/src/main/java/com/ffii/fpsms/modules/report/web/ReportController.kt b/src/main/java/com/ffii/fpsms/modules/report/web/ReportController.kt index 87b2631..35e5872 100644 --- a/src/main/java/com/ffii/fpsms/modules/report/web/ReportController.kt +++ b/src/main/java/com/ffii/fpsms/modules/report/web/ReportController.kt @@ -268,21 +268,6 @@ class ReportController( @RequestParam(required = false) lastOutDateStart: String?, @RequestParam(required = false) lastOutDateEnd: String? ): ResponseEntity { - val parameters = mutableMapOf() - - // Set report header parameters - parameters["stockCategory"] = stockCategory ?: "All" - parameters["itemNo"] = itemCode ?: "All" - parameters["reportDate"] = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) - parameters["reportTime"] = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")) - parameters["storeLocation"] = storeLocation ?: "" - parameters["balanceFilterStart"] = balanceFilterStart ?: "" - parameters["balanceFilterEnd"] = balanceFilterEnd ?: "" - parameters["lastInDateStart"] = lastInDateStart ?: "" - parameters["lastInDateEnd"] = lastInDateEnd ?: "" - parameters["lastOutDateStart"] = lastOutDateStart ?: "" - parameters["lastOutDateEnd"] = lastOutDateEnd ?: "" - val dbData = reportService.searchStockBalanceReport( stockCategory, itemCode, @@ -294,20 +279,16 @@ class ReportController( lastOutDateStart, lastOutDateEnd ) - - val pdfBytes = reportService.createPdfResponse( - "/jasper/StockBalanceReport.jrxml", - parameters, - dbData - ) - + + val excelBytes = reportService.createStockBalanceExcel(dbData) + val headers = HttpHeaders().apply { - contentType = MediaType.APPLICATION_PDF - setContentDispositionFormData("attachment", "StockBalanceReport.pdf") - set("filename", "StockBalanceReport.pdf") + contentType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + setContentDispositionFormData("attachment", "StockBalanceReport.xlsx") + set("filename", "StockBalanceReport.xlsx") } - - return ResponseEntity(pdfBytes, headers, HttpStatus.OK) + + return ResponseEntity(excelBytes, headers, HttpStatus.OK) } } \ No newline at end of file