Browse Source

update

master
CANCERYS\kw093 2 months ago
parent
commit
d841f4f8ce
15 changed files with 679 additions and 527 deletions
  1. +33
    -13
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt
  2. +32
    -10
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt
  3. +110
    -95
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
  4. +8
    -6
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt
  5. +24
    -17
      src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt
  6. +7
    -11
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/Router.kt
  7. +20
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/RouterOrder.kt
  8. +16
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/RouterOrderRepository.kt
  9. +4
    -6
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/RouterRepository.kt
  10. +14
    -14
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/Truck.kt
  11. +12
    -7
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/TruckRepository.kt
  12. +303
    -341
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
  13. +1
    -7
      src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt
  14. +27
    -0
      src/main/resources/db/changelog/changes/202511005_01_enson/01_altertable_enson.sql
  15. +68
    -0
      src/main/resources/db/changelog/changes/202511005_01_enson/02_altertable_enson.sql

+ 33
- 13
src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt View File

@@ -3,6 +3,7 @@ package com.ffii.fpsms.modules.deliveryOrder.entity
import jakarta.persistence.*
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.LocalDate
import com.ffii.fpsms.modules.deliveryOrder.enums.DoPickOrderStatus
import org.hibernate.annotations.CreationTimestamp
import org.hibernate.annotations.UpdateTimestamp
@@ -19,8 +20,10 @@ class DoPickOrder {
@Column(name = "ticket_no", length = 50)
var ticketNo: String? = null
@Column(name = "pick_order_id")
var pickOrderId: Long? = null
@Enumerated(EnumType.STRING)
@Column(name = "ticket_status")
var ticketStatus: DoPickOrderStatus? = null
@@ -30,21 +33,35 @@ class DoPickOrder {
@Column(name = "truck_departure_time")
var truckDepartureTime: LocalTime? = null
@Column(name = "item_id")
var itemId: Long? = null

@Column(name = "shop_id")
var shopId: Long? = null
@Column(name = "do_order_id")
var doOrderId: Long? = null
@Column(name = "shop_po_supplier_id")
var shopPoSupplierId: Long? = null
@Column(name = "handled_by")
var handledBy: Long? = null
@Column(name = "ticket_release_time")
var ticketReleaseTime: LocalDateTime? = null
// ✅ 新增字段声明
@Column(name = "ticketCompleteDateTime")
var ticketCompleteDateTime: LocalDateTime? = null
@Column(name = "TruckLanceCode", length = 50)
var truckLanceCode: String? = null
@Column(name = "ShopCode", length = 50)
var shopCode: String? = null
@Column(name = "ShopName", length = 255)
var shopName: String? = null
@Column(name = "RequiredDeliveryDate")
var requiredDeliveryDate: LocalDate? = null
@CreationTimestamp
@Column(name = "created")
var created: LocalDateTime? = null
@@ -64,9 +81,6 @@ class DoPickOrder {
@Column(name = "deleted")
var deleted: Boolean = false

@Column(name = "hide", nullable = false)
var hide: Boolean = false
// Default constructor for Hibernate
constructor()
@@ -81,10 +95,13 @@ class DoPickOrder {
pickOrderId: Long? = null,
doOrderId: Long? = null,
ticketReleaseTime: LocalDateTime? = null,
itemId: Long? = null,
shopId: Long? = null,
shopPoSupplierId: Long? = null,
handledBy: Long? = null,
ticketCompleteDateTime: LocalDateTime? = null,
truckLanceCode: String? = null,
shopCode: String? = null,
shopName: String? = null,
requiredDeliveryDate: LocalDate? = null,
createdBy: String? = null,
modifiedBy: String? = null
) {
@@ -96,10 +113,13 @@ class DoPickOrder {
this.ticketStatus = ticketStatus
this.truckId = truckId
this.truckDepartureTime = truckDepartureTime
this.itemId = itemId
this.shopId = shopId
this.shopPoSupplierId = shopPoSupplierId
this.handledBy = handledBy
this.ticketCompleteDateTime = ticketCompleteDateTime
this.truckLanceCode = truckLanceCode
this.shopCode = shopCode
this.shopName = shopName
this.requiredDeliveryDate = requiredDeliveryDate
this.createdBy = createdBy
this.modifiedBy = modifiedBy
}

+ 32
- 10
src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecord.kt View File

@@ -6,6 +6,7 @@ import java.time.LocalTime
import com.ffii.fpsms.modules.deliveryOrder.enums.DoPickOrderStatus
import org.hibernate.annotations.CreationTimestamp
import org.hibernate.annotations.UpdateTimestamp
import java.time.LocalDate

@Entity
@Table(name = "do_pick_order_record")
@@ -19,33 +20,48 @@ class DoPickOrderRecord {
@Column(name = "ticket_no", length = 50)
var ticketNo: String? = null
@Column(name = "pick_order_id")
var pickOrderId: Long? = null
@Column(name = "do_order_id")
var doOrderId: Long? = null
@Enumerated(EnumType.STRING)
@Column(name = "ticket_status")
var ticketStatus: DoPickOrderStatus? = null
@Column(name = "ticket_release_time")
var ticketReleaseTime: LocalDateTime? = null
@Column(name = "truck_id")
var truckId: Long? = null
@Column(name = "truck_departure_time")
var truckDepartureTime: LocalTime? = null
@Column(name = "item_id")
var itemId: Long? = null
@Column(name = "shop_id")
var shopId: Long? = null
@Column(name = "shop_po_supplier_id")
var shopPoSupplierId: Long? = null
@Column(name = "handled_by")
var handledBy: Long? = null
// ✅ 新增字段声明
@Column(name = "ticketCompleteDateTime")
var ticketCompleteDateTime: LocalDateTime? = null
@Column(name = "TruckLanceCode", length = 50)
var truckLanceCode: String? = null
@Column(name = "ShopCode", length = 50)
var shopCode: String? = null
@Column(name = "ShopName", length = 255)
var shopName: String? = null
@Column(name = "RequiredDeliveryDate")
var requiredDeliveryDate: LocalDate? = null
@CreationTimestamp
@Column(name = "created")
var created: LocalDateTime? = null
@@ -78,11 +94,14 @@ class DoPickOrderRecord {
truckDepartureTime: LocalTime? = null,
pickOrderId: Long? = null,
doOrderId: Long? = null,
itemId: Long? = null,
shopId: Long? = null,
ticketReleaseTime: LocalDateTime? = null,
shopPoSupplierId: Long? = null,
handledBy: Long? = null,
ticketCompleteDateTime: LocalDateTime? = null,
truckLanceCode: String? = null,
shopCode: String? = null,
shopName: String? = null,
requiredDeliveryDate: LocalDate? = null,
createdBy: String? = null,
modifiedBy: String? = null
) {
@@ -94,10 +113,13 @@ class DoPickOrderRecord {
this.ticketStatus = ticketStatus
this.truckId = truckId
this.truckDepartureTime = truckDepartureTime
this.itemId = itemId
this.shopId = shopId
this.shopPoSupplierId = shopPoSupplierId
this.handledBy = handledBy
this.ticketCompleteDateTime = ticketCompleteDateTime
this.truckLanceCode = truckLanceCode
this.shopCode = shopCode
this.shopName = shopName
this.requiredDeliveryDate = requiredDeliveryDate
this.createdBy = createdBy
this.modifiedBy = modifiedBy
}

+ 110
- 95
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt View File

@@ -469,101 +469,115 @@ open class DeliveryOrderService(
}

// ✅ CREATE do_pick_order_record entries
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("ddMMyy"))
println("�� DEBUG: Target date: $targetDate, Date prefix: $datePrefix")

val truck = deliveryOrder.shop?.id?.let { shopId ->
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
trucks.forEach { t ->
println("🔍 DEBUG: Truck ID: ${t.id}, DepartureTime: ${t.departureTime}")
}
val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX }
println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
selectedTruck
}
println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines")
// ✅ Group lines by store ID to get unique ticket numbers per store
val linesByStore = deliveryOrder.deliveryOrderLines.groupBy { line ->
if (deliveryOrder.supplier?.code == "P06B") "4/F" else "2/F"
}

linesByStore.forEach { (storeId, lines) ->
// ✅ Get ticket number for this specific store
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, storeId)
println("🔍 DEBUG: Next ticket number for store $storeId: $nextTicketNumber")

lines.forEach { line ->
println("�� DEBUG: Processing line - Item ID: ${line.item?.id}, Store ID: $storeId")

val doPickOrderRecord = DoPickOrderRecord(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
pickOrderId = createdPickOrder.id,
truckDepartureTime = truck?.departureTime,
itemId = line.item?.id,
shopId = deliveryOrder.shop?.id,
shopPoSupplierId = deliveryOrder.shop?.id,
handledBy = null
)

println("�� DEBUG: Creating DoPickOrderRecord - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")

val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord)
println("🔍 DEBUG: Saved DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}")
}
// ✅ Also create DoPickOrder records for this store
lines.forEach { line ->
println("�� DEBUG: Creating DoPickOrder - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")

val doPickOrder = DoPickOrder(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
doOrderId = deliveryOrder.id,
pickOrderId = createdPickOrder.id,
truckDepartureTime = truck?.departureTime,
itemId = line.item?.id,
shopId = deliveryOrder.shop?.id,
shopPoSupplierId = deliveryOrder.shop?.id,
handledBy = null,
ticketReleaseTime = null
)

val savedDoPickOrder = doPickOrderService.save(doPickOrder)
println("🔍 DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}")
}
}
return MessageResponse(
id = deliveryOrder.id,
code = deliveryOrder.code,
name = deliveryOrder.shop?.name,
type = null,
message = null,
errorPosition = null,
entity = mapOf("status" to deliveryOrder.status?.value)
)
// 第 471-555 行附近 - 修复创建逻辑

// ✅ CREATE do_pick_order_record entries
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("ddMMyy"))

println("🔍 DEBUG: Target date: $targetDate, Date prefix: $datePrefix")
val truck = deliveryOrder.shop?.id?.let { shopId ->
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
trucks.forEach { t ->
println("🔍 DEBUG: Truck ID: ${t.id}, DepartureTime: ${t.departureTime}")
}
val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX }
println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
selectedTruck
}

