From 1ca5f59a403381f7f9a94714846288cdd3ec6e0d Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Mon, 3 Nov 2025 18:43:41 +0800 Subject: [PATCH] update --- .../fpsms/modules/master/entity/Warehouse.kt | 4 +- .../pickOrder/service/PickOrderService.kt | 163 ++++++++++++++++++ .../pickOrder/web/PickOrderController.kt | 2 +- .../service/ProductProcessService.kt | 50 +++++- .../web/ProductProcessController.kt | 4 + .../web/model/SaveProductProcessRequest.kt | 33 +++- 6 files changed, 251 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/Warehouse.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/Warehouse.kt index 92dc840..993a3bf 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/Warehouse.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/Warehouse.kt @@ -14,7 +14,9 @@ open class Warehouse : BaseEntity() { @NotNull @Column(name = "code", nullable = false, length = 30) open var code: String? = null - + @NotNull + @Column(name = "order", nullable = false, length = 30) + open var order: String? = null @NotNull @Column(name = "name", nullable = false, length = 30) open var name: String? = null diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt index d54b39e..8cde86c 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt @@ -4520,6 +4520,169 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map BigDecimal.ZERO + is BigDecimal -> n + else -> BigDecimal.valueOf(n.toDouble()) + } + } + open fun getLotDetailsByDoPickOrderRecordId2(doPickOrderRecordId: Long): Map { + // 1) 头信息(来自 record 表) + val dpor = doPickOrderRecordRepository.findById(doPickOrderRecordId).orElse(null) + ?: return mapOf("fgInfo" to null, "pickOrders" to emptyList()) + + val fgInfo = mapOf( + "doPickOrderId" to dpor.id, + "ticketNo" to dpor.ticketNo, + "storeId" to dpor.storeId, + "shopCode" to dpor.shopCode, + "shopName" to dpor.shopName, + "truckLanceCode" to dpor.truckLanceCode, + "departureTime" to dpor.truckDepartureTime + ) + + // 2) 取该 record 下所有 pick orders(通过行记录聚合) + val lineRecords = doPickOrderLineRecordRepository.findByDoPickOrderIdAndDeletedFalse(dpor.id!!) + val pickOrderIds = lineRecords.mapNotNull { it.pickOrderId }.distinct() + if (pickOrderIds.isEmpty()) { + return mapOf("fgInfo" to fgInfo, "pickOrders" to emptyList()) + } + val pickOrders = pickOrderRepository.findAllById(pickOrderIds) + + // 3) 逐个 pick order 组装行与批次/出库行 + val pickOrderDtos = pickOrders.map { po -> + val lines = po.pickOrderLines + + val lineDtos = lines.map { pol -> + val item = pol.item + val uom = pol.uom + + // 建议批次 + val lots = pol.suggestedPickLots.mapNotNull { spl -> + val ill = spl.suggestedLotLine ?: return@mapNotNull null + val il = ill.inventoryLot + val w = ill.warehouse + val today = LocalDate.now() + val isExpired = il?.expiryDate?.let { exp -> exp.isBefore(today) } == true + + mapOf( + "id" to ill.id, + "lotNo" to il?.lotNo, + "expiryDate" to il?.expiryDate, + "location" to w?.name, + "stockUnit" to (ill.stockUom?.uom?.udfudesc ?: uom?.udfudesc ?: "N/A"), + "availableQty" to ((ill.inQty ?: BigDecimal.ZERO) + .minus(ill.outQty ?: BigDecimal.ZERO) + .minus(ill.holdQty ?: BigDecimal.ZERO)), + "requiredQty" to spl.qty, + "actualPickQty" to null, // 稍后回填 + "inQty" to ill.inQty, + "outQty" to ill.outQty, + "holdQty" to ill.holdQty, + "lotStatus" to ill.status?.value, + "lotAvailability" to when { + isExpired -> "expired" + ill.status?.value == "unavailable" -> "status_unavailable" + ((ill.inQty ?: BigDecimal.ZERO) + .minus(ill.outQty ?: BigDecimal.ZERO) + .minus(ill.holdQty ?: BigDecimal.ZERO)) <= BigDecimal.ZERO -> "insufficient_stock" + else -> "available" + }, + "processingStatus" to "pending", + "suggestedPickLotId" to spl.id, + "stockOutLineId" to null, + "stockOutLineStatus" to null, + "stockOutLineQty" to null, + "router" to mapOf( + "id" to null, + "index" to w?.order, + "route" to w?.code, + "area" to w?.code + ) + ) + } + + // 出库行(投影):支持 inventoryLotLineId 为空 + val stockOutLines = pol.id?.let { + // 使用你已有的方法;若该方法返回投影类型(如 StockOutLineInfo),则以下基于字段名访问 + stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(it) + } ?: emptyList() + + // 如果是投影,通常字段:id, qty(Double?), status(String?), inventoryLotLineId(Long?) + // 计算每个 ILL 的已拣数量(BigDecimal) + val actualQtyByIllId: Map = stockOutLines + .mapNotNull { sol -> + val illId = sol.inventoryLotLineId ?: return@mapNotNull null + val qtyBD = numToBigDecimal(sol.qty as Number?) + illId to qtyBD + } + .groupBy({ it.first }, { it.second }) + .mapValues { (_, list) -> list.fold(BigDecimal.ZERO) { acc, v -> acc + v } } + + val lotsWithActual = lots.map { lot -> + val illId = lot["id"] as? Long + val actual = illId?.let { actualQtyByIllId[it] } + lot.toMutableMap().apply { if (actual != null) put("actualPickQty", actual) } + } + + // 构建 stockouts,若有 lotLineId 则加载 ILL 以补充 lotNo/location/availableQty + val stockouts = stockOutLines.map { sol -> + val illId = sol.inventoryLotLineId + val ill = illId?.let { inventoryLotLineRepository.findById(it).orElse(null) } + val il = ill?.inventoryLot + val w = ill?.warehouse + val available = if (ill == null) null else + (ill.inQty ?: BigDecimal.ZERO) + .minus(ill.outQty ?: BigDecimal.ZERO) + .minus(ill.holdQty ?: BigDecimal.ZERO) + + mapOf( + "id" to sol.id, + "status" to sol.status, + "qty" to numToBigDecimal(sol.qty as Number?), + "lotId" to ill?.id, + "lotNo" to (il?.lotNo ?: ""), + "location" to (w?.name ?: ""), + "availableQty" to available, + "noLot" to (ill == null) + ) + } + + mapOf( + "id" to pol.id, + "requiredQty" to pol.qty, + "status" to pol.status?.value, + "item" to mapOf( + "id" to item?.id, + "code" to item?.code, + "name" to item?.name, + "uomCode" to uom?.code, + "uomDesc" to uom?.udfudesc, + "uomShortDesc" to uom?.udfShortDesc + ), + "lots" to lotsWithActual, + "stockouts" to stockouts + ) + } + + mapOf( + "pickOrderId" to po.id, + "pickOrderCode" to po.code, + "doOrderId" to po.deliveryOrder?.id, + "deliveryOrderCode" to po.deliveryOrder?.code, + "consoCode" to po.consoCode, + "status" to po.status?.value, + "targetDate" to po.targetDate?.toLocalDate(), + "pickOrderLines" to lineDtos + ) + } + + return mapOf( + "fgInfo" to fgInfo, + "pickOrders" to pickOrderDtos + ) + } // ✅ 新增:从 do_pick_order_record 表查询(用于已完成的 pick orders) open fun getFgPickOrdersFromRecordByPickOrderId(pickOrderId: Long): List> { try { diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt index bc96934..7a96a50 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt @@ -163,7 +163,7 @@ class PickOrderController( } @GetMapping("/lot-details-by-do-pick-order-record/{doPickOrderRecordId}") fun getLotDetailsByDoPickOrderRecordId(@PathVariable doPickOrderRecordId: Long): Map { - return pickOrderService.getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId) + return pickOrderService.getLotDetailsByDoPickOrderRecordId2(doPickOrderRecordId) } @PostMapping("/groups") diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt index 12471fe..074432f 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt @@ -584,7 +584,7 @@ open class ProductProcessService( open fun UpdateProductProcessLineOperatorIdOrEquipmentId(request: UpdateProductProcessLineOperatorIdOrEquipmentIdRequest): MessageResponse { val productProcessLine = productProcessLineRepository.findById(request.productProcessLineId).orElse(null) val equipmentId = request.equipmentId - val user = userRepository.findById(request.operatorId).orElse(null) + val user = userRepository.findById(request.operatorId?:0L).orElse(null) val bomProcess= bomProcessRepository.findById(productProcessLine?.bomProcess?.id?:0L).orElse(null) val bomProcessEquipment=bomProcess?.equipment if(equipmentId != null &&( equipmentId==bomProcessEquipment?.id)) { @@ -596,7 +596,7 @@ open class ProductProcessService( else { - println("not match") + println("not match equipment id${equipmentId} and ${bomProcessEquipment?.id}") } if(user != null) { productProcessLine.operator = user @@ -613,4 +613,50 @@ open class ProductProcessService( errorPosition = null, ) } + open fun UpdateProductProcessLineHandlerId(request: UpdateProductProcessLineHandlerIdRequest): MessageResponse { + val productProcessLine = productProcessLineRepository.findById(request.productProcessLineId).orElse(null) + val handlerId = request.handlerId + val user = userRepository.findById(handlerId?:0L).orElse(null) + if(user != null) { + productProcessLine.handler = user + productProcessLineRepository.save(productProcessLine) + } + return MessageResponse( + id = null, + code = null, + name = null, + type = null, + message = null, + errorPosition = null, + ) + } + open fun getJobOrderProcessLineDetail(productProcessLineId: Long): JobOrderProcessLineDetailResponse { + val productProcessLine = productProcessLineRepository.findById(productProcessLineId).orElse(null) + return JobOrderProcessLineDetailResponse( + id = productProcessLine.id?:0, + productProcessId = productProcessLine.productProcess ?.id?:0, + bomProcessId = productProcessLine.bomProcess?.id?:0, + operatorId = productProcessLine.operator?.id?:0, + operatorName = productProcessLine.operator?.name?:"", + handlerId = productProcessLine.handler?.id?:0, + seqNo = productProcessLine.seqNo?:0, + name = productProcessLine.name?:"", + description = productProcessLine.description?:"", + equipmentType = productProcessLine.equipmentType?:"", + equipment = productProcessLine.equipment?.name?:"", + startTime = productProcessLine.startTime?:LocalDateTime.now(), + endTime = productProcessLine.endTime?:LocalDateTime.now(), + status = productProcessLine.status?:"", + outputFromProcessQty = productProcessLine.outputFromProcessQty?:0, + outputFromProcessUom = productProcessLine.outputFromProcessUom?:"", + defectQty = productProcessLine.defectQty?:0, + defectUom = productProcessLine.defectUom?:"", + scrapQty = productProcessLine.scrapQty?:0, + scrapUom = productProcessLine.scrapUom?:"", + byproductId = productProcessLine.byproduct?.id?:0, + byproductName = productProcessLine.byproduct?.name?:"", + byproductQty = productProcessLine.byproductQty?:0, + byproductUom = productProcessLine.byproductUom?:"" + ) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt index 720594f..5c8539f 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt @@ -167,4 +167,8 @@ class ProductProcessController( fun demoupdate(@RequestBody request: UpdateProductProcessLineOperatorIdOrEquipmentIdRequest): MessageResponse { return productProcessService.UpdateProductProcessLineOperatorIdOrEquipmentId(request) } + @PostMapping("/Demo/update/handler") + fun demoupdatehandler(@RequestBody request: UpdateProductProcessLineHandlerIdRequest): MessageResponse { + return productProcessService.UpdateProductProcessLineHandlerId(request) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt index 67cd4a9..e0725c0 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt @@ -11,6 +11,10 @@ data class UpdateProductProcessLineOperatorIdOrEquipmentIdRequest( val operatorId: Long?, val equipmentId: Long? ) +data class UpdateProductProcessLineHandlerIdRequest( + val productProcessLineId: Long, + val handlerId: Long? +) data class ProductionProcessIssueResponse( val id: Long, val productProcessId: Long?, @@ -89,4 +93,31 @@ data class UpdateLineOutputRequest( val byproductName: String?, val byproductQty: Int?, val byproductUom: String? -) \ No newline at end of file +) +data class JobOrderProcessLineDetailResponse( + val id: Long, + val productProcessId: Long?, + val bomProcessId: Long?, + val operatorId: Long?, + val equipmentType: String?, + val operatorName: String?, + val handlerId: Long?, + val seqNo: Long?, + val name: String?, + val description: String?, + val equipment: String?, + val startTime: LocalDateTime?, + val endTime: LocalDateTime?, + + val status: String, + val outputFromProcessQty: Int?, + val outputFromProcessUom: String?, + val defectQty: Int?, + val defectUom: String?, + val scrapQty: Int?, + val scrapUom: String?, + val byproductId: Long?, + val byproductName: String?, + val byproductQty: Int?, + val byproductUom: String? +)