From 7517d99499250f5f0b761baada3c08258b0c3d9a Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Wed, 15 Oct 2025 11:10:02 +0800 Subject: [PATCH] update --- .../deliveryOrder/entity/DoPickOrder.kt | 21 ++- .../deliveryOrder/entity/DoPickOrderRecord.kt | 24 +++- .../entity/DoPickOrderRepository.kt | 3 + .../service/DeliveryOrderService.kt | 6 + .../service/DoPickOrderService.kt | 136 +++++++++++++++++- .../web/DoPickOrderController.kt | 11 +- .../web/models/DoDetailResponse.kt | 21 +++ .../20251014_01_enson/02_altertable_enson.sql | 72 ++++++++++ 8 files changed, 283 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/db/changelog/changes/20251014_01_enson/02_altertable_enson.sql diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt index 7d6571d..d5f16f9 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt @@ -81,6 +81,17 @@ class DoPickOrder { @Column(name = "deleted") var deleted: Boolean = false + @Column(name = "pick_order_code", length = 50) + var pickOrderCode: String? = null + + @Column(name = "delivery_order_code", length = 50) + var deliveryOrderCode: String? = null + + @Column(name = "loading_sequence") + var loadingSequence: Int? = null + + @Column(name = "handler_name", length = 100) + var handlerName: String? = null // Default constructor for Hibernate constructor() @@ -96,6 +107,7 @@ class DoPickOrder { doOrderId: Long? = null, ticketReleaseTime: LocalDateTime? = null, shopId: Long? = null, + handlerName: String? = null, handledBy: Long? = null, ticketCompleteDateTime: LocalDateTime? = null, truckLanceCode: String? = null, @@ -103,7 +115,10 @@ class DoPickOrder { shopName: String? = null, requiredDeliveryDate: LocalDate? = null, createdBy: String? = null, - modifiedBy: String? = null + modifiedBy: String? = null, + pickOrderCode: String? = null, + deliveryOrderCode: String? = null, + loadingSequence: Int? = null, ) { this.storeId = storeId this.ticketNo = ticketNo @@ -113,6 +128,7 @@ class DoPickOrder { this.ticketStatus = ticketStatus this.truckId = truckId this.truckDepartureTime = truckDepartureTime + this.handlerName = handlerName this.shopId = shopId this.handledBy = handledBy this.ticketCompleteDateTime = ticketCompleteDateTime @@ -122,5 +138,8 @@ class DoPickOrder { this.requiredDeliveryDate = requiredDeliveryDate this.createdBy = createdBy this.modifiedBy = modifiedBy + this.pickOrderCode = pickOrderCode + this.deliveryOrderCode = deliveryOrderCode + this.loadingSequence = loadingSequence } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt index 78edfb4..24e6dd0 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt @@ -26,7 +26,14 @@ class DoPickOrderRecord { @Column(name = "do_order_id") var doOrderId: Long? = null - + @Column(name = "pick_order_code", length = 50) + var pickOrderCode: String? = null + + @Column(name = "delivery_order_code", length = 50) + var deliveryOrderCode: String? = null + + @Column(name = "loading_sequence") + var loadingSequence: Int? = null @Enumerated(EnumType.STRING) @Column(name = "ticket_status") var ticketStatus: DoPickOrderStatus? = null @@ -81,7 +88,8 @@ class DoPickOrderRecord { @Column(name = "deleted") var deleted: Boolean = false - + @Column(name = "handler_name", length = 100) +var handlerName: String? = null // Default constructor for Hibernate constructor() @@ -94,8 +102,9 @@ class DoPickOrderRecord { truckDepartureTime: LocalTime? = null, pickOrderId: Long? = null, doOrderId: Long? = null, - shopId: Long? = null, ticketReleaseTime: LocalDateTime? = null, + shopId: Long? = null, + handlerName: String? = null, handledBy: Long? = null, ticketCompleteDateTime: LocalDateTime? = null, truckLanceCode: String? = null, @@ -103,7 +112,10 @@ class DoPickOrderRecord { shopName: String? = null, requiredDeliveryDate: LocalDate? = null, createdBy: String? = null, - modifiedBy: String? = null + modifiedBy: String? = null, + pickOrderCode: String? = null, + deliveryOrderCode: String? = null, + loadingSequence: Int? = null, ) { this.storeId = storeId this.ticketNo = ticketNo @@ -116,11 +128,15 @@ class DoPickOrderRecord { this.shopId = shopId this.handledBy = handledBy this.ticketCompleteDateTime = ticketCompleteDateTime + this.handlerName = handlerName this.truckLanceCode = truckLanceCode this.shopCode = shopCode this.shopName = shopName this.requiredDeliveryDate = requiredDeliveryDate this.createdBy = createdBy this.modifiedBy = modifiedBy + this.pickOrderCode = pickOrderCode + this.deliveryOrderCode = deliveryOrderCode + this.loadingSequence = loadingSequence } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRepository.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRepository.kt index 357199f..9dbafe0 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRepository.kt @@ -21,4 +21,7 @@ interface DoPickOrderRepository : JpaRepository { fun findByPickOrderId(pickOrderId: Long): List fun findByTicketStatusIn(statuses: List): List + // 在 DoPickOrderRepository 中添加这个方法 +fun findByHandledByAndTicketStatusIn(handledBy: Long, status: List): List +fun findByStoreIdAndTicketStatusIn(storeId: String, status: List): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt index d1eaede..7526d9b 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt @@ -563,6 +563,9 @@ val doPickOrderRecord = DoPickOrderRecord( shopId = deliveryOrder.shop?.id, handledBy = null, doOrderId = deliveryOrder.id, + pickOrderCode = createdPickOrder.code, + deliveryOrderCode = deliveryOrder.code, + loadingSequence = deliveryOrder.deliveryOrderLines.size, // ✅ 填充新增字段 truckLanceCode = truck?.truckLanceCode, shopCode = deliveryOrder.shop?.code, @@ -585,6 +588,9 @@ val doPickOrder = DoPickOrder( truckDepartureTime = truck?.departureTime, shopId = deliveryOrder.shop?.id, handledBy = null, + pickOrderCode = createdPickOrder.code, + deliveryOrderCode = deliveryOrder.code, + loadingSequence = deliveryOrder.deliveryOrderLines.size, ticketReleaseTime = null, // ✅ 填充新增字段 truckLanceCode = truck?.truckLanceCode, diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt index a542129..0843e93 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt @@ -35,10 +35,15 @@ import java.time.LocalDateTime import com.ffii.fpsms.modules.deliveryOrder.web.models.AssignByStoreRequest import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecord import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository +import com.ffii.fpsms.modules.deliveryOrder.web.models.* // ✅ 导入 +import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository +import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus @Service class DoPickOrderService( private val doPickOrderRepository: DoPickOrderRepository, - private val doPickOrderRecordRepository: DoPickOrderRecordRepository + private val doPickOrderRecordRepository: DoPickOrderRecordRepository, + private val userRepository: UserRepository, + private val pickOrderRepository: PickOrderRepository ) { fun findReleasedDoPickOrders(): List { return doPickOrderRepository.findByTicketStatusIn( @@ -107,10 +112,13 @@ class DoPickOrderService( // ✅ Updated method to set ticketReleaseTime when assigning order to user fun updateHandledByForPickOrder(pickOrderId: Long, userId: Long): List { val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) + val user = userRepository.findById(userId).orElse(null) // ✅ 改用 orElse(null) + val handlerName = user?.name ?: "Unknown" doPickOrders.forEach { it.handledBy = userId + it.handlerName = handlerName it.ticketStatus = DoPickOrderStatus.released - it.ticketReleaseTime = LocalDateTime.now() // ✅ 设置 release time + it.ticketReleaseTime = LocalDateTime.now() } return doPickOrderRepository.saveAll(doPickOrders) } @@ -142,10 +150,13 @@ class DoPickOrderService( // ✅ Add method to update DoPickOrderRecord status fun updateRecordHandledByForPickOrder(pickOrderId: Long, userId: Long): List { val doPickOrderRecords = doPickOrderRecordRepository.findByPickOrderId(pickOrderId) + val user = userRepository.findById(userId).orElse(null) // ✅ 改用 orElse(null) + val handlerName = user?.name ?: "Unknown" doPickOrderRecords.forEach { it.handledBy = userId + it.handlerName = handlerName it.ticketStatus = DoPickOrderStatus.released - it.ticketReleaseTime = LocalDateTime.now() // ✅ 设置 release time + it.ticketReleaseTime = LocalDateTime.now() } return doPickOrderRecordRepository.saveAll(doPickOrderRecords) } @@ -171,6 +182,121 @@ class DoPickOrderService( } return doPickOrderRepository.saveAll(doPickOrders) } - + fun getSummaryByStore(storeId: String): StoreLaneSummary { + // ✅ 修改:查询所有状态的订单,不只是 pending + val allRecords = doPickOrderRepository.findByStoreIdAndTicketStatusIn( + storeId, + listOf(DoPickOrderStatus.pending, DoPickOrderStatus.released, DoPickOrderStatus.completed) + ) + + val grouped = allRecords.groupBy { it.truckDepartureTime to it.truckLanceCode } + .mapValues { (_, list) -> + LaneBtn( + truckLanceCode = list.first().truckLanceCode ?: "", + unassigned = list.count { it.handledBy == null }, // 未分配的订单数 + total = list.size // 总订单数(包括已分配和未分配) + ) + } + + val timeGroups = grouped.entries + .groupBy { it.key.first } + .mapValues { (_, entries) -> + entries.map { it.value } + .sortedByDescending { it.unassigned } + .take(3) + } + .filterValues { lanes -> lanes.any { it.unassigned > 0 } } + .toSortedMap(compareBy { it }) + .entries.take(4) + .map { (time, lanes) -> + LaneRow( + truckDepartureTime = time?.toString() ?: "", + lanes = lanes + ) + } + + return StoreLaneSummary(storeId = storeId, rows = timeGroups) + } -} \ No newline at end of file + // ✅ 修复:把 assignByLane 移到类里面 + fun assignByLane(request: AssignByLaneRequest): MessageResponse { + val existingOrders = doPickOrderRepository.findByHandledByAndTicketStatusIn( + request.userId, + listOf(DoPickOrderStatus.released, DoPickOrderStatus.pending) + ) + + if (existingOrders.isNotEmpty()) { + return MessageResponse( + id = null, code = "USER_BUSY", name = null, type = null, + message = "User already has an active pick order. Please complete it first.", + errorPosition = null, entity = null + ) + } + val candidates = doPickOrderRepository + .findByStoreIdAndTicketStatusOrderByTruckDepartureTimeAsc( + request.storeId, + DoPickOrderStatus.pending + ) + .filter { + it.handledBy == null && + it.truckLanceCode == request.truckLanceCode && + (request.truckDepartureTime == null || + it.truckDepartureTime?.toString() == request.truckDepartureTime) + } + + if (candidates.isEmpty()) { + return MessageResponse( + id = null, code = "NO_ORDERS", name = null, type = null, + message = "No available orders for lane ${request.truckLanceCode}", + errorPosition = null, entity = null + ) + } + + val firstOrder = candidates.first() + val user = userRepository.findById(request.userId).orElse(null) + val handlerName = user?.name ?: "Unknown" + + // ✅ 更新 do_pick_order + firstOrder.handledBy = request.userId + firstOrder.handlerName = handlerName + firstOrder.ticketStatus = DoPickOrderStatus.released + firstOrder.ticketReleaseTime = LocalDateTime.now() + + doPickOrderRepository.save(firstOrder) + + // ✅ 同步更新 pick_order 表 + if (firstOrder.pickOrderId != null) { + val pickOrder = pickOrderRepository.findById(firstOrder.pickOrderId!!).orElse(null) + if (pickOrder != null) { + // ✅ 修复:assignTo 需要 User 对象,不是 Long + val user = userRepository.findById(request.userId).orElse(null) + pickOrder.assignTo = user + pickOrder.status = PickOrderStatus.RELEASED + pickOrderRepository.save(pickOrder) + } + } + + // 同步更新 record + val records = doPickOrderRecordRepository.findByPickOrderId(firstOrder.pickOrderId!!) + records.forEach { + it.handledBy = request.userId + it.handlerName = handlerName + it.ticketStatus = DoPickOrderStatus.released + it.ticketReleaseTime = LocalDateTime.now() + } + doPickOrderRecordRepository.saveAll(records) + + return MessageResponse( + id = firstOrder.pickOrderId, + code = "SUCCESS", + name = null, + type = null, + message = "Assigned pick order from lane ${request.truckLanceCode}", + errorPosition = null, + entity = mapOf( + "pickOrderId" to firstOrder.pickOrderId, + "ticketNo" to firstOrder.ticketNo + ) + ) + } +} // ✅ 类结束 \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoPickOrderController.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoPickOrderController.kt index d0a995b..5685eda 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoPickOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoPickOrderController.kt @@ -13,6 +13,7 @@ import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderRequest import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderResponse import com.ffii.fpsms.modules.pickOrder.web.models.ReleaseConsoPickOrderRequest import com.ffii.fpsms.modules.pickOrder.web.models.SearchPickOrderRequest +import com.ffii.fpsms.modules.deliveryOrder.web.models.DoDetailResponse import com.ffii.fpsms.modules.pickOrder.web.models.SavePickOrderGroupRequest import jakarta.servlet.http.HttpServletRequest import jakarta.validation.Valid @@ -35,7 +36,7 @@ import java.time.LocalDate import com.ffii.fpsms.modules.deliveryOrder.service.DoPickOrderService import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRepository import com.ffii.fpsms.modules.deliveryOrder.web.models.AssignByStoreRequest - +import com.ffii.fpsms.modules.deliveryOrder.web.models.* @RestController @RequestMapping("/doPickOrder") class DoPickOrderController( @@ -56,4 +57,12 @@ class DoPickOrderController( fun getReleasedDoPickOrders(): List { return doPickOrderService.findReleasedDoPickOrders() } + @GetMapping("/summary-by-store") + fun getSummaryByStore(@RequestParam storeId: String): StoreLaneSummary { + return doPickOrderService.getSummaryByStore(storeId) + } + @PostMapping("/assign-by-lane") +fun assignByLane(@RequestBody request: AssignByLaneRequest): MessageResponse { + return doPickOrderService.assignByLane(request) +} } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt index 17e0572..9d3f4e5 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt @@ -29,4 +29,25 @@ data class DoDetailLineResponse( val uom: String?, val uomCode: String?, val shortUom: String?, +) +data class StoreLaneSummary( + val storeId: String, + val rows: List +) + +data class LaneRow( + val truckDepartureTime: String, + val lanes: List +) + +data class LaneBtn( + val truckLanceCode: String, + val unassigned: Int, + val total: Int +) +data class AssignByLaneRequest( + val userId: Long, + val storeId: String, + val truckDepartureTime: String?, // 可选:限定出车时间 + val truckLanceCode: String // 必填:车道编号 ) \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20251014_01_enson/02_altertable_enson.sql b/src/main/resources/db/changelog/changes/20251014_01_enson/02_altertable_enson.sql new file mode 100644 index 0000000..486f230 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20251014_01_enson/02_altertable_enson.sql @@ -0,0 +1,72 @@ +-- liquibase formatted sql +-- changeset enson:altertable_warehouse + + +ALTER TABLE do_pick_order_record + ADD COLUMN pick_order_code VARCHAR(50) NULL AFTER pick_order_id, + ADD COLUMN delivery_order_code VARCHAR(50) NULL AFTER do_order_id, + ADD COLUMN handler_name VARCHAR(100) NULL AFTER handled_by, + ADD COLUMN loading_sequence INT NULL AFTER ShopName; + + +ALTER TABLE do_pick_order + ADD COLUMN pick_order_code VARCHAR(50) NULL AFTER pick_order_id, + ADD COLUMN delivery_order_code VARCHAR(50) NULL AFTER do_order_id, + ADD COLUMN handler_name VARCHAR(100) NULL AFTER handled_by, + ADD COLUMN loading_sequence INT NULL AFTER ShopName; + +ALTER TABLE do_pick_order_record + MODIFY COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, + MODIFY COLUMN pick_order_id INT NULL AFTER id, + MODIFY COLUMN do_order_id INT NULL AFTER pick_order_id, + MODIFY COLUMN truck_id INT NULL AFTER do_order_id, + MODIFY COLUMN shop_id INT NULL AFTER truck_id, + MODIFY COLUMN store_id VARCHAR(10) NULL AFTER shop_id, + MODIFY COLUMN RequiredDeliveryDate DATE NULL AFTER store_id, + MODIFY COLUMN truck_departure_time TIME NULL AFTER RequiredDeliveryDate, + MODIFY COLUMN TruckLanceCode VARCHAR(50) NULL AFTER truck_departure_time, + MODIFY COLUMN ShopCode VARCHAR(50) NULL AFTER TruckLanceCode, + MODIFY COLUMN ShopName VARCHAR(255) NULL AFTER ShopCode, + MODIFY COLUMN loading_sequence INT NULL AFTER ShopName, + MODIFY COLUMN delivery_order_code VARCHAR(50) NULL AFTER loading_sequence, + MODIFY COLUMN pick_order_code VARCHAR(50) NULL AFTER delivery_order_code, + MODIFY COLUMN ticket_no VARCHAR(50) NULL AFTER pick_order_code, + MODIFY COLUMN ticket_release_time DATETIME NULL AFTER ticket_no, + MODIFY COLUMN ticketCompleteDateTime DATETIME NULL AFTER ticket_release_time, + MODIFY COLUMN ticket_status ENUM('pending','released','completed') NULL AFTER ticketCompleteDateTime, + MODIFY COLUMN handled_by INT NULL AFTER ticket_status, + MODIFY COLUMN handler_name VARCHAR(100) NULL AFTER handled_by, + MODIFY COLUMN created DATETIME NULL AFTER handler_name, + MODIFY COLUMN createdBy VARCHAR(30) NULL AFTER created, + MODIFY COLUMN version INT NULL AFTER createdBy, + MODIFY COLUMN modified DATETIME NULL AFTER version, + MODIFY COLUMN modifiedBy VARCHAR(30) NULL AFTER modified, + MODIFY COLUMN deleted TINYINT(1) NULL AFTER modifiedBy; + +ALTER TABLE do_pick_order + MODIFY COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, + MODIFY COLUMN pick_order_id INT NULL AFTER id, + MODIFY COLUMN do_order_id INT NULL AFTER pick_order_id, + MODIFY COLUMN truck_id INT NULL AFTER do_order_id, + MODIFY COLUMN shop_id INT NULL AFTER truck_id, + MODIFY COLUMN store_id VARCHAR(10) NULL AFTER shop_id, + MODIFY COLUMN RequiredDeliveryDate DATE NULL AFTER store_id, + MODIFY COLUMN truck_departure_time TIME NULL AFTER RequiredDeliveryDate, + MODIFY COLUMN TruckLanceCode VARCHAR(50) NULL AFTER truck_departure_time, + MODIFY COLUMN ShopCode VARCHAR(50) NULL AFTER TruckLanceCode, + MODIFY COLUMN ShopName VARCHAR(255) NULL AFTER ShopCode, + MODIFY COLUMN loading_sequence INT NULL AFTER ShopName, + MODIFY COLUMN delivery_order_code VARCHAR(50) NULL AFTER loading_sequence, + MODIFY COLUMN pick_order_code VARCHAR(50) NULL AFTER delivery_order_code, + MODIFY COLUMN ticket_no VARCHAR(50) NULL AFTER pick_order_code, + MODIFY COLUMN ticket_release_time DATETIME NULL AFTER ticket_no, + MODIFY COLUMN ticketCompleteDateTime DATETIME NULL AFTER ticket_release_time, + MODIFY COLUMN ticket_status ENUM('pending','released','completed') NULL AFTER ticketCompleteDateTime, + MODIFY COLUMN handled_by INT NULL AFTER ticket_status, + MODIFY COLUMN handler_name VARCHAR(100) NULL AFTER handled_by, + MODIFY COLUMN created DATETIME NULL AFTER handler_name, + MODIFY COLUMN createdBy VARCHAR(30) NULL AFTER created, + MODIFY COLUMN version INT NULL AFTER createdBy, + MODIFY COLUMN modified DATETIME NULL AFTER version, + MODIFY COLUMN modifiedBy VARCHAR(30) NULL AFTER modified, + MODIFY COLUMN deleted TINYINT(1) NULL AFTER modifiedBy; \ No newline at end of file