// ✅ 根据 truck 的 Store_id 字段确定 storeId
val storeId = when (truck?.storeId) {
4 -> "4/F"
2 -> "2/F"
else -> "2/F" // 默认值
}

println("🔍 DEBUG: Determined store ID: $storeId")

// ✅ Get ticket number for this store (只需要一次)
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, storeId)
println("🔍 DEBUG: Next ticket number for store $storeId: $nextTicketNumber")

// ✅ 每个 pick order 只创建一条 DoPickOrderRecord
val doPickOrderRecord = DoPickOrderRecord(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
pickOrderId = createdPickOrder.id,
truckDepartureTime = truck?.departureTime,
shopId = deliveryOrder.shop?.id,
handledBy = null,
// ✅ 填充新增字段
truckLanceCode = truck?.truckLanceCode,
shopCode = deliveryOrder.shop?.code,
shopName = deliveryOrder.shop?.name,
requiredDeliveryDate = targetDate
)

println("🔍 DEBUG: Creating DoPickOrderRecord - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")
val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord)
println("🔍 DEBUG: Saved DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}")

// ✅ 每个 pick order 只创建一条 DoPickOrder
val doPickOrder = DoPickOrder(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
doOrderId = deliveryOrder.id,
pickOrderId = createdPickOrder.id,
truckDepartureTime = truck?.departureTime,
shopId = deliveryOrder.shop?.id,
handledBy = null,
ticketReleaseTime = null,
// ✅ 填充新增字段
truckLanceCode = truck?.truckLanceCode,
shopCode = deliveryOrder.shop?.code,
shopName = deliveryOrder.shop?.name,
requiredDeliveryDate = targetDate
)

println("🔍 DEBUG: Creating DoPickOrder - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")
val savedDoPickOrder = doPickOrderService.save(doPickOrder)
println("🔍 DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}")

return MessageResponse(
id = deliveryOrder.id,
code = deliveryOrder.code,
name = deliveryOrder.shop?.name,
type = null,
message = null,
errorPosition = null,
entity = mapOf("status" to deliveryOrder.status?.value)
)

// ... existing code ...
}

open fun getRouteAndIndexByInventoryLotId(inventoryLotId: Int): List<Router> {
return routerRepository.findByInventoryLotIdAndDeletedFalse(inventoryLotId)
.sortedBy { it.index }
.sortedWith(compareBy(
{ it.routerOrder?.order ?: 999999 },
{ it.route ?: 999999 }
))
}

open fun getRoutesByInventoryLotId(inventoryLotId: Int): List<String> {
return getRouteAndIndexByInventoryLotId(inventoryLotId)
.mapNotNull { it.route }
.mapNotNull { router ->
val routeArea = router.routerOrder?.routeArea ?: ""
val route = router.route?.toString() ?: ""
if (routeArea.isNotEmpty() || route.isNotEmpty()) {
"$routeArea$route"
} else {
null
}
}
}

