From f94b79be8d5b77177d02d1a51bd5e99ed0a62f0d Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Tue, 11 Nov 2025 12:35:20 +0800 Subject: [PATCH] update --- .../pickOrder/service/PickOrderService.kt | 246 ++++++++++++++++++ .../pickOrder/web/PickOrderController.kt | 4 +- .../web/models/SearchPickOrderRequest.kt | 85 ++++++ .../service/ProductProcessService.kt | 6 +- 4 files changed, 336 insertions(+), 5 deletions(-) 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 cdbecae..0a332d8 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 @@ -5019,6 +5019,252 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map + stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(lineId) + } + } else { + emptyList() + } + + // 7) 按 pickOrderLineId 分组 + val suggestionsByLineId = allSuggestions.groupBy { it.pickOrderLine?.id } + val stockOutLinesByLineId = allStockOutLines.groupBy { it.pickOrderLineId } + + // 8) 批量加载所有 inventoryLotLineIds + val allInventoryLotLineIds = allSuggestions + .mapNotNull { it.suggestedLotLine?.id } + .distinct() + + val inventoryLotLinesMap = if (allInventoryLotLineIds.isNotEmpty()) { + inventoryLotLineRepository.findAllById(allInventoryLotLineIds) + .associateBy { it.id!! } + } else { + emptyMap() + } + + // 9) 构建响应 + val pickOrderDtos = pickOrders.map { po -> + val lineDtos = po.pickOrderLines + .filter { !it.deleted } + .map { pol -> + val lineId = pol.id + val item = pol.item + val uom = pol.uom + + // 获取该 line 的 suggestions 和 stock out lines + val suggestions = lineId?.let { suggestionsByLineId[it] } ?: emptyList() + val stockOutLines = lineId?.let { stockOutLinesByLineId[it] } ?: emptyList() + + // 构建 lots(合并相同 lot 的多个 suggestions) + val lotMap = mutableMapOf() + + suggestions.forEach { spl -> + val ill = spl.suggestedLotLine + if (ill != null && ill.id != null) { + val illId = ill.id!! + val illEntity = inventoryLotLinesMap[illId] ?: ill + val il = illEntity.inventoryLot + val w = illEntity.warehouse + val isExpired = il?.expiryDate?.let { exp -> exp.isBefore(today) } == true + + val availableQty = (illEntity.inQty ?: zero) + .minus(illEntity.outQty ?: zero) + .minus(illEntity.holdQty ?: zero) + + // 查找对应的 stock out line + val stockOutLine = stockOutLines.find { sol -> + sol.inventoryLotLineId == illId + } + + // 计算 actualPickQty + val actualPickQty = stockOutLine?.qty?.let { numToBigDecimal(it as? Number) } + + if (lotMap.containsKey(illId)) { + // 合并 requiredQty + val existing = lotMap[illId]!! + val newRequiredQty = (existing.requiredQty ?: zero).plus(spl.qty ?: zero) + lotMap[illId] = existing.copy(requiredQty = newRequiredQty) + } else { + lotMap[illId] = LotDetailResponse( + id = illId, + lotNo = il?.lotNo, + expiryDate = il?.expiryDate, + location = w?.name, + stockUnit = illEntity.stockUom?.uom?.udfudesc ?: uom?.udfudesc ?: "N/A", + availableQty = availableQty, + requiredQty = spl.qty, + actualPickQty = actualPickQty, + inQty = illEntity.inQty, + outQty = illEntity.outQty, + holdQty = illEntity.holdQty, + lotStatus = illEntity.status?.value, + lotAvailability = when { + isExpired -> "expired" + stockOutLine?.status == "rejected" -> "rejected" + availableQty <= zero -> "insufficient_stock" + illEntity.status?.value == "unavailable" -> "status_unavailable" + else -> "available" + }, + processingStatus = when { + stockOutLine?.status == "completed" -> "completed" + stockOutLine?.status == "rejected" -> "rejected" + else -> "pending" + }, + suggestedPickLotId = spl.id, + stockOutLineId = stockOutLine?.id, + stockOutLineStatus = stockOutLine?.status, + stockOutLineQty = stockOutLine?.qty?.let { numToBigDecimal(it as? Number) }, + router = RouterInfoResponse( + id = null, + index = w?.order, + route = w?.code, + area = w?.code + ) + ) + } + } + } + + val lots = lotMap.values.toList() + + // 构建 stockouts(包括没有 lot 的) + val stockouts = stockOutLines.map { sol -> + val illId = sol.inventoryLotLineId + val ill = illId?.let { inventoryLotLinesMap[it] } + val il = ill?.inventoryLot + val w = ill?.warehouse + val available = if (ill == null) null else + (ill.inQty ?: zero) + .minus(ill.outQty ?: zero) + .minus(ill.holdQty ?: zero) + + StockOutDetailResponse( + id = sol.id, + status = sol.status, + qty = sol.qty?.let { numToBigDecimal(it as? Number) }, + lotId = ill?.id, + lotNo = il?.lotNo ?: "", + location = w?.name ?: "", + availableQty = available, + noLot = (ill == null) + ) + } + + PickOrderLineDetailResponse( + id = lineId, + requiredQty = pol.qty, + status = pol.status?.value, + item = ItemInfoResponse( + id = item?.id, + code = item?.code, + name = item?.name, + uomCode = uom?.code, + uomDesc = uom?.udfudesc, + uomShortDesc = uom?.udfShortDesc + ), + lots = lots, + stockouts = stockouts + ) + } + + PickOrderDetailResponse( + pickOrderId = po.id, + pickOrderCode = po.code, + doOrderId = po.deliveryOrder?.id, + deliveryOrderCode = po.deliveryOrder?.code, + consoCode = po.consoCode, + status = po.status?.value, + targetDate = po.targetDate?.toLocalDate(), + pickOrderLines = lineDtos + ) + } + + println("✅ Successfully built response with ${pickOrderDtos.size} pick orders") + + return LotDetailsByDoPickOrderRecordResponse( + fgInfo = fgInfo, + pickOrders = 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 ab0ccae..f518b0c 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 @@ -162,8 +162,8 @@ class PickOrderController( return pickOrderService.getPickOrderLineLotDetails(pickOrderLineId); } @GetMapping("/lot-details-by-do-pick-order-record/{doPickOrderRecordId}") - fun getLotDetailsByDoPickOrderRecordId(@PathVariable doPickOrderRecordId: Long): Map { - return pickOrderService.getLotDetailsByDoPickOrderRecordId2(doPickOrderRecordId) + fun getLotDetailsByDoPickOrderRecordId(@PathVariable doPickOrderRecordId: Long): LotDetailsByDoPickOrderRecordResponse { + return pickOrderService.getLotDetailsByDoPickOrderRecordId3(doPickOrderRecordId) } @PostMapping("/groups") diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/SearchPickOrderRequest.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/SearchPickOrderRequest.kt index 529c5fb..cafbd0f 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/SearchPickOrderRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/SearchPickOrderRequest.kt @@ -3,6 +3,8 @@ package com.ffii.fpsms.modules.pickOrder.web.models import org.springframework.web.bind.annotation.RequestParam import java.time.LocalDateTime import java.time.LocalTime +import java.time.LocalDate +import java.math.BigDecimal data class SearchPickOrderRequest ( val code: String?, val targetDateFrom: String?, @@ -47,4 +49,87 @@ data class CompletedDoPickOrderResponse( data class FgPickOrderSummary( val pickOrderId: Long, val deliveryOrderId: Long? +) +data class LotDetailsByDoPickOrderRecordResponse( + val fgInfo: FgInfoResponse?, + val pickOrders: List +) + +data class FgInfoResponse( + val doPickOrderId: Long?, + val ticketNo: String?, + val storeId: String?, + val shopCode: String?, + val shopName: String?, + val truckLanceCode: String?, + val departureTime: LocalTime? +) + +data class PickOrderDetailResponse( + val pickOrderId: Long?, + val pickOrderCode: String?, + val doOrderId: Long?, + val deliveryOrderCode: String?, + val consoCode: String?, + val status: String?, + val targetDate: LocalDate?, + val pickOrderLines: List +) + +data class PickOrderLineDetailResponse( + val id: Long?, + val requiredQty: BigDecimal?, + val status: String?, + val item: ItemInfoResponse, + val lots: List, + val stockouts: List +) + +data class ItemInfoResponse( + val id: Long?, + val code: String?, + val name: String?, + val uomCode: String?, + val uomDesc: String?, + val uomShortDesc: String? +) + +data class LotDetailResponse( + val id: Long?, + val lotNo: String?, + val expiryDate: LocalDate?, + val location: String?, + val stockUnit: String?, + val availableQty: BigDecimal?, + val requiredQty: BigDecimal?, + val actualPickQty: BigDecimal?, + val inQty: BigDecimal?, + val outQty: BigDecimal?, + val holdQty: BigDecimal?, + val lotStatus: String?, + val lotAvailability: String?, + val processingStatus: String?, + val suggestedPickLotId: Long?, + val stockOutLineId: Long?, + val stockOutLineStatus: String?, + val stockOutLineQty: BigDecimal?, + val router: RouterInfoResponse +) + +data class RouterInfoResponse( + val id: Long?, + val index: String?, + val route: String?, + val area: String? +) + +data class StockOutDetailResponse( + val id: Long?, + val status: String?, + val qty: BigDecimal?, + val lotId: Long?, + val lotNo: String?, + val location: String?, + val availableQty: BigDecimal?, + val noLot: Boolean ) \ No newline at end of file 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 c3aaae7..92f8580 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 @@ -476,7 +476,7 @@ open class ProductProcessService( seqNo = line.seqNo?:0, name = line.name?:"", description = line.description?:"", - equipment_name = line.equipment?.name?:"", + equipment_name = line.equipmentType?:"", status = line.status?:"", byproductId = line.byproduct?.id?:0, byproductName = line.byproduct?.name?:"", @@ -487,8 +487,8 @@ open class ProductProcessService( defectUom = line.defectUom?:"", outputFromProcessQty = line.outputFromProcessQty?:0, outputFromProcessUom = line.outputFromProcessUom?:"", - startTime = line.startTime?:LocalDateTime.now(), - endTime = line.endTime?:LocalDateTime.now() + startTime = line.startTime, + endTime = line.endTime ) } )