diff --git a/src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt b/src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt index a992be7..689909f 100644 --- a/src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt +++ b/src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt @@ -1,38 +1,21 @@ package com.ffii.fpsms.modules.bag.web -import com.ffii.core.response.RecordsRes import com.ffii.fpsms.modules.bag.service.BagService -import jakarta.validation.Valid +import com.ffii.fpsms.modules.bag.web.model.BagConsumptionResponse +import com.ffii.fpsms.modules.bag.web.model.BagInfo +import com.ffii.fpsms.modules.bag.web.model.BagLotLineResponse +import com.ffii.fpsms.modules.bag.web.model.BagSummaryResponse +import com.ffii.fpsms.modules.bag.web.model.BagUsageRecordResponse +import com.ffii.fpsms.modules.bag.web.model.CreateJoBagConsumptionRequest +import com.ffii.fpsms.modules.master.web.models.MessageResponse import org.springframework.web.bind.annotation.GetMapping -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.PutMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController -import com.ffii.fpsms.modules.jobOrder.service.JoPickOrderService -import com.ffii.fpsms.modules.productProcess.service.ProductProcessService -import com.ffii.fpsms.modules.jobOrder.web.model.* -import com.ffii.fpsms.modules.jobOrder.web.model.ExportPickRecordRequest -import com.ffii.fpsms.modules.jobOrder.web.model.PrintPickRecordRequest -import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanSubmitRequest -import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanIssueRequest -import jakarta.servlet.http.HttpServletResponse -import net.sf.jasperreports.engine.JasperExportManager -import net.sf.jasperreports.engine.JasperPrint -import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException -import org.springframework.context.NoSuchMessageException -import java.io.OutputStream -import java.io.UnsupportedEncodingException -import java.text.ParseException -import org.springframework.web.bind.annotation.* -import org.springframework.web.bind.annotation.RequestParam -import com.ffii.fpsms.modules.jobOrder.web.model.UpdateJoPickOrderHandledByRequest -import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfo -import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfoWithTypeName -import com.ffii.fpsms.modules.jobOrder.web.model.ExportFGStockInLabelRequest -import com.ffii.fpsms.modules.bag.web.model.* -import com.ffii.fpsms.modules.master.web.models.MessageResponse + @RestController @RequestMapping("/bag") class BagController( @@ -43,14 +26,17 @@ class BagController( fun getBagInfo(): List { return bagService.getAllBagInfo() } + @PostMapping("/createJoBagConsumption") fun createJoBagConsumption(@RequestBody request: CreateJoBagConsumptionRequest): MessageResponse { return bagService.createJoBagConsumption(request) } + @GetMapping("/bagUsageRecords") fun getBagUsageRecords(): List { return bagService.getAllBagUsageRecords() } + @GetMapping("/bags") fun getBags(): List = bagService.getBagSummaries() @@ -66,4 +52,4 @@ class BagController( @PutMapping("/by-item/{itemId}/soft-delete") fun softDeleteBagByItemId(@PathVariable itemId: Long): MessageResponse = bagService.softDeleteBagByItemId(itemId) -} \ No newline at end of file +} diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt index fa83bb6..5752b71 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt @@ -51,6 +51,7 @@ import com.ffii.fpsms.modules.stock.entity.enum.StockInLineStatus import com.ffii.fpsms.modules.stock.entity.StockInLineRepository import java.time.LocalDate import com.ffii.fpsms.modules.jobOrder.web.model.MaterialPickStatusItem +import com.ffii.fpsms.modules.jobOrder.web.model.PlasticBoxCartonQtyDashboardRecord @Service open class JoPickOrderService( private val joPickOrderRepository: JoPickOrderRepository, @@ -1688,6 +1689,9 @@ open fun getCompletedJobOrderPickOrders(completedDate: LocalDate?): List { + val fromDt = from.atStartOfDay() + val toExclusive = to.plusDays(1).atStartOfDay() + return pickOrderRepository + .findCompletedWithPlasticBoxCartonQtyInPlanStartRange( + PickOrderStatus.COMPLETED, + fromDt, + toExclusive, + ) + .mapNotNull { pickOrder -> + val planStart = pickOrder.jobOrder?.planStart ?: return@mapNotNull null + val statLocalDate = planStart.toLocalDate() + PlasticBoxCartonQtyDashboardRecord( + pickOrderId = pickOrder.id, + statDate = "${statLocalDate.year}-${"%02d".format(statLocalDate.monthValue)}-${"%02d".format(statLocalDate.dayOfMonth)}", + plasticBoxCartonQty2f = pickOrder.plasticBoxCartonQty2f, + plasticBoxCartonQty3f = pickOrder.plasticBoxCartonQty3f, + plasticBoxCartonQty4f = pickOrder.plasticBoxCartonQty4f, + ) + } + } + open fun getJobOrderPickOrders(date: LocalDate?, status: PickOrderStatus?): List> { println("=== getJobOrderPickOrders ===") println("date: $date, status: $status") diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt index 7addc6b..e8d5d96 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt @@ -737,6 +737,92 @@ open class JobOrderService( } //Pick Record + private fun validatePickRecordFloor(floor: String?): String { + val normalizedFloor = floor?.trim()?.uppercase() + ?: throw BadRequestException("floor is required for pick record print") + if (normalizedFloor !in setOf("2F", "3F", "4F", "ALL")) { + throw BadRequestException("floor must be one of 2F, 3F, 4F, ALL") + } + return normalizedFloor + } + + private fun validatePlasticBoxCartonQty(qty: Int?): Int { + val value = qty ?: throw BadRequestException("plasticBoxCartonQty is required") + if (value < 1) { + throw BadRequestException("plasticBoxCartonQty must be at least 1") + } + return value + } + + private data class AllFloorsPlasticBoxCartonQty( + val qty2f: Int, + val qty3f: Int, + val qty4f: Int, + val sum: Int, + ) + + private fun normalizeFloorPlasticBoxCartonQty(qty: Int?): Int { + if (qty == null) return 0 + if (qty < 0) { + throw BadRequestException("plastic box carton qty cannot be negative") + } + return qty + } + + private fun resolveAllFloorsPlasticBoxCartonQty( + qty2f: Int?, + qty3f: Int?, + qty4f: Int?, + ): AllFloorsPlasticBoxCartonQty { + val q2 = normalizeFloorPlasticBoxCartonQty(qty2f) + val q3 = normalizeFloorPlasticBoxCartonQty(qty3f) + val q4 = normalizeFloorPlasticBoxCartonQty(qty4f) + return AllFloorsPlasticBoxCartonQty(q2, q3, q4, q2 + q3 + q4) + } + + private fun updatePickOrderPlasticBoxCartonQty(pickOrderId: Long, floor: String, qty: Int) { + val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) ?: return + when (floor) { + "2F" -> pickOrder.plasticBoxCartonQty2f = qty + "3F" -> pickOrder.plasticBoxCartonQty3f = qty + "4F" -> pickOrder.plasticBoxCartonQty4f = qty + } + pickOrderRepository.save(pickOrder) + } + + private fun persistAllFloorsPlasticBoxCartonQty(pickOrderId: Long, all: AllFloorsPlasticBoxCartonQty) { + updatePickOrderPlasticBoxCartonQty(pickOrderId, "2F", all.qty2f) + updatePickOrderPlasticBoxCartonQty(pickOrderId, "3F", all.qty3f) + updatePickOrderPlasticBoxCartonQty(pickOrderId, "4F", all.qty4f) + } + + open fun getPickRecordPlasticBoxCartonQty(pickOrderId: Long): PickRecordPlasticBoxCartonQtyResponse { + val pickOrder = pickOrderRepository.findById(pickOrderId).orElseThrow { + NoSuchElementException("Pick order not found with ID: $pickOrderId") + } + return PickRecordPlasticBoxCartonQtyResponse( + plasticBoxCartonQty2f = pickOrder.plasticBoxCartonQty2f, + plasticBoxCartonQty3f = pickOrder.plasticBoxCartonQty3f, + plasticBoxCartonQty4f = pickOrder.plasticBoxCartonQty4f, + ) + } + + private fun resolvePlasticBoxCartonQtyForPickRecord(request: ExportPickRecordRequest): Int { + val floor = validatePickRecordFloor(request.floor) + return if (floor == "ALL") { + val all = resolveAllFloorsPlasticBoxCartonQty( + request.plasticBoxCartonQty2f, + request.plasticBoxCartonQty3f, + request.plasticBoxCartonQty4f, + ) + persistAllFloorsPlasticBoxCartonQty(request.pickOrderIds, all) + all.sum + } else { + request.plasticBoxCartonQty + ?: throw BadRequestException("plasticBoxCartonQty is required") + } + } + @Throws(IOException::class) @Transactional open fun exportPickRecord(request: ExportPickRecordRequest): Map { @@ -821,6 +907,8 @@ open class JobOrderService( println("unit (from BOM): $unit")*/ params["unit"] = pickRecordInfo.firstOrNull()?.get("uomConversionDesc") as? String ?: "N/A" + val plasticBoxCartonQtyForPdf = resolvePlasticBoxCartonQtyForPickRecord(request) + params["PlasticBoxCartonQty"] = plasticBoxCartonQtyForPdf.toString() val pickOrderCode = pickRecordInfo.firstOrNull()?.get("pickOrderCode") as? String ?: "unknown" return mapOf( @@ -833,13 +921,26 @@ open class JobOrderService( @Transactional open fun printPickRecord(request: PrintPickRecordRequest){ val printer = printerService.findById(request.printerId) ?: throw java.util.NoSuchElementException("No such printer") - - val pdf = exportPickRecord( + val floor = validatePickRecordFloor(request.floor) + val exportRequest = if (floor == "ALL") { ExportPickRecordRequest( pickOrderIds = request.pickOrderId, floor = request.floor, + plasticBoxCartonQty2f = request.plasticBoxCartonQty2f, + plasticBoxCartonQty3f = request.plasticBoxCartonQty3f, + plasticBoxCartonQty4f = request.plasticBoxCartonQty4f, ) - ) + } else { + val plasticBoxCartonQty = validatePlasticBoxCartonQty(request.plasticBoxCartonQty) + updatePickOrderPlasticBoxCartonQty(request.pickOrderId, floor, plasticBoxCartonQty) + ExportPickRecordRequest( + pickOrderIds = request.pickOrderId, + floor = request.floor, + plasticBoxCartonQty = plasticBoxCartonQty, + ) + } + + val pdf = exportPickRecord(exportRequest) val jasperPrint = pdf["report"] as JasperPrint diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt index c90b20e..baa3e4b 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt @@ -27,7 +27,6 @@ import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus import org.springframework.format.annotation.DateTimeFormat import com.ffii.fpsms.modules.productProcess.service.ProductProcessService import com.ffii.fpsms.modules.jobOrder.web.model.* -import com.ffii.fpsms.modules.jobOrder.web.model.ExportPickRecordRequest import com.ffii.fpsms.modules.jobOrder.web.model.PrintPickRecordRequest import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanSubmitRequest import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanIssueRequest @@ -224,16 +223,9 @@ fun recordSecondScanIssue( return joPickOrderService.getCompletedJobOrderPickOrderLotDetails(pickOrderId) } - @PostMapping("/PickRecord") - @Throws(UnsupportedEncodingException::class, NoSuchMessageException::class, ParseException::class, Exception::class) - fun printPickRecord(@Valid @RequestBody request: ExportPickRecordRequest, response: HttpServletResponse){ - response.characterEncoding = "utf-8" - response.contentType = "application/pdf" - val out: OutputStream = response.outputStream - val pdf = jobOrderService.exportPickRecord(request) - val jasperPrint = pdf["report"] as JasperPrint - response.addHeader("filename", "${pdf["filename"]}.pdf") - out.write(JasperExportManager.exportReportToPdf(jasperPrint)) + @GetMapping("/pick-record-plastic-box-carton-qty/{pickOrderId}") + fun getPickRecordPlasticBoxCartonQty(@PathVariable pickOrderId: Long): PickRecordPlasticBoxCartonQtyResponse { + return jobOrderService.getPickRecordPlasticBoxCartonQty(pickOrderId) } @GetMapping("/print-PickRecord") @@ -272,6 +264,18 @@ fun recordSecondScanIssue( ): List> { return joPickOrderService.getCompletedJobOrderPickOrders(completedDate) } + + @GetMapping("/plastic-box-carton-qty-dashboard") + fun getPlasticBoxCartonQtyDashboard( + @RequestParam(name = "from") + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) + from: LocalDate, + @RequestParam(name = "to") + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) + to: LocalDate, + ): List { + return joPickOrderService.getPlasticBoxCartonQtyDashboard(from, to) + } @GetMapping("/job-order-pick-orders") fun getJobOrderPickOrders( @RequestParam(name = "date", required = false) diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/ExportPickRecordRequest.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/ExportPickRecordRequest.kt index 738525f..c7f40aa 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/ExportPickRecordRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/ExportPickRecordRequest.kt @@ -3,4 +3,8 @@ package com.ffii.fpsms.modules.jobOrder.web.model data class ExportPickRecordRequest ( val pickOrderIds: Long, val floor: String? = null, + val plasticBoxCartonQty: Int? = null, + val plasticBoxCartonQty2f: Int? = null, + val plasticBoxCartonQty3f: Int? = null, + val plasticBoxCartonQty4f: Int? = null, ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PickRecordPlasticBoxCartonQtyResponse.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PickRecordPlasticBoxCartonQtyResponse.kt new file mode 100644 index 0000000..b42d1b0 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PickRecordPlasticBoxCartonQtyResponse.kt @@ -0,0 +1,7 @@ +package com.ffii.fpsms.modules.jobOrder.web.model + +data class PickRecordPlasticBoxCartonQtyResponse( + val plasticBoxCartonQty2f: Int?, + val plasticBoxCartonQty3f: Int?, + val plasticBoxCartonQty4f: Int?, +) diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PlasticBoxCartonQtyDashboardRecord.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PlasticBoxCartonQtyDashboardRecord.kt new file mode 100644 index 0000000..1b92f07 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PlasticBoxCartonQtyDashboardRecord.kt @@ -0,0 +1,9 @@ +package com.ffii.fpsms.modules.jobOrder.web.model + +data class PlasticBoxCartonQtyDashboardRecord( + val pickOrderId: Long?, + val statDate: String, + val plasticBoxCartonQty2f: Int? = null, + val plasticBoxCartonQty3f: Int? = null, + val plasticBoxCartonQty4f: Int? = null, +) diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PrintPickRecordRequest.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PrintPickRecordRequest.kt index 416d3f9..79a0b15 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PrintPickRecordRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/PrintPickRecordRequest.kt @@ -5,4 +5,8 @@ data class PrintPickRecordRequest( val printerId: Long, val printQty: Int?, val floor: String? = null, + val plasticBoxCartonQty: Int? = null, + val plasticBoxCartonQty2f: Int? = null, + val plasticBoxCartonQty3f: Int? = null, + val plasticBoxCartonQty4f: Int? = null, ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrder.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrder.kt index 9c140f5..c221933 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrder.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrder.kt @@ -72,4 +72,13 @@ open class PickOrder: BaseEntity() { @Column(name = "submittedLines") open var submittedLines: Int? = null + + @Column(name = "plastic_box_carton_qty_2f") + open var plasticBoxCartonQty2f: Int? = null + + @Column(name = "plastic_box_carton_qty_3f") + open var plasticBoxCartonQty3f: Int? = null + + @Column(name = "plastic_box_carton_qty_4f") + open var plasticBoxCartonQty4f: Int? = null } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderRepository.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderRepository.kt index b957faf..27b5bdb 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderRepository.kt @@ -135,6 +135,28 @@ fun findAllCompletedWithJobOrderPlanStartOnDay( @Param("planStartToExclusive") planStartToExclusive: LocalDateTime, ): List +@Query( + """ + SELECT po FROM PickOrder po + WHERE po.status = :status + AND po.deleted = false + AND po.jobOrder IS NOT NULL + AND po.jobOrder.planStart IS NOT NULL + AND po.jobOrder.planStart >= :planStartFrom + AND po.jobOrder.planStart < :planStartToExclusive + AND ( + po.plasticBoxCartonQty2f IS NOT NULL + OR po.plasticBoxCartonQty3f IS NOT NULL + OR po.plasticBoxCartonQty4f IS NOT NULL + ) + """ +) +fun findCompletedWithPlasticBoxCartonQtyInPlanStartRange( + @Param("status") status: PickOrderStatus, + @Param("planStartFrom") planStartFrom: LocalDateTime, + @Param("planStartToExclusive") planStartToExclusive: LocalDateTime, +): List + @Modifying(clearAutomatically = true, flushAutomatically = true) @Query( diff --git a/src/main/resources/PickRecord/PickRecordPDF.jrxml b/src/main/resources/PickRecord/PickRecordPDF.jrxml index cbe9ac6..eb0bf1f 100644 --- a/src/main/resources/PickRecord/PickRecordPDF.jrxml +++ b/src/main/resources/PickRecord/PickRecordPDF.jrxml @@ -8,6 +8,7 @@ + @@ -24,6 +25,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/changes/20260521_01_plastic_box_carton_qty/01_alter_pick_order_plastic_box_carton_qty.sql b/src/main/resources/db/changelog/changes/20260521_01_plastic_box_carton_qty/01_alter_pick_order_plastic_box_carton_qty.sql new file mode 100644 index 0000000..d2a735a --- /dev/null +++ b/src/main/resources/db/changelog/changes/20260521_01_plastic_box_carton_qty/01_alter_pick_order_plastic_box_carton_qty.sql @@ -0,0 +1,8 @@ +-- liquibase formatted sql +-- changeset fpsms:alter_pick_order_plastic_box_carton_qty + +ALTER TABLE `pick_order` + ADD COLUMN `plastic_box_carton_qty_2f` INT NULL DEFAULT NULL AFTER `submittedLines`, + ADD COLUMN `plastic_box_carton_qty_3f` INT NULL DEFAULT NULL AFTER `plastic_box_carton_qty_2f`, + ADD COLUMN `plastic_box_carton_qty_4f` INT NULL DEFAULT NULL AFTER `plastic_box_carton_qty_3f`, + ADD COLUMN `plastic_box_carton_qty_all` INT NULL DEFAULT NULL AFTER `plastic_box_carton_qty_4f`; diff --git a/src/main/resources/db/changelog/changes/20260521_02_drop_plastic_box_carton_qty_all/01_drop_pick_order_plastic_box_carton_qty_all.sql b/src/main/resources/db/changelog/changes/20260521_02_drop_plastic_box_carton_qty_all/01_drop_pick_order_plastic_box_carton_qty_all.sql new file mode 100644 index 0000000..f9d1216 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20260521_02_drop_plastic_box_carton_qty_all/01_drop_pick_order_plastic_box_carton_qty_all.sql @@ -0,0 +1,5 @@ +-- liquibase formatted sql +-- changeset fpsms:drop_pick_order_plastic_box_carton_qty_all + +ALTER TABLE `pick_order` + DROP COLUMN `plastic_box_carton_qty_all`;