open fun getRouteByItemId(itemId: Long): String? {
val inventoryLots = inventoryLotService.findByItemId(itemId)
if (inventoryLots.isNotEmpty()){
@@ -575,16 +589,17 @@ open class DeliveryOrderService(
return null
}

open fun getRouterIndexByItemId(itemId: Long): Int? {
val inventoryLots = inventoryLotService.findByItemId(itemId)
if( inventoryLots.isNotEmpty()){
val inventoryLotId = inventoryLots.first().id?.toInt()
return inventoryLotId?.let { lotId ->
getRouteAndIndexByInventoryLotId(lotId).firstOrNull()?.index
}
open fun getRouterIndexByItemId(itemId: Long): Int? {
val inventoryLots = inventoryLotService.findByItemId(itemId)
if (inventoryLots.isNotEmpty()){
val inventoryLotId = inventoryLots.first().id?.toInt()
return inventoryLotId?.let { lotId ->
getRouteAndIndexByInventoryLotId(lotId).firstOrNull()?.routerOrder?.order
}
return null
}
return null
}

open fun getLotNumbersForPickOrderByItemId(itemId: Long, pickOrderId: Long): String {
try {
@@ -624,7 +639,7 @@ open class DeliveryOrderService(
val deliveryOrderEntity = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.deliveryOrderIds)
val selectedTruckNo = deliveryOrderEntity?.shop?.id?.let { shopId ->
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
trucks.firstOrNull()?.truckNo
trucks.firstOrNull()?.truckLanceCode
} ?: ""

val selectedPickOrder = pickOrderRepository.findById(request.pickOrderIds).orElse(null)


+ 8
- 6
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt View File

@@ -109,13 +109,14 @@ class DoPickOrderService(
return doPickOrderRepository.saveAll(doPickOrders)
}
fun completeDoPickOrdersForPickOrder(pickOrderId: Long): List<DoPickOrder> {
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
doPickOrders.forEach {
it.ticketStatus = DoPickOrderStatus.completed // ✅ Update status to "completed"
fun completeDoPickOrdersForPickOrder(pickOrderId: Long): List<DoPickOrder> {
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
doPickOrders.forEach {
it.ticketStatus = DoPickOrderStatus.completed
it.ticketCompleteDateTime = LocalDateTime.now() // ✅ 设置完成时间
}
return doPickOrderRepository.saveAll(doPickOrders)
}
return doPickOrderRepository.saveAll(doPickOrders)
}
// ✅ New method to remove do_pick_order records when auto-assigning by store
fun removeDoPickOrdersForPickOrder(pickOrderId: Long): Int {
@@ -151,6 +152,7 @@ class DoPickOrderService(
val doPickOrderRecords = doPickOrderRecordRepository.findByPickOrderId(pickOrderId)
doPickOrderRecords.forEach {
it.ticketStatus = DoPickOrderStatus.completed
it.ticketCompleteDateTime = LocalDateTime.now() // ✅ 设置完成时间
}
return doPickOrderRecordRepository.saveAll(doPickOrderRecords)
}


+ 24
- 17
src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt View File

@@ -221,9 +221,9 @@ open class JoPickOrderService(
-- Router Information
r.id as routerId,
r.index as routerIndex,
r.route as routerRoute,
r.area as routerArea,
ro.`order` as routerIndex,
CONCAT(COALESCE(ro.route_area, ''), COALESCE(r.route, '')) as routerRoute,
ro.route_area as routerArea,
-- Set quantities to NULL for rejected lots
CASE
@@ -297,6 +297,7 @@ open class JoPickOrderService(
LEFT JOIN fpsmsdb.router r ON r.inventoryLotId = ill.id AND r.deleted = false
LEFT JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId
LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId
LEFT JOIN fpsmsdb.router_order ro ON r.router_id = ro.id
LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ill.id AND sol.deleted = false
LEFT JOIN fpsmsdb.jo_pick_order jpo ON jpo.pick_order_id = po.id AND jpo.item_id = pol.itemId
WHERE po.deleted = false
@@ -309,7 +310,8 @@ open class JoPickOrderService(
AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL)
ORDER BY
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END,
COALESCE(r.index, 0) ASC,
COALESCE(ro.`order`, 999999) ASC,
COALESCE(r.route, 999999) ASC,
po.code ASC,
i.code ASC,
il.expiryDate ASC,
@@ -497,10 +499,9 @@ open fun getCompletedJobOrderLotsHierarchical(userId: Long): Map<String, Any?> {
-- Router Information
r.id as routerId,
r.index as routerIndex,
r.route as routerRoute,
r.area as routerArea,
ro.`order` as routerIndex,
CONCAT(COALESCE(ro.route_area, ''), COALESCE(r.route, '')) as routerRoute,
ro.route_area as routerArea,
-- Set quantities to NULL for rejected lots
CASE
WHEN sol.status = 'rejected' THEN NULL
@@ -573,6 +574,7 @@ open fun getCompletedJobOrderLotsHierarchical(userId: Long): Map<String, Any?> {
LEFT JOIN fpsmsdb.router r ON r.inventoryLotId = ill.id AND r.deleted = false
LEFT JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId
LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId
LEFT JOIN fpsmsdb.router_order ro ON r.router_id = ro.id
LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ill.id AND sol.deleted = false
LEFT JOIN fpsmsdb.jo_pick_order jpo ON jpo.pick_order_id = po.id AND jpo.item_id = pol.itemId
WHERE po.deleted = false
@@ -586,7 +588,8 @@ open fun getCompletedJobOrderLotsHierarchical(userId: Long): Map<String, Any?> {
AND jpo.second_qr_scan_status = 'pending' OR jpo.second_qr_scan_status = 'scanned'
ORDER BY
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END,
COALESCE(r.index, 0) ASC,
COALESCE(ro.`order`, 999999) ASC,
COALESCE(r.route, 999999) ASC,
po.code ASC,
i.code ASC,
il.expiryDate ASC,
@@ -1158,9 +1161,9 @@ open fun getCompletedJobOrderPickOrderLotDetails(pickOrderId: Long): List<Map<St
-- Router Information
r.id as routerId,
r.index as routerIndex,
r.route as routerRoute,
r.area as routerArea,
ro.`order` as routerIndex,
CONCAT(COALESCE(ro.route_area, ''), COALESCE(r.route, '')) as routerRoute,
ro.route_area as routerArea,
-- Set quantities to NULL for rejected lots
CASE
@@ -1238,6 +1241,7 @@ open fun getCompletedJobOrderPickOrderLotDetails(pickOrderId: Long): List<Map<St
LEFT JOIN fpsmsdb.jo_pick_order jpo ON jpo.pick_order_id = po.id AND jpo.item_id = pol.itemId
LEFT JOIN fpsmsdb.item_uom iu ON iu.itemId = b.itemId AND iu.stockUnit = 1
LEFT JOIN fpsmsdb.uom_conversion uc_fg ON uc_fg.id = iu.uomId
LEFT JOIN fpsmsdb.router_order ro ON r.router_id = ro.id
LEFT JOIN fpsmsdb.uom_conversion uc_bom ON uc_bom.id = iu.uomId
WHERE po.deleted = false
AND po.id = :pickOrderId
@@ -1248,7 +1252,8 @@ open fun getCompletedJobOrderPickOrderLotDetails(pickOrderId: Long): List<Map<St
AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL)
ORDER BY
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END,
COALESCE(r.index, 0) ASC,
COALESCE(ro.`order`, 999999) ASC,
COALESCE(r.route, 999999) ASC,
po.code ASC,
i.code ASC,
il.expiryDate ASC,
@@ -1373,9 +1378,9 @@ open fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId: Lo
-- Router Information
r.id as routerId,
r.index as routerIndex,
r.route as routerRoute,
r.area as routerArea,
ro.`order` as routerIndex,
CONCAT(COALESCE(ro.route_area, ''), COALESCE(r.route, '')) as routerRoute,
ro.route_area as routerArea,
-- Set quantities to NULL for rejected lots
CASE
@@ -1449,6 +1454,7 @@ open fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId: Lo
LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId
LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ill.id AND sol.deleted = false
LEFT JOIN fpsmsdb.jo_pick_order jpo ON jpo.pick_order_id = po.id AND jpo.item_id = pol.itemId
LEFT JOIN fpsmsdb.router_order ro ON r.router_id = ro.id
WHERE po.deleted = false
AND po.id = :pickOrderId
AND pol.deleted = false
@@ -1458,7 +1464,8 @@ open fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId: Lo
AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL)
ORDER BY
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END,
COALESCE(r.index, 0) ASC,
COALESCE(ro.`order`, 999999) ASC,
COALESCE(r.route, 999999) ASC,
po.code ASC,
i.code ASC,
il.expiryDate ASC,


+ 7
- 11
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/Router.kt View File

@@ -10,16 +10,9 @@ import java.math.BigDecimal
@Table(name = "router")
open class Router : BaseEntity<Long>() {
@Column(name = "`index`", nullable = false)
open var index: Int? = null

@Size(max = 50)
@Column(name = "route")
open var route: String? = null

@Size(max = 50)
@Column(name = "area")
open var area: String? = null
open var route: Int? = null

@Column(name = "item_code")
open var itemCode: Int? = null
@@ -31,9 +24,12 @@ open class Router : BaseEntity<Long>() {
@Column(name = "uomId")
open var uomId: Int? = null

@Column(name = "NoofCarton")
open var noofCarton: Int? = null

@Column(name = "inventoryLotId")
open var inventoryLotId: Int? = null

@Column(name = "router_id")
open var routerId: Int? = null
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "router_id", insertable = false, updatable = false)
open var routerOrder: RouterOrder? = null
}

+ 20
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/RouterOrder.kt View File

@@ -0,0 +1,20 @@
package com.ffii.fpsms.modules.pickOrder.entity

import com.ffii.core.entity.BaseEntity
import jakarta.persistence.*
import jakarta.validation.constraints.NotNull
import jakarta.validation.constraints.Size
import java.math.BigDecimal

@Entity
@Table(name = "router_order")
open class RouterOrder : BaseEntity<Long>() {
@Size(max = 50)
@Column(name = "route_area")
open var routeArea: String? = null

@Column(name = "`order`")
open var order: Int? = null

}

+ 16
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/RouterOrderRepository.kt View File

@@ -0,0 +1,16 @@
package com.ffii.fpsms.modules.pickOrder.entity

import com.ffii.core.support.AbstractRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import org.springframework.stereotype.Repository

@Repository
interface RouterOrderRepository : AbstractRepository<RouterOrder, Long> {
@Query("SELECT ro FROM RouterOrder ro WHERE ro.routeArea = :routeArea AND ro.deleted = false")
fun findByRouteAreaAndDeletedFalse(@Param("routeArea") routeArea: String): RouterOrder?
@Query("SELECT ro FROM RouterOrder ro WHERE ro.deleted = false ORDER BY ro.order ASC")
fun findAllByDeletedFalseOrderByOrder(): List<RouterOrder>
}

+ 4
- 6
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/RouterRepository.kt View File

@@ -17,11 +17,9 @@ interface RouterRepository : AbstractRepository<Router, Long> {
@Query("SELECT r FROM Router r WHERE r.itemCode = :itemCode AND r.deleted = false")
fun findByItemCodeAndDeletedFalse(@Param("itemCode") itemCode: Int): List<Router>
@Query("SELECT r FROM Router r WHERE r.`index` = :index AND r.deleted = false")
fun findByIndexAndDeletedFalse(@Param("index") index: Int): List<Router>
@Query("SELECT r FROM Router r WHERE r.route = :route AND r.deleted = false")
fun findByRouteAndDeletedFalse(@Param("route") route: String): List<Router>


fun findByRouteAndDeletedFalse(@Param("route") route: Int): List<Router>
@Query("SELECT r FROM Router r WHERE r.routerId = :routerId AND r.deleted = false")
fun findByRouterIdAndDeletedFalse(@Param("routerId") routerId: Int): List<Router>
}

+ 14
- 14
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/Truck.kt View File

@@ -5,7 +5,6 @@ import com.ffii.fpsms.modules.master.entity.Shop
import jakarta.persistence.*
import jakarta.validation.constraints.NotNull
import jakarta.validation.constraints.Size
import java.math.BigDecimal
import java.time.LocalTime

@Entity
@@ -14,12 +13,8 @@ open class Truck : BaseEntity<Long>() {
@Size(max = 50)
@NotNull
@Column(name = "truckNo", nullable = false, unique = true)
open var truckNo: String? = null

@Size(max = 100)
@Column(name = "truckName")
open var truckName: String? = null
@Column(name = "TruckLanceCode", nullable = false)
open var truckLanceCode: String? = null

@Column(name = "DepartureTime")
open var departureTime: LocalTime? = null
@@ -27,11 +22,16 @@ open class Truck : BaseEntity<Long>() {
@ManyToOne
@JoinColumn(name = "shopId")
open var shop: Shop? = null

@Column(name = "capacity", precision = 10, scale = 2)
open var capacity: BigDecimal? = null

@Size(max = 20)
@Column(name = "status")
open var status: String? = null
@Column(name = "ShopName", length = 255)
open var shopName: String? = null
@Column(name = "ShopCode", length = 50)
open var shopCode: String? = null
@Column(name = "LoadingSequence")
open var loadingSequence: Int? = null
@Column(name = "Store_id")
open var storeId: Int? = null
}

+ 12
- 7
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/TruckRepository.kt View File

@@ -8,15 +8,20 @@ import org.springframework.stereotype.Repository
@Repository
interface TruckRepository : AbstractRepository<Truck, Long> {
@Query("SELECT t FROM Truck t WHERE t.shop.id = :shopId AND t.deleted = false")
fun findByShopIdAndDeletedFalse(@Param("shopId") shopId: Long): List<Truck>
fun findByShopIdAndDeletedFalse(shopId: Long): List<Truck>
@Query("SELECT t FROM Truck t WHERE t.shop.id = :shopId AND t.deleted = false ORDER BY t.id ASC")
fun findFirstByShopIdAndDeletedFalse(@Param("shopId") shopId: Long): List<Truck> // ✅ Change to List<Truck>
fun findFirstByShopIdAndDeletedFalse(@Param("shopId") shopId: Long): List<Truck>
@Query("SELECT t FROM Truck t WHERE t.truckNo = :truckNo AND t.deleted = false")
fun findByTruckNoAndDeletedFalse(@Param("truckNo") truckNo: String): Truck?
// ✅ 使用新的 TruckLanceCode 字段名
@Query("SELECT t FROM Truck t WHERE t.truckLanceCode = :truckLanceCode AND t.deleted = false")
fun findByTruckLanceCodeAndDeletedFalse(@Param("truckLanceCode") truckLanceCode: String): Truck?
@Query("SELECT t FROM Truck t WHERE t.status = :status AND t.deleted = false")
fun findByStatusAndDeletedFalse(@Param("status") status: String): List<Truck>

// ✅ 按 ShopCode 查询
@Query("SELECT t FROM Truck t WHERE t.shopCode = :shopCode AND t.deleted = false")
fun findByShopCodeAndDeletedFalse(@Param("shopCode") shopCode: String): List<Truck>
// ✅ 按 Store_id 查询
fun findByStoreIdAndDeletedFalse(storeId: Int): List<Truck>
}

+ 303
- 341
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt View File

@@ -494,13 +494,6 @@ open class PickOrderService(
)
}

// Actual Pick Lots
// val actualPickLots = pol.stockOutLines
// val finalActualPickLots = actualPickLots.map {
// ActualPickLotInConso(
//
// )
// }

// Return
PickOrderLineInConso(
@@ -2221,245 +2214,257 @@ open fun autoAssignAndReleasePickOrderByStoreAndTicket(storeId: String, ticketNo
}
}
@Transactional(rollbackFor = [java.lang.Exception::class])
open fun autoAssignAndReleasePickOrderByStore(userId: Long, storeId: String): MessageResponse {
try {
println("=== DEBUG: autoAssignAndReleasePickOrderByStore ===")
println("userId: $userId, storeId: $storeId")

val zero = BigDecimal.ZERO
val releasedBy = SecurityUtils.getUser().getOrNull()
val user = userService.find(userId).orElse(null)
if (user == null) {
return MessageResponse(id = null, name = "User not found", code = "ERROR", type = "pickorder",
message = "User with ID $userId not found", errorPosition = null)
}

val sql = """
SELECT DISTINCT dpo.pick_order_id AS pickOrderId
FROM do_pick_order dpo
WHERE dpo.deleted = false
AND dpo.ticket_status = 'pending'
AND dpo.store_id = :storeId
AND dpo.pick_order_id IS NOT NULL
""".trimIndent()
val idRows = jdbcDao.queryForList(sql, mapOf("storeId" to storeId))
val pickOrderIdsByStore = idRows.mapNotNull { row ->
when (val id = row["pickOrderId"]) {
is Number -> id.toLong()
is String -> id.toLongOrNull()
else -> null
open fun autoAssignAndReleasePickOrderByStore(userId: Long, storeId: String): MessageResponse {
try {
println("=== DEBUG: autoAssignAndReleasePickOrderByStore ===")
println("userId: $userId, storeId: $storeId")
val zero = BigDecimal.ZERO
val releasedBy = SecurityUtils.getUser().getOrNull()
val user = userService.find(userId).orElse(null)
if (user == null) {
return MessageResponse(id = null, name = "User not found", code = "ERROR", type = "pickorder",
message = "User with ID $userId not found", errorPosition = null)
}
}.toSet()
println("Candidate pickOrderIds by store $storeId: $pickOrderIdsByStore")

if (pickOrderIdsByStore.isEmpty()) {
return MessageResponse(id = null, name = "No pick orders", code = "NO_ORDERS", type = "pickorder",
message = "No pending pick orders found for store $storeId", errorPosition = null)
}
// Add this check after line 2142 (before finding availablePickOrders)
// ✅ Check if user already has pick orders in progress
val userExistingOrders = pickOrderRepository.findAllByAssignToAndStatusIn(
user,
listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED) // Only active orders, not completed
).filter { it.deliveryOrder != null }

if (userExistingOrders.isNotEmpty()) {
println("🔍 DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress:")
userExistingOrders.forEach { po ->
println("�� DEBUG: Existing order ${po.id}: code=${po.code}, status=${po.status}")
val sql = """
SELECT DISTINCT dpo.pick_order_id AS pickOrderId
FROM do_pick_order dpo
WHERE dpo.deleted = false
AND dpo.ticket_status = 'pending'
AND dpo.store_id = :storeId
AND dpo.pick_order_id IS NOT NULL
""".trimIndent()
val idRows = jdbcDao.queryForList(sql, mapOf("storeId" to storeId))
val pickOrderIdsByStore = idRows.mapNotNull { row ->
when (val id = row["pickOrderId"]) {
is Number -> id.toLong()
is String -> id.toLongOrNull()
else -> null
}
}.toSet()
println("Candidate pickOrderIds by store $storeId: $pickOrderIdsByStore")
if (pickOrderIdsByStore.isEmpty()) {
return MessageResponse(id = null, name = "No pick orders", code = "NO_ORDERS", type = "pickorder",
message = "No pending pick orders found for store $storeId", errorPosition = null)
}
return MessageResponse(
id = null,
name = "User already has pick orders",
code = "USER_BUSY",
type = "pickorder",
message = "User $userId already has ${userExistingOrders.size} pick orders in progress. Cannot assign new orders.",
errorPosition = null,
entity = mapOf(
"existingOrders" to userExistingOrders.map { mapOf(
"id" to it.id,
"code" to it.code,
"status" to it.status?.value
)}
// ✅ Check if user already has pick orders in progress
val userExistingOrders = pickOrderRepository.findAllByAssignToAndStatusIn(
user,
listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED)
).filter { it.deliveryOrder != null }
if (userExistingOrders.isNotEmpty()) {
println("🔍 DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress:")
userExistingOrders.forEach { po ->
println("🔍 DEBUG: Existing order ${po.id}: code=${po.code}, status=${po.status}")
}
return MessageResponse(
id = null,
name = "User already has pick orders",
code = "USER_BUSY",
type = "pickorder",
message = "User $userId already has ${userExistingOrders.size} pick orders in progress. Cannot assign new orders.",
errorPosition = null,
entity = mapOf(
"existingOrders" to userExistingOrders.map { mapOf(
"id" to it.id,
"code" to it.code,
"status" to it.status?.value
)}
)
)
)
}

// Continue with existing logic...
val availablePickOrders = pickOrderRepository
.findAll()
.filter { it.id != null && pickOrderIdsByStore.contains(it.id!!) }
.filter { it.deliveryOrder != null }
.filter { it.assignTo == null }
.filter { it.status == PickOrderStatus.PENDING || it.status == PickOrderStatus.RELEASED }
.sortedBy { it.targetDate }
.take(1)

if (availablePickOrders.isEmpty()) {
return MessageResponse(id = null, name = "No available pick orders", code = "NO_ORDERS", type = "pickorder",
message = "No unassigned pick orders available for store $storeId", errorPosition = null)
}

val selected = availablePickOrders.first()
val currUser = SecurityUtils.getUser().orElseThrow()

// If still PENDING, perform full release flow; if already RELEASED, skip creation duplication
if (selected.status == PickOrderStatus.PENDING) {
val newConsoCode = assignConsoCode()

val stockOut = StockOut().apply {
this.type = "job"
this.consoPickOrderCode = newConsoCode
this.status = StockOutStatus.PENDING.status
this.handler = currUser.id
}
val savedStockOut = stockOutRepository.saveAndFlush(stockOut)

selected.apply {
this.releasedBy = releasedBy
status = PickOrderStatus.RELEASED
this.consoCode = newConsoCode
val availablePickOrders = pickOrderRepository
.findAll()
.filter { it.id != null && pickOrderIdsByStore.contains(it.id!!) }
.filter { it.deliveryOrder != null }
.filter { it.assignTo == null }
.filter { it.status == PickOrderStatus.PENDING || it.status == PickOrderStatus.RELEASED }
.sortedBy { it.targetDate }
.take(1)
if (availablePickOrders.isEmpty()) {
return MessageResponse(id = null, name = "No available pick orders", code = "NO_ORDERS", type = "pickorder",
message = "No unassigned pick orders available for store $storeId", errorPosition = null)
}

val suggestions = suggestedPickLotService.suggestionForPickOrders(
SuggestedPickLotForPoRequest(pickOrders = listOf(selected))
)
val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList)
pickOrderRepository.saveAndFlush(selected)

val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn(
saveSuggestedPickLots.mapNotNull { it.suggestedLotLine?.id }
)
saveSuggestedPickLots.forEach { lot ->
val lotLineId = lot.suggestedLotLine?.id
if (lotLineId != null) {
val idx = inventoryLotLines.indexOf(lot.suggestedLotLine)
if (idx >= 0) {
val currentHold = inventoryLotLines[idx].holdQty ?: zero
val addHold = lot.qty ?: zero
inventoryLotLines[idx].holdQty = currentHold.plus(addHold)
val selected = availablePickOrders.first()
val currUser = SecurityUtils.getUser().orElseThrow()
// If still PENDING, perform full release flow
if (selected.status == PickOrderStatus.PENDING) {
val newConsoCode = assignConsoCode()
val stockOut = StockOut().apply {
this.type = "job"
this.consoPickOrderCode = newConsoCode
this.status = StockOutStatus.PENDING.status
this.handler = currUser.id
}
val savedStockOut = stockOutRepository.saveAndFlush(stockOut)
selected.apply {
this.releasedBy = releasedBy
status = PickOrderStatus.RELEASED
this.consoCode = newConsoCode
}
val suggestions = suggestedPickLotService.suggestionForPickOrders(
SuggestedPickLotForPoRequest(pickOrders = listOf(selected))
)
val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList)
pickOrderRepository.saveAndFlush(selected)
val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn(
saveSuggestedPickLots.mapNotNull { it.suggestedLotLine?.id }
)
saveSuggestedPickLots.forEach { lot ->
val lotLineId = lot.suggestedLotLine?.id
if (lotLineId != null) {
val idx = inventoryLotLines.indexOf(lot.suggestedLotLine)
if (idx >= 0) {
val currentHold = inventoryLotLines[idx].holdQty ?: zero
val addHold = lot.qty ?: zero
inventoryLotLines[idx].holdQty = currentHold.plus(addHold)
}
}
}
}
inventoryLotLineRepository.saveAll(inventoryLotLines)

var precreated = 0
saveSuggestedPickLots.forEach { lot ->
val polId = lot.pickOrderLine?.id
val illId = lot.suggestedLotLine?.id
if (polId != null && illId != null) {
val existing = stockOutLIneRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(polId, illId)
if (existing.isEmpty()) {
val pol = pickOrderLineRepository.findById(polId).orElse(null)
val ill = inventoryLotLineRepository.findById(illId).orElse(null)
if (pol != null && ill != null) {
val line = com.ffii.fpsms.modules.stock.entity.StockOutLine().apply {
this.stockOut = savedStockOut
this.pickOrderLine = pol
this.inventoryLotLine = ill
this.item = pol.item
this.status = com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus.PENDING.status
this.qty = 0.0
inventoryLotLineRepository.saveAll(inventoryLotLines)
var precreated = 0
saveSuggestedPickLots.forEach { lot ->
val polId = lot.pickOrderLine?.id
val illId = lot.suggestedLotLine?.id
if (polId != null && illId != null) {
val existing = stockOutLIneRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(polId, illId)
if (existing.isEmpty()) {
val pol = pickOrderLineRepository.findById(polId).orElse(null)
val ill = inventoryLotLineRepository.findById(illId).orElse(null)
if (pol != null && ill != null) {
val line = com.ffii.fpsms.modules.stock.entity.StockOutLine().apply {
this.stockOut = savedStockOut
this.pickOrderLine = pol
this.inventoryLotLine = ill
this.item = pol.item
this.status = com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus.PENDING.status
this.qty = 0.0
}
stockOutLIneRepository.save(line)
precreated++
}
stockOutLIneRepository.save(line)
precreated++
}
}
}
println("Precreated $precreated stock out lines for store $storeId")
}
println("Precreated $precreated stock out lines for store $storeId")
}

// Assign user (both pending->released and already released)
selected.assignTo = user
pickOrderRepository.saveAndFlush(selected)
val deliveryOrder = selected.deliveryOrder
if (deliveryOrder != null) {
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("ddMMyy"))
println("�� DEBUG: Target date: $targetDate, Date prefix: $datePrefix")

val storeId = if (deliveryOrder.supplier?.code == "P06B") "4/F" else "2/F"
println("🔍 DEBUG: Determined store ID: $storeId")

// Get next ticket number for this date and store
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, storeId)
println("🔍 DEBUG: Next ticket number: $nextTicketNumber")
// Assign user (both pending->released and already released)
selected.assignTo = user
pickOrderRepository.saveAndFlush(selected)
// ✅ Find truck by shop ID with earliest departure time
val truck = deliveryOrder.shop?.id?.let { shopId ->
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX }
println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
selectedTruck
// ✅ 更新 DoPickOrderRecord,填充新字段
val deliveryOrder = selected.deliveryOrder
if (deliveryOrder != null) {
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("ddMMyy"))
println("🔍 DEBUG: Target date: $targetDate, Date prefix: $datePrefix")
// ✅ Find truck by shop ID with earliest departure time
val truck = deliveryOrder.shop?.id?.let { shopId ->
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX }
println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
selectedTruck
}
// ✅ 根据 truck 的 Store_id 字段确定 storeId
val determinedStoreId = when (truck?.storeId) {
4 -> "4/F"
2 -> "2/F"
else -> "2/F"
}
// Get next ticket number for this date and store
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, determinedStoreId)
println("🔍 DEBUG: Next ticket number: $nextTicketNumber")
println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines")
// ✅ UPDATE existing do_pick_order_record entries instead of creating new ones
val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!)
println("🔍 DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}")
if (existingRecords.isNotEmpty()) {
// ✅ Update existing records
existingRecords.forEach { record ->
record.handledBy = user.id
record.ticketStatus = DoPickOrderStatus.released
// ✅ 填充新字段
record.truckLanceCode = truck?.truckLanceCode
record.shopCode = deliveryOrder.shop?.code
record.shopName = deliveryOrder.shop?.name
record.requiredDeliveryDate = targetDate
println("🔍 DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released")
}
doPickOrderRecordRepository.saveAll(existingRecords)
println("✅ Updated ${existingRecords.size} existing DoPickOrderRecord entries")
} else {
// ✅ Only create new records if none exist (fallback)
println("⚠️ No existing DoPickOrderRecord entries found, creating new ones")
deliveryOrder.deliveryOrderLines.forEach { line ->
println("🔍 DEBUG: Processing line - Store ID: $determinedStoreId")
val doPickOrderRecord = DoPickOrderRecord(
storeId = determinedStoreId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.released,
truckId = truck?.id,
pickOrderId = selected.id,
truckDepartureTime = truck?.departureTime,
shopId = deliveryOrder.shop?.id,
handledBy = user.id,
// ✅ 填充新增字段
truckLanceCode = truck?.truckLanceCode,
shopCode = deliveryOrder.shop?.code,
shopName = deliveryOrder.shop?.name,
requiredDeliveryDate = targetDate
)
println("🔍 DEBUG: Creating new DoPickOrderRecord - Store: $determinedStoreId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")
val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord)
println("🔍 DEBUG: Saved new DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}")
}
}
}
println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines")
doPickOrderService.updateHandledByForPickOrder(selected.id!!, user.id!!)
println("✅ Updated DoPickOrder handledBy to user $userId for pick order ${selected.id}")
// Replace lines 2253-2275 with this:
// ✅ UPDATE existing do_pick_order_record entries instead of creating new ones
val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!)
println("🔍 DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}")

if (existingRecords.isNotEmpty()) {
// ✅ Update existing records
existingRecords.forEach { record ->
record.handledBy = user.id
record.ticketStatus = DoPickOrderStatus.released
println("🔍 DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released")
}
doPickOrderRecordRepository.saveAll(existingRecords)
println("✅ Updated ${existingRecords.size} existing DoPickOrderRecord entries")
} else {
// ✅ Only create new records if none exist (fallback)
println("⚠️ No existing DoPickOrderRecord entries found, creating new ones")
deliveryOrder.deliveryOrderLines.forEach { line ->
val storeId = if (deliveryOrder.supplier?.code == "P06B") "4/F" else "2/F"
println(" DEBUG: Processing line - Item ID: ${line.item?.id}, Store ID: $storeId")
val doPickOrderRecord = DoPickOrderRecord(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.released, // ✅ Set to released
truckId = truck?.id,
pickOrderId = selected.id,
truckDepartureTime = truck?.departureTime,
itemId = line.item?.id,
shopId = deliveryOrder.shop?.id,
shopPoSupplierId = deliveryOrder.shop?.id,
handledBy = user.id
)
println(" DEBUG: Creating new DoPickOrderRecord - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")
val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord)
println("🔍 DEBUG: Saved new DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}")
}
}
return MessageResponse(
id = null,
name = "Pick order assigned",
code = "SUCCESS",
type = "pickorder",
message = "Assigned to user $userId for store $storeId",
errorPosition = null,
entity = mapOf("pickOrderIds" to listOf(selected.id!!), "storeId" to storeId, "status" to selected.status?.value)
)
} catch (e: Exception) {
e.printStackTrace()
return MessageResponse(
id = null, name = "Failed to auto-assign by store", code = "ERROR", type = "pickorder",
message = "Failed to auto-assign by store: ${e.message}", errorPosition = null
)
}
doPickOrderService.updateHandledByForPickOrder(selected.id!!, user.id!!)
println("✅ Updated DoPickOrder handledBy to user $userId for pick order ${selected.id}")
return MessageResponse(
id = null,
name = "Pick order assigned",
code = "SUCCESS",
type = "pickorder",
message = "Assigned to user $userId for store $storeId",
errorPosition = null,
entity = mapOf("pickOrderIds" to listOf(selected.id!!), "storeId" to storeId, "status" to selected.status?.value)
)
} catch (e: Exception) {
e.printStackTrace()
return MessageResponse(
id = null, name = "Failed to auto-assign by store", code = "ERROR", type = "pickorder",
message = "Failed to auto-assign by store: ${e.message}", errorPosition = null
)
}
}
open fun getAllPickOrderLotsWithDetailsWithAutoAssign(userId: Long): List<Map<String, Any>> {
println("=== Debug: getAllPickOrderLotsWithDetailsWithAutoAssign ===")
println("today: ${LocalDate.now()}")
@@ -2642,13 +2647,13 @@ if (existingRecords.isNotEmpty()) {
val router = routerRepository.findFirstByInventoryLotIdAndDeletedFalse(inventoryLotId.toInt())
if (router != null) {
mapOf(
"routerIndex" to (router.index ?: 0),
"routerRoute" to (router.route ?: ""),
"routerArea" to (router.area ?: ""),
"routerIndex" to (router.routerOrder?.order ?: 0),
"routerRoute" to "${router.routerOrder?.routeArea ?: ""}${router.route ?: ""}",
"routerArea" to (router.routerOrder?.routeArea ?: ""),
"routerItemCode" to (router.itemCode ?: 0),
"routerItemName" to (router.itemName ?: ""),
"routerUomId" to (router.uomId ?: 0),
"routerNoofCarton" to (router.noofCarton ?: 0)
)
} else {
mapOf(
@@ -2715,7 +2720,7 @@ if (existingRecords.isNotEmpty()) {
val truckInfo = if (shop?.id != null) {
try {
jdbcDao.queryForMap("""
SELECT truckNo, DepartureTime
SELECT TruckLanceCode, DepartureTime
FROM truck
WHERE shopId = :shopId AND deleted = false
LIMIT 1
@@ -2741,7 +2746,7 @@ if (existingRecords.isNotEmpty()) {
"shopAddress" to buildShopAddress(shop),
"shopPoNo" to (supplier?.code ?: ""),
"numberOfCartons" to (po.pickOrderLines.size),
"truckNo" to (truckInfo?.get("truckNo") ?: ""), // ✅ Add truck number
"TruckLanceCode" to (truckInfo?.get("TruckLanceCode") ?: ""), // ✅ Add truck number
"DepartureTime" to (truckInfo?.get("DepartureTime") ?: ""), // ✅ Add departure time
"qrCodeData" to (po.id ?: 0L)
)
@@ -2767,10 +2772,7 @@ if (existingRecords.isNotEmpty()) {
println("❌ Pick order not found with ID: $pickOrderId")
return emptyList()
}
if (doPickOrderRepository.findByPickOrderId(pickOrderId).firstOrNull()?.hide == true) {
println("🔍 Pick order $pickOrderId is hidden, returning empty list")
return emptyList()
}
println("🔍 Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}")
if (pickOrder.type?.value != "do") {
@@ -2801,14 +2803,14 @@ if (existingRecords.isNotEmpty()) {
val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id)
println("🔍 Trucks for shop ${shop.id}: ${trucksForShop.size}")
trucksForShop.forEach { t ->
println(" - Truck ID: ${t.id}, TruckNo: ${t.truckNo}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}")
println(" - Truck ID: ${t.id}, truckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}")
}
// Take the first truck (or null if none found)
val selectedTruck = trucksForShop.firstOrNull()
if (selectedTruck != null) {
println("✅ Selected truck: ID=${selectedTruck.id}, TruckNo=${selectedTruck.truckNo}, DepartureTime=${selectedTruck.departureTime}")
println("✅ Selected truck: ID=${selectedTruck.id}, truckLanceCode=${selectedTruck.truckLanceCode}, DepartureTime=${selectedTruck.departureTime}")
} else {
println("❌ No truck found for shopId ${shop.id}")
}
@@ -2854,7 +2856,7 @@ if (existingRecords.isNotEmpty()) {
"shopAddress" to buildShopAddress(shop),
"shopPoNo" to (supplier?.code ?: ""),
"numberOfCartons" to (pickOrder.pickOrderLines.size),
"truckNo" to (truck?.truckNo ?: ""), // ✅ Use entity property
"truckLanceCode" to (truck?.truckLanceCode ?: ""), // ✅ Use entity property
"DepartureTime" to (truck?.departureTime?.toString() ?: ""),
"ticketNo" to ticketNo,
"storeId" to dpoStoreId,
@@ -2880,10 +2882,7 @@ if (existingRecords.isNotEmpty()) {
println("❌ Pick order not found with ID: $pickOrderId")
return emptyList()
}
if (doPickOrderRepository.findByPickOrderId(pickOrderId).firstOrNull()?.hide == true) {
println("🔍 Pick order $pickOrderId is hidden, returning empty list")
return emptyList()
}
println("🔍 Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}")
if (pickOrder.type?.value != "do") {
@@ -2914,14 +2913,14 @@ if (existingRecords.isNotEmpty()) {
val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id)
println("🔍 Trucks for shop ${shop.id}: ${trucksForShop.size}")
trucksForShop.forEach { t ->
println(" - Truck ID: ${t.id}, TruckNo: ${t.truckNo}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}")
println(" - Truck ID: ${t.id}, TruckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}")
}
// Take the first truck (or null if none found)
val selectedTruck = trucksForShop.firstOrNull()
if (selectedTruck != null) {
println("✅ Selected truck: ID=${selectedTruck.id}, TruckNo=${selectedTruck.truckNo}, DepartureTime=${selectedTruck.departureTime}")
println("✅ Selected truck: ID=${selectedTruck.id}, TruckLanceCode=${selectedTruck.truckLanceCode}, DepartureTime=${selectedTruck.departureTime}")
} else {
println("❌ No truck found for shopId ${shop.id}")
}
@@ -2967,7 +2966,7 @@ if (existingRecords.isNotEmpty()) {
"shopAddress" to buildShopAddress(shop),
"shopPoNo" to (supplier?.code ?: ""),
"numberOfCartons" to (pickOrder.pickOrderLines.size),
"truckNo" to (truck?.truckNo ?: ""), // ✅ Use entity property
"TruckLanceCode" to (truck?.truckLanceCode ?: ""), // ✅ Use entity property
"DepartureTime" to (truck?.departureTime?.toString() ?: ""),
"ticketNo" to ticketNo,
"storeId" to dpoStoreId,
@@ -3093,16 +3092,18 @@ open fun getAllPickOrderLotsWithDetailsWithoutAutoAssign(userId: Long): List<Map
w.name as location,
COALESCE(uc.udfudesc, 'N/A') as stockUnit,
-- Router Information
-- Router Information
r.id as routerId,
r.index as routerIndex,
r.route as routerRoute,
ro.`order` as routerIndex,
CONCAT(COALESCE(ro.route_area, ''), COALESCE(r.route, '')) as routerRoute,
ro.route_area as routerArea,


-- ✅ FIXED: Set quantities to NULL for rejected lots
CASE
WHEN sol.status = 'rejected' THEN NULL
ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0))
END as availableQty,
WHEN sol.status = 'rejected' THEN NULL
ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0))
END as availableQty,
-- Required quantity for this lot
COALESCE(spl.qty, 0) as requiredQty,
@@ -3168,31 +3169,32 @@ open fun getAllPickOrderLotsWithDetailsWithoutAutoAssign(userId: Long): List<Map
END as processingStatus
FROM fpsmsdb.pick_order po
JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id
JOIN fpsmsdb.items i ON i.id = pol.itemId
LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = pol.uomId
LEFT JOIN fpsmsdb.suggested_pick_lot spl ON pol.id = spl.pickOrderLineId

LEFT JOIN fpsmsdb.inventory_lot_line ill ON spl.suggestedLotLineId = ill.id
LEFT JOIN fpsmsdb.router r ON r.inventoryLotId = ill.id AND r.deleted = false
LEFT JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId
LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId
LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ill.id AND sol.deleted = false
WHERE po.deleted = false
AND po.id IN ($pickOrderIdsStr)
AND pol.deleted = false
AND po.status IN ('PENDING', 'RELEASED', 'COMPLETED')
AND po.assignTo = :userId
AND ill.deleted = false
AND il.deleted = false
AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL)
ORDER BY
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END, -- Show rejected lots first
COALESCE(r.index, 0) ASC,
po.code ASC,
i.code ASC,
il.expiryDate ASC,
il.lotNo ASC
JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id
JOIN fpsmsdb.items i ON i.id = pol.itemId
LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = pol.uomId
LEFT JOIN fpsmsdb.suggested_pick_lot spl ON pol.id = spl.pickOrderLineId
LEFT JOIN fpsmsdb.inventory_lot_line ill ON spl.suggestedLotLineId = ill.id
LEFT JOIN fpsmsdb.router r ON r.inventoryLotId = ill.id AND r.deleted = false
LEFT JOIN fpsmsdb.router_order ro ON r.router_id = ro.id
LEFT JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId
LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId
LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ill.id AND sol.deleted = false
WHERE po.deleted = false
AND po.id IN ($pickOrderIdsStr)
AND pol.deleted = false
AND po.status IN ('PENDING', 'RELEASED', 'COMPLETED')
AND po.assignTo = :userId
AND ill.deleted = false
AND il.deleted = false
AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL)
ORDER BY
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END,
COALESCE(ro.`order`, 999999) ASC,
COALESCE(r.route, 999999) ASC,
po.code ASC,
i.code ASC,
il.expiryDate ASC,
il.lotNo ASC
""".trimIndent()
println("🔍 Executing SQL for all pick order lots with details (no auto-assign): $sql")
@@ -3219,13 +3221,13 @@ open fun getAllPickOrderLotsWithDetailsWithoutAutoAssign(userId: Long): List<Map
val router = routerRepository.findFirstByInventoryLotIdAndDeletedFalse(inventoryLotId.toInt())
if (router != null) {
mapOf(
"routerIndex" to (router.index ?: 0),
"routerRoute" to (router.route ?: ""),
"routerArea" to (router.area ?: ""),
"routerItemCode" to (router.itemCode ?: 0),
"routerItemName" to (router.itemName ?: ""),
"routerUomId" to (router.uomId ?: 0),
"routerNoofCarton" to (router.noofCarton ?: 0)
)
} else {
mapOf(
@@ -3295,12 +3297,9 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A
).filter { it.deliveryOrder != null } // Only pick orders with doId
println("🔍 DEBUG: Found ${allAssignedPickOrders.size} pick orders assigned to user $userId")
val visiblePickOrders = allAssignedPickOrders.filter { pickOrder ->
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrder.id!!)
doPickOrders.none { it.hide } // 只显示 hide = false 的订单
}

// ✅ NEW LOGIC: Filter based on assignment and status
val filteredPickOrders = if (visiblePickOrders.isNotEmpty()) {
val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) {
// Check if there are any RELEASED orders assigned to this user (active work)
val assignedReleasedOrders = allAssignedPickOrders.filter {
it.status == PickOrderStatus.RELEASED && it.assignTo?.id == userId
@@ -3315,7 +3314,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A
val completedOrders = allAssignedPickOrders.filter { it.status == PickOrderStatus.COMPLETED }
if (completedOrders.isNotEmpty()) {
val latestCompleted = completedOrders.maxByOrNull { it.completeDate ?: it.modified ?: LocalDateTime.MIN }
println(" DEBUG: No assigned RELEASED orders, showing latest completed order: ${latestCompleted?.code}")
println("🔍 DEBUG: No assigned RELEASED orders, showing latest completed order: ${latestCompleted?.code}")
listOfNotNull(latestCompleted)
} else {
println("🔍 DEBUG: No orders found")
@@ -3372,9 +3371,9 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A
-- Router Information
r.id as routerId,
r.index as routerIndex,
r.route as routerRoute,
r.area as routerArea,
ro.`order` as routerIndex,
CONCAT(COALESCE(ro.route_area, ''), COALESCE(r.route, '')) as routerRoute,
ro.route_area as routerArea,
-- ✅ FIXED: Set quantities to NULL for rejected lots
CASE
@@ -3455,7 +3454,8 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A
ON sol.pickOrderLineId = pol.id AND sol.inventoryLotLineId = ll.lotLineId AND sol.deleted = false

LEFT JOIN fpsmsdb.inventory_lot_line ill ON ill.id = ll.lotLineId
LEFT JOIN fpsmsdb.router r ON r.inventoryLotId = ill.id AND r.deleted = false
LEFT JOIN router r ON r.inventoryLotId = ill.inventoryLotId AND r.deleted = false
LEFT JOIN router_order ro ON r.router_id = ro.id
LEFT JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId
LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId

@@ -3470,7 +3470,8 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A
AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL)
ORDER BY
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END,
COALESCE(r.index, 0) ASC,
COALESCE(ro.`order`, 999999) ASC,
COALESCE(r.route, 999999) ASC,
po.code ASC,
i.code ASC,
il.expiryDate ASC,
@@ -3807,48 +3808,7 @@ open fun confirmLotSubstitution(req: LotSubstitutionConfirmRequest): MessageResp
errorPosition = null
)
}
open fun updateDoPickOrderHideStatus(pickOrderId: Long, hide: Boolean): MessageResponse {
return try {
// ✅ 修复:根据 pickOrderId 查找 do_pick_order 记录
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
if (doPickOrders.isEmpty()) {
MessageResponse(
id = null,
name = "Pick order not found",
code = "ERROR",
type = "pickorder",
message = "No do_pick_order found for pickOrderId $pickOrderId",
errorPosition = "pickOrderId"
)
} else {
// ✅ 更新所有相关的 do_pick_order 记录
doPickOrders.forEach { doPickOrder ->
doPickOrder.hide = hide
doPickOrderRepository.save(doPickOrder)
}
MessageResponse(
id = null,
name = "Hide status updated",
code = "SUCCESS",
type = "pickorder",
message = "Updated hide status for ${doPickOrders.size} do_pick_order records to $hide",
errorPosition = null
)
}
} catch (e: Exception) {
println("❌ Error in updateDoPickOrderHideStatus: ${e.message}")
e.printStackTrace()
MessageResponse(
id = null,
name = "Failed to update hide status",
code = "ERROR",
type = "pickorder",
message = "Failed to update hide status: ${e.message}",
errorPosition = null
)
}
}

open fun getCompletedDoPickOrders(
userId: Long,
pickOrderCode: String?,
@@ -3914,7 +3874,7 @@ open fun getCompletedDoPickOrders(
"ticketNo" to firstFgOrder["ticketNo"],
"shopPoNo" to firstFgOrder["shopPoNo"],
"numberOfCartons" to firstFgOrder["numberOfCartons"],
"truckNo" to firstFgOrder["truckNo"],
"TruckLanceCode" to firstFgOrder["TruckLanceCode"],
"storeId" to firstFgOrder["storeId"],
"completedDate" to (pickOrder.completeDate?.toString() ?: pickOrder.modified?.toString()),
"fgPickOrders" to fgPickOrders
@@ -3990,8 +3950,9 @@ open fun getLotDetailsByPickOrderId(pickOrderId: Long): List<Map<String, Any>> {
-- Router Information
r.id as routerId,
r.index as routerIndex,
r.route as routerRoute,
ro.`order` as routerIndex,
CONCAT(COALESCE(ro.route_area, ''), COALESCE(r.route, '')) as routerRoute,

-- Set quantities to NULL for rejected lots
CASE
@@ -4080,7 +4041,8 @@ open fun getLotDetailsByPickOrderId(pickOrderId: Long): List<Map<String, Any>> {
AND (spl.pickOrderLineId IS NOT NULL OR sol.pickOrderLineId IS NOT NULL)
ORDER BY
CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END, -- Show rejected lots first
COALESCE(r.index, 0) ASC,
COALESCE(ro.`order`, 999999) ASC,
COALESCE(r.route, 999999) ASC,
po.code ASC,
i.code ASC,
il.expiryDate ASC,


+ 1
- 7
src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt View File

@@ -287,13 +287,7 @@ fun getPickOrdersByStore(@PathVariable storeId: String): Map<String, Any?> {
fun confirmLotSubstitution(@RequestBody req: LotSubstitutionConfirmRequest): MessageResponse {
return pickOrderService.confirmLotSubstitution(req)
}
@PostMapping("/update-hide-status/{pickOrderId}")
fun updatePickOrderHideStatus(
@PathVariable pickOrderId: Long,
@RequestParam hide: Boolean
): MessageResponse {
return pickOrderService.updateDoPickOrderHideStatus(pickOrderId, hide)
}

@GetMapping("/completed-do-pick-orders/{userId}")
fun getCompletedDoPickOrders(
@PathVariable userId: Long,


+ 27
- 0
src/main/resources/db/changelog/changes/202511005_01_enson/01_altertable_enson.sql View File

@@ -0,0 +1,27 @@
--liquibase formatted sql

--changeset enson:update

CREATE TABLE router_order (
id int AUTO_INCREMENT PRIMARY KEY,
route_area varchar(255),
`order` int,
created datetime DEFAULT CURRENT_TIMESTAMP,
createdBy varchar(30),
version int DEFAULT 1,
modified datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
modifiedBy varchar(30),
deleted tinyint(1) DEFAULT 0
);
ALTER TABLE router MODIFY COLUMN route VARCHAR(50) NULL;
-- Clear route data first (separate statement)
UPDATE router SET route = NULL WHERE route IS NOT NULL;

-- All ALTER TABLE operations in one statement
ALTER TABLE router
ADD COLUMN router_id int,
ADD FOREIGN KEY (router_id) REFERENCES router_order(id),
CHANGE COLUMN `route` `route` INT NULL,
DROP COLUMN `index`,
DROP COLUMN area,
DROP COLUMN noofCarton;

+ 68
- 0
src/main/resources/db/changelog/changes/202511005_01_enson/02_altertable_enson.sql View File

@@ -0,0 +1,68 @@
--liquibase formatted sql

--changeset enson:update

ALTER TABLE truck
CHANGE COLUMN truckNo TruckLanceCode VARCHAR(50);

-- Add new columns to truck
ALTER TABLE truck
ADD COLUMN ShopName VARCHAR(255),
ADD COLUMN ShopCode VARCHAR(50),
ADD COLUMN LoadingSequence INT,
ADD COLUMN Store_id INT;

-- Drop columns from truck
ALTER TABLE truck
DROP COLUMN capacity,
DROP COLUMN status,
DROP COLUMN truckName;

-- ==========================================
-- 2. Modify do_pick_order table
-- ==========================================

-- Add new columns to do_pick_order
ALTER TABLE do_pick_order
ADD COLUMN ticketCompleteDateTime DATETIME,
ADD COLUMN TruckLanceCode VARCHAR(50),
ADD COLUMN ShopCode VARCHAR(50),
ADD COLUMN ShopName VARCHAR(255),
ADD COLUMN RequiredDeliveryDate DATE;

-- Drop foreign key constraints first
ALTER TABLE do_pick_order
DROP FOREIGN KEY FK_DO_PICK_ORDER_ON_ITEM;

ALTER TABLE do_pick_order
DROP FOREIGN KEY FK_DO_PICK_ORDER_ON_SHOP_PO_SUPPLIER;

-- Drop columns from do_pick_order
ALTER TABLE do_pick_order
DROP COLUMN item_id,
DROP COLUMN shop_po_supplier_id,
DROP COLUMN hide;

-- ==========================================
-- 3. Modify do_pick_order_record table
-- ==========================================

-- Add new columns to do_pick_order_record
ALTER TABLE do_pick_order_record
ADD COLUMN ticketCompleteDateTime DATETIME,
ADD COLUMN TruckLanceCode VARCHAR(50),
ADD COLUMN ShopCode VARCHAR(50),
ADD COLUMN ShopName VARCHAR(255),
ADD COLUMN RequiredDeliveryDate DATE;

-- Drop foreign key constraints for do_pick_order_record
ALTER TABLE do_pick_order_record
DROP FOREIGN KEY FK_DO_PICK_ORDER_REC_ON_ITEM;

ALTER TABLE do_pick_order_record
DROP FOREIGN KEY FK_DO_PICK_ORDER_REC_ON_SHOP_PO_SUPPLIER;

-- Drop columns from do_pick_order_record
ALTER TABLE do_pick_order_record
DROP COLUMN item_id,
DROP COLUMN shop_po_supplier_id;

Loading…
Cancel
Save