| @@ -0,0 +1,252 @@ | |||||
| package com.ffii.fpsms.modules.report.service | |||||
| import com.ffii.core.support.JdbcDao | |||||
| import org.springframework.stereotype.Service | |||||
| @Service | |||||
| class FGStockOutTraceabilityReportService( | |||||
| private val jdbcDao: JdbcDao, | |||||
| ) { | |||||
| fun getDistinctHandlersForFGStockOutTraceability(): List<String> { | |||||
| val sql = """ | |||||
| SELECT DISTINCT COALESCE(picker_user.name, modified_user.name, '') AS handler | |||||
| FROM stock_out_line sol | |||||
| INNER JOIN stock_out so ON sol.stockOutId = so.id AND so.deleted = 0 AND so.type = 'do' | |||||
| LEFT JOIN user picker_user ON sol.handled_by = picker_user.id AND picker_user.deleted = 0 | |||||
| LEFT JOIN user modified_user ON sol.modifiedBy = modified_user.staffNo AND modified_user.deleted = 0 AND sol.handled_by IS NULL | |||||
| WHERE sol.deleted = 0 | |||||
| ORDER BY handler | |||||
| """.trimIndent() | |||||
| return jdbcDao | |||||
| .queryForList(sql, emptyMap<String, Any>()) | |||||
| .map { row -> (row["handler"]?.toString() ?: "").trim() } | |||||
| .filter { it.isNotBlank() } | |||||
| } | |||||
| fun searchFGStockOutTraceabilityReport( | |||||
| stockCategory: String?, | |||||
| stockSubCategory: String?, | |||||
| itemCode: String?, | |||||
| year: String?, | |||||
| lastOutDateStart: String?, | |||||
| lastOutDateEnd: String?, | |||||
| handler: String?, | |||||
| ): List<Map<String, Any>> { | |||||
| val args = mutableMapOf<String, Any>() | |||||
| val stockCategorySql = buildMultiValueExactClause( | |||||
| stockCategory, | |||||
| "it.type", | |||||
| "stockCategory", | |||||
| args, | |||||
| ) | |||||
| // Keep parameter for API compatibility; currently no SQL filter is needed. | |||||
| val stockSubCategorySql = "" | |||||
| val itemCodeSql = buildMultiValueLikeClause( | |||||
| itemCode, | |||||
| "it.code", | |||||
| "itemCode", | |||||
| args, | |||||
| ) | |||||
| val yearSql = if (!year.isNullOrBlank()) { | |||||
| args["year"] = year | |||||
| "AND YEAR(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) = :year" | |||||
| } else { | |||||
| "" | |||||
| } | |||||
| val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) { | |||||
| val formattedDate = lastOutDateStart.replace("/", "-") | |||||
| args["lastOutDateStart"] = formattedDate | |||||
| "AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) >= DATE(:lastOutDateStart)" | |||||
| } else { | |||||
| "" | |||||
| } | |||||
| val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) { | |||||
| val formattedDate = lastOutDateEnd.replace("/", "-") | |||||
| args["lastOutDateEnd"] = formattedDate | |||||
| "AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) <= DATE(:lastOutDateEnd)" | |||||
| } else { | |||||
| "" | |||||
| } | |||||
| val handlerSql = buildMultiValueExactClause( | |||||
| handler, | |||||
| "COALESCE(picker_user.name, modified_user.name, '')", | |||||
| "handler", | |||||
| args, | |||||
| ) | |||||
| val sql = """ | |||||
| SELECT | |||||
| IFNULL(DATE_FORMAT( | |||||
| IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate), | |||||
| '%Y-%m-%d' | |||||
| ), '') AS deliveryDate, | |||||
| IFNULL(it.code, '') AS itemNo, | |||||
| IFNULL(it.name, '') AS itemName, | |||||
| IFNULL(uc.udfudesc, '') AS unitOfMeasure, | |||||
| IFNULL(dpor.deliveryNoteCode, '') AS dnNo, | |||||
| CAST(IFNULL(sp.id, 0) AS CHAR) AS customerId, | |||||
| IFNULL(sp.name, '') AS customerName, | |||||
| FORMAT( | |||||
| ROUND(SUM(IFNULL(sol.qty, 0)) OVER (PARTITION BY it.code), 0), 0 | |||||
| ) AS qtyNumeric, | |||||
| FORMAT(ROUND(IFNULL(sol.qty, 0), 0), 0) AS qty, | |||||
| '' AS truckNo, | |||||
| '' AS driver, | |||||
| IFNULL(do.code, '') AS deliveryOrderNo, | |||||
| IFNULL(po.code, '') AS fgPickOrderNo, | |||||
| IFNULL(po.code, '') AS stockReqNo, | |||||
| IFNULL(il.lotNo, '') AS lotNo, | |||||
| IFNULL(DATE_FORMAT(il.expiryDate, '%Y-%m-%d'), '') AS expiryDate, | |||||
| FORMAT(ROUND(IFNULL(sol.qty, 0), 0), 0) AS stockOutQty, | |||||
| COALESCE( | |||||
| picker_user.name, | |||||
| modified_user.name, | |||||
| '' | |||||
| ) AS handler, | |||||
| COALESCE( | |||||
| picker_user.name, | |||||
| modified_user.name, | |||||
| '' | |||||
| ) AS pickedBy, | |||||
| GROUP_CONCAT(DISTINCT wh.code ORDER BY wh.code SEPARATOR ', ') AS storeLocation, | |||||
| '' AS pickRemark, | |||||
| FORMAT( | |||||
| ROUND(SUM(IFNULL(sol.qty, 0)) OVER (PARTITION BY it.code), 0), 0 | |||||
| ) AS totalStockOutQty, | |||||
| 0 AS stockSubCategory | |||||
| FROM do_pick_order_line_record dpolr | |||||
| LEFT JOIN do_pick_order_record dpor | |||||
| ON dpolr.record_id = dpor.id | |||||
| AND dpor.deleted = 0 | |||||
| AND dpor.ticket_status = 'completed' | |||||
| INNER JOIN delivery_order do | |||||
| ON dpolr.do_order_id = do.id | |||||
| AND do.deleted = 0 | |||||
| LEFT JOIN shop sp | |||||
| ON do.shopId = sp.id | |||||
| AND sp.deleted = 0 | |||||
| LEFT JOIN delivery_order_line dol | |||||
| ON do.id = dol.deliveryOrderId | |||||
| AND dol.deleted = 0 | |||||
| LEFT JOIN items it | |||||
| ON dol.itemId = it.id | |||||
| AND it.deleted = 0 | |||||
| LEFT JOIN item_uom iu | |||||
| ON it.id = iu.itemId | |||||
| AND iu.stockUnit = 1 | |||||
| LEFT JOIN uom_conversion uc | |||||
| ON iu.uomId = uc.id | |||||
| LEFT JOIN pick_order_line pol | |||||
| ON dpolr.pick_order_id = pol.poId | |||||
| AND pol.itemId = it.id | |||||
| AND pol.deleted = 0 | |||||
| LEFT JOIN pick_order po | |||||
| ON pol.poId = po.id | |||||
| AND po.deleted = 0 | |||||
| LEFT JOIN stock_out_line sol | |||||
| ON pol.id = sol.pickOrderLineId | |||||
| AND sol.itemId = it.id | |||||
| AND sol.deleted = 0 | |||||
| LEFT JOIN stock_out so | |||||
| ON sol.stockOutId = so.id | |||||
| AND so.deleted = 0 | |||||
| AND so.type = 'do' | |||||
| LEFT JOIN inventory_lot_line ill | |||||
| ON sol.inventoryLotLineId = ill.id | |||||
| AND ill.deleted = 0 | |||||
| LEFT JOIN inventory_lot il | |||||
| ON ill.inventoryLotId = il.id | |||||
| AND il.deleted = 0 | |||||
| LEFT JOIN warehouse wh | |||||
| ON ill.warehouseId = wh.id | |||||
| AND wh.deleted = 0 | |||||
| LEFT JOIN user picker_user | |||||
| ON sol.handled_by = picker_user.id | |||||
| AND picker_user.deleted = 0 | |||||
| LEFT JOIN user modified_user | |||||
| ON sol.modifiedBy = modified_user.staffNo | |||||
| AND modified_user.deleted = 0 | |||||
| AND sol.handled_by IS NULL | |||||
| WHERE | |||||
| dpolr.deleted = 0 | |||||
| $stockCategorySql | |||||
| $stockSubCategorySql | |||||
| $itemCodeSql | |||||
| $yearSql | |||||
| $lastOutDateStartSql | |||||
| $lastOutDateEndSql | |||||
| $handlerSql | |||||
| GROUP BY | |||||
| sol.id, | |||||
| dpor.RequiredDeliveryDate, | |||||
| do.estimatedArrivalDate, | |||||
| it.code, | |||||
| it.name, | |||||
| uc.udfudesc, | |||||
| dpor.deliveryNoteCode, | |||||
| sp.id, | |||||
| sp.name, | |||||
| sol.qty, | |||||
| picker_user.name, | |||||
| modified_user.name, | |||||
| po.code, | |||||
| do.code, | |||||
| il.lotNo, | |||||
| il.expiryDate | |||||
| ORDER BY | |||||
| it.code, | |||||
| deliveryDate, | |||||
| il.lotNo | |||||
| """.trimIndent() | |||||
| return jdbcDao.queryForList(sql, args) | |||||
| } | |||||
| private fun buildMultiValueLikeClause( | |||||
| paramValue: String?, | |||||
| columnName: String, | |||||
| paramPrefix: String, | |||||
| args: MutableMap<String, Any>, | |||||
| ): String { | |||||
| if (paramValue.isNullOrBlank()) return "" | |||||
| val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() } | |||||
| if (values.isEmpty()) return "" | |||||
| val conditions = values.mapIndexed { index, value -> | |||||
| val paramName = "${paramPrefix}_$index" | |||||
| args[paramName] = "%$value%" | |||||
| "$columnName LIKE :$paramName" | |||||
| } | |||||
| return "AND (${conditions.joinToString(" OR ")})" | |||||
| } | |||||
| private fun buildMultiValueExactClause( | |||||
| paramValue: String?, | |||||
| columnName: String, | |||||
| paramPrefix: String, | |||||
| args: MutableMap<String, Any>, | |||||
| ): String { | |||||
| if (paramValue.isNullOrBlank()) return "" | |||||
| val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() } | |||||
| if (values.isEmpty()) return "" | |||||
| val conditions = values.mapIndexed { index, value -> | |||||
| val paramName = "${paramPrefix}_$index" | |||||
| args[paramName] = value | |||||
| "$columnName = :$paramName" | |||||
| } | |||||
| return "AND (${conditions.joinToString(" OR ")})" | |||||
| } | |||||
| } | |||||
| @@ -272,225 +272,6 @@ return result | |||||
| } | } | ||||
| fun getDistinctHandlersForFGStockOutTraceability(): List<String> { | |||||
| val sql = """ | |||||
| SELECT DISTINCT COALESCE(picker_user.name, modified_user.name, '') AS handler | |||||
| FROM stock_out_line sol | |||||
| INNER JOIN stock_out so ON sol.stockOutId = so.id AND so.deleted = 0 AND so.type = 'do' | |||||
| LEFT JOIN user picker_user ON sol.handled_by = picker_user.id AND picker_user.deleted = 0 | |||||
| LEFT JOIN user modified_user ON sol.modifiedBy = modified_user.staffNo AND modified_user.deleted = 0 AND sol.handled_by IS NULL | |||||
| WHERE sol.deleted = 0 | |||||
| ORDER BY handler | |||||
| """.trimIndent() | |||||
| return jdbcDao.queryForList(sql, emptyMap<String, Any>()).map { row -> (row["handler"]?.toString() ?: "").trim() }.filter { it.isNotBlank() } | |||||
| } | |||||
| fun searchFGStockOutTraceabilityReport( | |||||
| stockCategory: String?, | |||||
| stockSubCategory: String?, | |||||
| itemCode: String?, | |||||
| year: String?, | |||||
| lastOutDateStart: String?, | |||||
| lastOutDateEnd: String?, | |||||
| handler: String? | |||||
| ): List<Map<String, Any>> { | |||||
| val args = mutableMapOf<String, Any>() | |||||
| // Stock Category 过滤:通过 items.type | |||||
| val stockCategorySql = if (!stockCategory.isNullOrBlank()) { | |||||
| val categories = stockCategory.split(",").map { it.trim() }.filter { it.isNotBlank() } | |||||
| if (categories.isNotEmpty()) { | |||||
| val conditions = categories.mapIndexed { index, cat -> | |||||
| val paramName = "stockCategory_$index" | |||||
| args[paramName] = cat | |||||
| "it.type = :$paramName" | |||||
| } | |||||
| "AND (${conditions.joinToString(" OR ")})" | |||||
| } else { | |||||
| "" | |||||
| } | |||||
| } else { | |||||
| "" | |||||
| } | |||||
| // 移除 stockSubCategory 过滤(不需要) | |||||
| val itemCodeSql = buildMultiValueLikeClause(itemCode, "it.code", "itemCode", args) | |||||
| val yearSql = if (!year.isNullOrBlank()) { | |||||
| args["year"] = year | |||||
| "AND YEAR(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) = :year" | |||||
| } else { | |||||
| "" | |||||
| } | |||||
| val lastOutDateStartSql = if (!lastOutDateStart.isNullOrBlank()) { | |||||
| val formattedDate = lastOutDateStart.replace("/", "-") | |||||
| args["lastOutDateStart"] = formattedDate | |||||
| "AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) >= DATE(:lastOutDateStart)" | |||||
| } else "" | |||||
| val lastOutDateEndSql = if (!lastOutDateEnd.isNullOrBlank()) { | |||||
| val formattedDate = lastOutDateEnd.replace("/", "-") | |||||
| args["lastOutDateEnd"] = formattedDate | |||||
| "AND DATE(IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate)) <= DATE(:lastOutDateEnd)" | |||||
| } else "" | |||||
| val handlerSql = buildMultiValueExactClause( | |||||
| handler, | |||||
| "COALESCE(picker_user.name, modified_user.name, '')", | |||||
| "handler", | |||||
| args | |||||
| ) | |||||
| val sql = """ | |||||
| SELECT | |||||
| IFNULL(DATE_FORMAT( | |||||
| IFNULL(dpor.RequiredDeliveryDate, do.estimatedArrivalDate), | |||||
| '%Y-%m-%d' | |||||
| ), '') AS deliveryDate, | |||||
| IFNULL(it.code, '') AS itemNo, | |||||
| IFNULL(it.name, '') AS itemName, | |||||
| IFNULL(uc.udfudesc, '') AS unitOfMeasure, | |||||
| IFNULL(dpor.deliveryNoteCode, '') AS dnNo, | |||||
| CAST(IFNULL(sp.id, 0) AS CHAR) AS customerId, | |||||
| IFNULL(sp.name, '') AS customerName, | |||||
| FORMAT( | |||||
| ROUND(SUM(IFNULL(sol.qty, 0)) OVER (PARTITION BY it.code), 0), 0 | |||||
| ) AS qtyNumeric, | |||||
| FORMAT(ROUND(IFNULL(sol.qty, 0), 0), 0) AS qty, | |||||
| '' AS truckNo, | |||||
| '' AS driver, | |||||
| IFNULL(do.code, '') AS deliveryOrderNo, | |||||
| IFNULL(po.code, '') AS fgPickOrderNo, | |||||
| IFNULL(po.code, '') AS stockReqNo, | |||||
| IFNULL(il.lotNo, '') AS lotNo, | |||||
| IFNULL(DATE_FORMAT(il.expiryDate, '%Y-%m-%d'), '') AS expiryDate, | |||||
| FORMAT(ROUND(IFNULL(sol.qty, 0), 0), 0) AS stockOutQty, | |||||
| COALESCE( | |||||
| picker_user.name, | |||||
| modified_user.name, | |||||
| '' | |||||
| ) AS handler, | |||||
| COALESCE( | |||||
| picker_user.name, | |||||
| modified_user.name, | |||||
| '' | |||||
| ) AS pickedBy, | |||||
| GROUP_CONCAT(DISTINCT wh.code ORDER BY wh.code SEPARATOR ', ') AS storeLocation, | |||||
| '' AS pickRemark, | |||||
| FORMAT( | |||||
| ROUND(SUM(IFNULL(sol.qty, 0)) OVER (PARTITION BY it.code), 0), 0 | |||||
| ) AS totalStockOutQty, | |||||
| 0 AS stockSubCategory | |||||
| FROM do_pick_order_line_record dpolr | |||||
| LEFT JOIN do_pick_order_record dpor | |||||
| ON dpolr.record_id = dpor.id | |||||
| AND dpor.deleted = 0 | |||||
| AND dpor.ticket_status = 'completed' | |||||
| INNER JOIN delivery_order do | |||||
| ON dpolr.do_order_id = do.id | |||||
| AND do.deleted = 0 | |||||
| LEFT JOIN shop sp | |||||
| ON do.shopId = sp.id | |||||
| AND sp.deleted = 0 | |||||
| LEFT JOIN delivery_order_line dol | |||||
| ON do.id = dol.deliveryOrderId | |||||
| AND dol.deleted = 0 | |||||
| LEFT JOIN items it | |||||
| ON dol.itemId = it.id | |||||
| AND it.deleted = 0 | |||||
| LEFT JOIN item_uom iu | |||||
| ON it.id = iu.itemId | |||||
| AND iu.stockUnit = 1 | |||||
| LEFT JOIN uom_conversion uc | |||||
| ON iu.uomId = uc.id | |||||
| LEFT JOIN pick_order_line pol | |||||
| ON dpolr.pick_order_id = pol.poId | |||||
| AND pol.itemId = it.id | |||||
| AND pol.deleted = 0 | |||||
| LEFT JOIN pick_order po | |||||
| ON pol.poId = po.id | |||||
| AND po.deleted = 0 | |||||
| LEFT JOIN stock_out_line sol | |||||
| ON pol.id = sol.pickOrderLineId | |||||
| AND sol.itemId = it.id | |||||
| AND sol.deleted = 0 | |||||
| LEFT JOIN stock_out so | |||||
| ON sol.stockOutId = so.id | |||||
| AND so.deleted = 0 | |||||
| AND so.type = 'do' | |||||
| LEFT JOIN inventory_lot_line ill | |||||
| ON sol.inventoryLotLineId = ill.id | |||||
| AND ill.deleted = 0 | |||||
| LEFT JOIN inventory_lot il | |||||
| ON ill.inventoryLotId = il.id | |||||
| AND il.deleted = 0 | |||||
| LEFT JOIN warehouse wh | |||||
| ON ill.warehouseId = wh.id | |||||
| AND wh.deleted = 0 | |||||
| LEFT JOIN user picker_user | |||||
| ON sol.handled_by = picker_user.id | |||||
| AND picker_user.deleted = 0 | |||||
| LEFT JOIN user modified_user | |||||
| ON sol.modifiedBy = modified_user.staffNo | |||||
| AND modified_user.deleted = 0 | |||||
| AND sol.handled_by IS NULL | |||||
| WHERE | |||||
| dpolr.deleted = 0 | |||||
| $stockCategorySql | |||||
| $itemCodeSql | |||||
| $yearSql | |||||
| $lastOutDateStartSql | |||||
| $lastOutDateEndSql | |||||
| $handlerSql | |||||
| GROUP BY | |||||
| sol.id, | |||||
| dpor.RequiredDeliveryDate, | |||||
| do.estimatedArrivalDate, | |||||
| it.code, | |||||
| it.name, | |||||
| uc.udfudesc, | |||||
| dpor.deliveryNoteCode, | |||||
| sp.id, | |||||
| sp.name, | |||||
| sol.qty, | |||||
| picker_user.name, | |||||
| modified_user.name, | |||||
| po.code, | |||||
| do.code, | |||||
| il.lotNo, | |||||
| il.expiryDate | |||||
| ORDER BY | |||||
| it.code, | |||||
| deliveryDate, | |||||
| il.lotNo | |||||
| """.trimIndent() | |||||
| val result = jdbcDao.queryForList(sql, args) | |||||
| // 打印查询结果 | |||||
| println("=== Query Result (Total: ${result.size} rows) ===") | |||||
| result.take(50).forEachIndexed { index, row -> | |||||
| println("Row $index:") | |||||
| println(" deliveryDate: ${row["deliveryDate"]}") | |||||
| println(" itemNo: ${row["itemNo"]}") | |||||
| println(" itemName: ${row["itemName"]}") | |||||
| println(" qty: ${row["qty"]}") | |||||
| println(" qtyNumeric: ${row["qtyNumeric"]}") | |||||
| println(" deliveryOrderNo: ${row["deliveryOrderNo"]}") | |||||
| println(" dnNo: ${row["dnNo"]}") | |||||
| println(" fgPickOrderNo: ${row["fgPickOrderNo"]}") | |||||
| println(" pickedBy: ${row["pickedBy"]}") | |||||
| println(" storeLocation: ${row["storeLocation"]}") | |||||
| println(" ---") | |||||
| } | |||||
| if (result.size > 50) { | |||||
| println("... (showing first 50 rows, total ${result.size} rows)") | |||||
| } | |||||
| return result | |||||
| } | |||||
| /** | /** | ||||
| * Helper function to build SQL clause for comma-separated values. | * Helper function to build SQL clause for comma-separated values. | ||||
| * Supports multiple values like "val1, val2, val3" and generates OR conditions with LIKE. | * Supports multiple values like "val1, val2, val3" and generates OR conditions with LIKE. | ||||
| @@ -0,0 +1,74 @@ | |||||
| package com.ffii.fpsms.modules.report.web | |||||
| import com.ffii.fpsms.modules.report.service.FGStockOutTraceabilityReportService | |||||
| import com.ffii.fpsms.modules.report.service.ReportService | |||||
| import org.springframework.http.HttpHeaders | |||||
| import org.springframework.http.HttpStatus | |||||
| import org.springframework.http.MediaType | |||||
| import org.springframework.http.ResponseEntity | |||||
| import org.springframework.web.bind.annotation.GetMapping | |||||
| import org.springframework.web.bind.annotation.RequestMapping | |||||
| import org.springframework.web.bind.annotation.RequestParam | |||||
| import org.springframework.web.bind.annotation.RestController | |||||
| import java.time.LocalDate | |||||
| import java.time.LocalTime | |||||
| import java.time.format.DateTimeFormatter | |||||
| @RestController | |||||
| @RequestMapping("/report") | |||||
| class FGStockOutTraceabilityReportController( | |||||
| private val reportService: ReportService, | |||||
| private val fgStockOutTraceabilityReportService: FGStockOutTraceabilityReportService, | |||||
| ) { | |||||
| @GetMapping("/fg-stock-out-traceability-handlers") | |||||
| fun getFGStockOutTraceabilityHandlers(): List<String> = | |||||
| fgStockOutTraceabilityReportService.getDistinctHandlersForFGStockOutTraceability() | |||||
| @GetMapping("/print-fg-stock-out-traceability") | |||||
| fun generateFGStockOutTraceabilityReport( | |||||
| @RequestParam(required = false) stockCategory: String?, | |||||
| @RequestParam(required = false) stockSubCategory: String?, | |||||
| @RequestParam(required = false) itemCode: String?, | |||||
| @RequestParam(required = false) year: String?, | |||||
| @RequestParam(required = false) lastOutDateStart: String?, | |||||
| @RequestParam(required = false) lastOutDateEnd: String?, | |||||
| @RequestParam(required = false) handler: String?, | |||||
| ): ResponseEntity<ByteArray> { | |||||
| val parameters = mutableMapOf<String, Any>() | |||||
| parameters["stockCategory"] = stockCategory ?: "All" | |||||
| parameters["stockSubCategory"] = stockSubCategory ?: "All" | |||||
| parameters["itemNo"] = itemCode ?: "All" | |||||
| parameters["year"] = year ?: LocalDate.now().year.toString() | |||||
| parameters["reportDate"] = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) | |||||
| parameters["reportTime"] = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")) | |||||
| parameters["lastOutDateStart"] = lastOutDateStart ?: "" | |||||
| parameters["lastOutDateEnd"] = lastOutDateEnd ?: "" | |||||
| parameters["deliveryPeriodStart"] = "" | |||||
| parameters["deliveryPeriodEnd"] = "" | |||||
| val dbData = fgStockOutTraceabilityReportService.searchFGStockOutTraceabilityReport( | |||||
| stockCategory, | |||||
| stockSubCategory, | |||||
| itemCode, | |||||
| year, | |||||
| lastOutDateStart, | |||||
| lastOutDateEnd, | |||||
| handler, | |||||
| ) | |||||
| val pdfBytes = reportService.createPdfResponse( | |||||
| "/jasper/FGStockOutTraceabilityReport.jrxml", | |||||
| parameters, | |||||
| dbData, | |||||
| ) | |||||
| val headers = HttpHeaders().apply { | |||||
| contentType = MediaType.APPLICATION_PDF | |||||
| setContentDispositionFormData("attachment", "FGStockOutTraceabilityReport.pdf") | |||||
| set("filename", "FGStockOutTraceabilityReport.pdf") | |||||
| } | |||||
| return ResponseEntity(pdfBytes, headers, HttpStatus.OK) | |||||
| } | |||||
| } | |||||
| @@ -165,58 +165,6 @@ class ReportController( | |||||
| return ResponseEntity(pdfBytes, headers, HttpStatus.OK) | return ResponseEntity(pdfBytes, headers, HttpStatus.OK) | ||||
| } | } | ||||
| @GetMapping("/fg-stock-out-traceability-handlers") | |||||
| fun getFGStockOutTraceabilityHandlers(): List<String> = | |||||
| reportService.getDistinctHandlersForFGStockOutTraceability() | |||||
| @GetMapping("/print-fg-stock-out-traceability") | |||||
| fun generateFGStockOutTraceabilityReport( | |||||
| @RequestParam(required = false) stockCategory: String?, | |||||
| @RequestParam(required = false) stockSubCategory: String?, | |||||
| @RequestParam(required = false) itemCode: String?, | |||||
| @RequestParam(required = false) year: String?, | |||||
| @RequestParam(required = false) lastOutDateStart: String?, | |||||
| @RequestParam(required = false) lastOutDateEnd: String?, | |||||
| @RequestParam(required = false) handler: String? | |||||
| ): ResponseEntity<ByteArray> { | |||||
| val parameters = mutableMapOf<String, Any>() | |||||
| // Set report header parameters | |||||
| parameters["stockCategory"] = stockCategory ?: "All" | |||||
| parameters["stockSubCategory"] = stockSubCategory ?: "All" | |||||
| parameters["itemNo"] = itemCode ?: "All" | |||||
| parameters["year"] = year ?: LocalDate.now().year.toString() | |||||
| parameters["reportDate"] = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) | |||||
| parameters["reportTime"] = LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")) | |||||
| parameters["lastOutDateStart"] = lastOutDateStart ?: "" | |||||
| parameters["lastOutDateEnd"] = lastOutDateEnd ?: "" | |||||
| parameters["deliveryPeriodStart"] = "" | |||||
| parameters["deliveryPeriodEnd"] = "" | |||||
| val dbData = reportService.searchFGStockOutTraceabilityReport( | |||||
| stockCategory, | |||||
| stockSubCategory, | |||||
| itemCode, | |||||
| year, | |||||
| lastOutDateStart, | |||||
| lastOutDateEnd, | |||||
| handler | |||||
| ) | |||||
| val pdfBytes = reportService.createPdfResponse( | |||||
| "/jasper/FGStockOutTraceabilityReport.jrxml", | |||||
| parameters, | |||||
| dbData | |||||
| ) | |||||
| val headers = HttpHeaders().apply { | |||||
| contentType = MediaType.APPLICATION_PDF | |||||
| setContentDispositionFormData("attachment", "FGStockOutTraceabilityReport.pdf") | |||||
| set("filename", "FGStockOutTraceabilityReport.pdf") | |||||
| } | |||||
| return ResponseEntity(pdfBytes, headers, HttpStatus.OK) | |||||
| } | |||||
| @GetMapping("/print-stock-balance") | @GetMapping("/print-stock-balance") | ||||
| fun generateStockBalanceReport( | fun generateStockBalanceReport( | ||||
| @RequestParam(required = false) stockCategory: String?, | @RequestParam(required = false) stockCategory: String?, | ||||