CANCERYS\kw093 3 недель назад
Родитель
Сommit
47c2bf8a8a
14 измененных файлов: 428 добавлений и 276 удалений
  1. +19
    -19
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
  2. +11
    -11
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderAssignmentService.kt
  3. +8
    -8
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderQueryService.kt
  4. +25
    -25
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt
  5. +10
    -10
      src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt
  6. +74
    -74
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
  7. +7
    -7
      src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt
  8. +4
    -4
      src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt
  9. +7
    -0
      src/main/java/com/ffii/fpsms/modules/stock/entity/InventoryLotLineRepository.kt
  10. +3
    -0
      src/main/java/com/ffii/fpsms/modules/stock/entity/StockInLine.kt
  11. +3
    -0
      src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLine.kt
  12. +237
    -117
      src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt
  13. +12
    -1
      src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt
  14. +8
    -0
      src/main/resources/db/changelog/changes/20260109_enson/01_alter_table.sql

+ 19
- 19
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt Просмотреть файл

@@ -436,7 +436,7 @@ open class DeliveryOrderService(
) )


val createdPickOrder = pickOrderService.create(po) val createdPickOrder = pickOrderService.create(po)
println("🔍 DEBUG: Created pick order - ID: ${createdPickOrder.id}")
println(" DEBUG: Created pick order - ID: ${createdPickOrder.id}")


val consoCode = pickOrderService.assignConsoCode() val consoCode = pickOrderService.assignConsoCode()
val pickOrderEntity = pickOrderRepository.findById(createdPickOrder.id!!).orElse(null) val pickOrderEntity = pickOrderRepository.findById(createdPickOrder.id!!).orElse(null)
@@ -450,7 +450,7 @@ open class DeliveryOrderService(
// Debug: Check pick order lines // Debug: Check pick order lines
println("�� DEBUG: Pick order has ${pickOrderEntity.pickOrderLines?.size ?: 0} pick order lines") println("�� DEBUG: Pick order has ${pickOrderEntity.pickOrderLines?.size ?: 0} pick order lines")
pickOrderEntity.pickOrderLines?.forEach { line -> pickOrderEntity.pickOrderLines?.forEach { line ->
println("🔍 DEBUG: Pick order line - Item ID: ${line.item?.id}, Qty: ${line.qty}")
println(" DEBUG: Pick order line - Item ID: ${line.item?.id}, Qty: ${line.qty}")
} }




@@ -460,7 +460,7 @@ open class DeliveryOrderService(
) )


val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList)
println("🔍 DEBUG: Saved ${saveSuggestedPickLots.size} suggested pick lots")
println(" DEBUG: Saved ${saveSuggestedPickLots.size} suggested pick lots")
val insufficientCount = suggestions.suggestedList.count { it.suggestedLotLine == null } val insufficientCount = suggestions.suggestedList.count { it.suggestedLotLine == null }
if (insufficientCount > 0) { if (insufficientCount > 0) {
println("⚠️ WARNING: $insufficientCount items have insufficient stock (issues auto-created)") println("⚠️ WARNING: $insufficientCount items have insufficient stock (issues auto-created)")
@@ -525,11 +525,11 @@ open class DeliveryOrderService(
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now() val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"))


println("🔍 DEBUG: Target date: $targetDate, Date prefix: $datePrefix")
println(" DEBUG: Target date: $targetDate, Date prefix: $datePrefix")
val truck = deliveryOrder.shop?.id?.let { shopId -> val truck = deliveryOrder.shop?.id?.let { shopId ->
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
println(" DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
println(" DEBUG: Found ${trucks.size} trucks for shop $shopId")


// 移除提前返回,总是分析 items 分布 // 移除提前返回,总是分析 items 分布
// 分析 DO order lines 中的 items 分布 // 分析 DO order lines 中的 items 分布
@@ -553,8 +553,8 @@ open class DeliveryOrderService(
floorItemCount[row["floor"] as? String ?: "Other"] = (row["item_count"] as? Number)?.toInt() ?: 0 floorItemCount[row["floor"] as? String ?: "Other"] = (row["item_count"] as? Number)?.toInt() ?: 0
} }


println("🔍 DEBUG: Floor item count distribution: $floorItemCount")
println("🔍 DEBUG: Total items: ${itemIds.size}, Items on 4F: ${floorItemCount["4F"] ?: 0}")
println(" DEBUG: Floor item count distribution: $floorItemCount")
println(" DEBUG: Total items: ${itemIds.size}, Items on 4F: ${floorItemCount["4F"] ?: 0}")


// 新逻辑:只有所有 items 都在 4F,才算 4F,否则算 2F // 新逻辑:只有所有 items 都在 4F,才算 4F,否则算 2F
val preferredFloor = if ((floorItemCount["4F"] ?: 0) == itemIds.size && (floorItemCount["2F"] ?: 0) == 0) { val preferredFloor = if ((floorItemCount["4F"] ?: 0) == itemIds.size && (floorItemCount["2F"] ?: 0) == 0) {
@@ -563,13 +563,13 @@ open class DeliveryOrderService(
"2F" // 只要有任何 item 不在 4F,就算 2F "2F" // 只要有任何 item 不在 4F,就算 2F
} }


println("🔍 DEBUG: Preferred floor: $preferredFloor (All items on 4F: ${preferredFloor == "4F"})")
println(" DEBUG: Preferred floor: $preferredFloor (All items on 4F: ${preferredFloor == "4F"})")


// 查找 truck // 查找 truck
val truck = deliveryOrder.shop?.id?.let { shopId -> val truck = deliveryOrder.shop?.id?.let { shopId ->
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
println(" DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
println(" DEBUG: Found ${trucks.size} trucks for shop $shopId")




val preferredStoreId = when (preferredFloor) { val preferredStoreId = when (preferredFloor) {
@@ -586,7 +586,7 @@ open class DeliveryOrderService(
trucks.firstOrNull() trucks.firstOrNull()
} }


println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, StoreId=${selectedTruck?.storeId}")
println(" DEBUG: Selected truck: ID=${selectedTruck?.id}, StoreId=${selectedTruck?.storeId}")
selectedTruck selectedTruck
} }


@@ -612,7 +612,7 @@ open class DeliveryOrderService(
val storeId = "$preferredFloor/F" val storeId = "$preferredFloor/F"
val loadingSequence = truck.loadingSequence ?: 999 val loadingSequence = truck.loadingSequence ?: 999


println("🔍 DEBUG: Creating DoPickOrder - Floor: $preferredFloor, Store: $storeId, Truck: ${truck.id}")
println(" DEBUG: Creating DoPickOrder - Floor: $preferredFloor, Store: $storeId, Truck: ${truck.id}")


val doPickOrder = DoPickOrder( val doPickOrder = DoPickOrder(
storeId = storeId, storeId = storeId,
@@ -635,7 +635,7 @@ open class DeliveryOrderService(
) )


val savedDoPickOrder = doPickOrderService.save(doPickOrder) val savedDoPickOrder = doPickOrderService.save(doPickOrder)
println("🔍 DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}")
println(" DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}")
truck truck
} }
return MessageResponse( return MessageResponse(
@@ -1084,7 +1084,7 @@ open class DeliveryOrderService(


@Transactional(rollbackFor = [Exception::class]) @Transactional(rollbackFor = [Exception::class])
open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDoResult { open fun releaseDeliveryOrderWithoutTicket(request: ReleaseDoRequest): ReleaseDoResult {
println("🔍 DEBUG: Starting releaseDeliveryOrderWithoutTicket for DO ID: ${request.id}")
println(" DEBUG: Starting releaseDeliveryOrderWithoutTicket for DO ID: ${request.id}")


val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.id) val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.id)
?: throw NoSuchElementException("Delivery Order not found") ?: throw NoSuchElementException("Delivery Order not found")
@@ -1233,7 +1233,7 @@ open class DeliveryOrderService(
else -> "2F" // 默认 2F else -> "2F" // 默认 2F
} }


println("🔍 DEBUG: Floor calculation for DO ${deliveryOrder.id}")
println(" DEBUG: Floor calculation for DO ${deliveryOrder.id}")
println(" - Total items: ${itemIds.size}") println(" - Total items: ${itemIds.size}")
println(" - Items with store_id: $totalItemsWithStoreId") println(" - Items with store_id: $totalItemsWithStoreId")
println(" - Items without store_id: ${itemIds.size - totalItemsWithStoreId}") println(" - Items without store_id: ${itemIds.size - totalItemsWithStoreId}")
@@ -1274,15 +1274,15 @@ open class DeliveryOrderService(
java.time.DayOfWeek.SUNDAY -> "Sun" java.time.DayOfWeek.SUNDAY -> "Sun"
} }


println("🔍 DEBUG: DO ${deliveryOrder.id} - Target date: $targetDate ($dayAbbr), Shop: $shopId")
println("🔍 DEBUG: Found ${matchedTrucks.size} matched 4F trucks")
println(" DEBUG: DO ${deliveryOrder.id} - Target date: $targetDate ($dayAbbr), Shop: $shopId")
println(" DEBUG: Found ${matchedTrucks.size} matched 4F trucks")




val dayMatchedTrucks = matchedTrucks.filter { val dayMatchedTrucks = matchedTrucks.filter {
it.truckLanceCode?.contains(dayAbbr, ignoreCase = true) == true it.truckLanceCode?.contains(dayAbbr, ignoreCase = true) == true
} }


println("🔍 DEBUG: Found ${dayMatchedTrucks.size} trucks matching $dayAbbr")
println(" DEBUG: Found ${dayMatchedTrucks.size} trucks matching $dayAbbr")
dayMatchedTrucks.forEach { t -> dayMatchedTrucks.forEach { t ->
println(" - Truck ID=${t.id}, Code=${t.truckLanceCode}, Time=${t.departureTime}") println(" - Truck ID=${t.id}, Code=${t.truckLanceCode}, Time=${t.departureTime}")
} }


+ 11
- 11
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderAssignmentService.kt Просмотреть файл

@@ -36,22 +36,22 @@ class DoPickOrderAssignmentService(
"4/F" -> "4/F" "4/F" -> "4/F"
else -> request.storeId else -> request.storeId
} }
println("🔍 DEBUG: assignByLane - Converting storeId from '${request.storeId}' to '$actualStoreId'")
println(" DEBUG: assignByLane - Converting storeId from '${request.storeId}' to '$actualStoreId'")
// 获取日期(如果提供) // 获取日期(如果提供)
val requiredDate = request.requiredDate val requiredDate = request.requiredDate
println("🔍 DEBUG: assignByLane - Requested date: $requiredDate")
println(" DEBUG: assignByLane - Requested date: $requiredDate")
// 根据是否有日期参数选择不同的查询方法 // 根据是否有日期参数选择不同的查询方法
val allCandidates = if (requiredDate != null) { val allCandidates = if (requiredDate != null) {
println("🔍 DEBUG: Filtering by date: $requiredDate")
println(" DEBUG: Filtering by date: $requiredDate")
doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn( doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
actualStoreId, actualStoreId,
requiredDate, requiredDate,
listOf(DoPickOrderStatus.pending) listOf(DoPickOrderStatus.pending)
) )
} else { } else {
println("🔍 DEBUG: No date filter applied")
println(" DEBUG: No date filter applied")
doPickOrderRepository.findByStoreIdAndTicketStatusOrderByTruckDepartureTimeAsc( doPickOrderRepository.findByStoreIdAndTicketStatusOrderByTruckDepartureTimeAsc(
actualStoreId, actualStoreId,
DoPickOrderStatus.pending DoPickOrderStatus.pending
@@ -60,18 +60,18 @@ class DoPickOrderAssignmentService(
.filter { it.truckLanceCode == request.truckLanceCode } .filter { it.truckLanceCode == request.truckLanceCode }
.sortedBy { it.truckDepartureTime } .sortedBy { it.truckDepartureTime }
println("🔍 DEBUG: Found ${allCandidates.size} candidate do_pick_orders for lane ${request.truckLanceCode}")
println(" DEBUG: Found ${allCandidates.size} candidate do_pick_orders for lane ${request.truckLanceCode}")
// 过滤掉所有 pick orders 都是 issue 的记录 // 过滤掉所有 pick orders 都是 issue 的记录
val filteredCandidates = allCandidates.filter { doPickOrder -> val filteredCandidates = allCandidates.filter { doPickOrder ->
val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!) val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!)
if (!hasNonIssueLines) { if (!hasNonIssueLines) {
println("🔍 DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues")
println(" DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues")
} }
hasNonIssueLines hasNonIssueLines
} }
println("🔍 DEBUG: After filtering, ${filteredCandidates.size} do_pick_orders remain")
println(" DEBUG: After filtering, ${filteredCandidates.size} do_pick_orders remain")
if (filteredCandidates.isEmpty()) { if (filteredCandidates.isEmpty()) {
return MessageResponse( return MessageResponse(
@@ -92,7 +92,7 @@ class DoPickOrderAssignmentService(
// 获取这个 do_pick_order 下的所有 pick orders 并分配给用户 // 获取这个 do_pick_order 下的所有 pick orders 并分配给用户
val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(firstOrder.id!!) val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(firstOrder.id!!)
println("🔍 DEBUG: Found ${doPickOrderLines.size} pick orders in do_pick_order ${firstOrder.id}")
println(" DEBUG: Found ${doPickOrderLines.size} pick orders in do_pick_order ${firstOrder.id}")
doPickOrderLines.forEach { line -> doPickOrderLines.forEach { line ->
if (line.pickOrderId != null) { if (line.pickOrderId != null) {
@@ -101,7 +101,7 @@ class DoPickOrderAssignmentService(
pickOrder.assignTo = user pickOrder.assignTo = user
pickOrder.status = PickOrderStatus.RELEASED pickOrder.status = PickOrderStatus.RELEASED
pickOrderRepository.save(pickOrder) pickOrderRepository.save(pickOrder)
println("🔍 DEBUG: Assigned pick order ${line.pickOrderId} to user ${request.userId}")
println(" DEBUG: Assigned pick order ${line.pickOrderId} to user ${request.userId}")
} else { } else {
println("⚠️ WARNING: Pick order ${line.pickOrderId} not found") println("⚠️ WARNING: Pick order ${line.pickOrderId} not found")
} }
@@ -120,7 +120,7 @@ class DoPickOrderAssignmentService(
} }
if (records.isNotEmpty()) { if (records.isNotEmpty()) {
doPickOrderRecordRepository.saveAll(records) doPickOrderRecordRepository.saveAll(records)
println("🔍 DEBUG: Updated ${records.size} do_pick_order_record for pick order ${line.pickOrderId}")
println(" DEBUG: Updated ${records.size} do_pick_order_record for pick order ${line.pickOrderId}")
} }
} }
} }
@@ -171,7 +171,7 @@ class DoPickOrderAssignmentService(
val hasNonIssueLines = nonIssueLines > 0 val hasNonIssueLines = nonIssueLines > 0
println("🔍 DEBUG: DoPickOrder $doPickOrderId - Total lines: $totalLines, Non-issue lines: $nonIssueLines, Has non-issue lines: $hasNonIssueLines")
println(" DEBUG: DoPickOrder $doPickOrderId - Total lines: $totalLines, Non-issue lines: $nonIssueLines, Has non-issue lines: $hasNonIssueLines")
hasNonIssueLines hasNonIssueLines


+ 8
- 8
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderQueryService.kt Просмотреть файл

@@ -20,7 +20,7 @@ class DoPickOrderQueryService(
fun getSummaryByStore(storeId: String, requiredDate: LocalDate?, releaseType: String): StoreLaneSummary { fun getSummaryByStore(storeId: String, requiredDate: LocalDate?, releaseType: String): StoreLaneSummary {
val targetDate = requiredDate ?: LocalDate.now() val targetDate = requiredDate ?: LocalDate.now()
println("🔍 DEBUG: Getting summary for store=$storeId, date=$targetDate, releaseType=$releaseType")
println(" DEBUG: Getting summary for store=$storeId, date=$targetDate, releaseType=$releaseType")
val actualStoreId = when (storeId) { val actualStoreId = when (storeId) {
"2/F" -> "2/F" "2/F" -> "2/F"
@@ -56,16 +56,16 @@ class DoPickOrderQueryService(
else -> completedRecords // "all" 或其他值,不过滤 else -> completedRecords // "all" 或其他值,不过滤
} }
println("🔍 DEBUG: Found ${activeRecords.size} active records for date $targetDate")
println("🔍 DEBUG: After releaseType filter: ${filteredActiveRecordsByReleaseType.size} active records")
println("🔍 DEBUG: Found ${completedRecords.size} completed records for date $targetDate")
println("🔍 DEBUG: After releaseType filter: ${filteredCompletedRecordsByReleaseType.size} completed records")
println(" DEBUG: Found ${activeRecords.size} active records for date $targetDate")
println(" DEBUG: After releaseType filter: ${filteredActiveRecordsByReleaseType.size} active records")
println(" DEBUG: Found ${completedRecords.size} completed records for date $targetDate")
println(" DEBUG: After releaseType filter: ${filteredCompletedRecordsByReleaseType.size} completed records")
// Filter active records (check for non-issue lines) // Filter active records (check for non-issue lines)
val filteredActiveRecords = filteredActiveRecordsByReleaseType.filter { doPickOrder -> val filteredActiveRecords = filteredActiveRecordsByReleaseType.filter { doPickOrder ->
val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!) val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!)
if (!hasNonIssueLines) { if (!hasNonIssueLines) {
println("🔍 DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues")
println(" DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues")
} }
hasNonIssueLines hasNonIssueLines
} }
@@ -74,7 +74,7 @@ class DoPickOrderQueryService(
val filteredCompletedRecords = filteredCompletedRecordsByReleaseType.filter { record -> val filteredCompletedRecords = filteredCompletedRecordsByReleaseType.filter { record ->
val hasNonIssueLines = checkDoPickOrderRecordHasNonIssueLines(record.id!!) val hasNonIssueLines = checkDoPickOrderRecordHasNonIssueLines(record.id!!)
if (!hasNonIssueLines) { if (!hasNonIssueLines) {
println("🔍 DEBUG: Filtering out DoPickOrderRecord ${record.id} - all lines are issues")
println(" DEBUG: Filtering out DoPickOrderRecord ${record.id} - all lines are issues")
} }
hasNonIssueLines hasNonIssueLines
} }
@@ -95,7 +95,7 @@ class DoPickOrderQueryService(
) )
} }
println("🔍 DEBUG: After filtering, ${allRecords.size} records remain (${filteredActiveRecords.size} active + ${filteredCompletedRecords.size} completed)")
println(" DEBUG: After filtering, ${allRecords.size} records remain (${filteredActiveRecords.size} active + ${filteredCompletedRecords.size} completed)")
val grouped = allRecords.groupBy { it.truckDepartureTime to it.truckLanceCode } val grouped = allRecords.groupBy { it.truckDepartureTime to it.truckLanceCode }
.mapValues { (_, list) -> .mapValues { (_, list) ->


+ 25
- 25
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt Просмотреть файл

@@ -264,8 +264,8 @@ class DoReleaseCoordinatorService(


private fun getOrderedDeliveryOrderIds(ids: List<Long>): List<Long> { private fun getOrderedDeliveryOrderIds(ids: List<Long>): List<Long> {
try { try {
println("🔍 DEBUG: Getting ordered IDs for ${ids.size} orders")
println("🔍 DEBUG: First 5 IDs: ${ids.take(5)}")
println(" DEBUG: Getting ordered IDs for ${ids.size} orders")
println(" DEBUG: First 5 IDs: ${ids.take(5)}")
val dayOfWeekSql = getDayOfWeekAbbrSql("do.estimatedArrivalDate") val dayOfWeekSql = getDayOfWeekAbbrSql("do.estimatedArrivalDate")
val sql = """ val sql = """
WITH DoFloorCounts AS ( WITH DoFloorCounts AS (
@@ -470,24 +470,24 @@ class DoReleaseCoordinatorService(
""".trimIndent() """.trimIndent()
println("🔍 DEBUG: SQL length: ${sql.length} characters")
println("🔍 DEBUG: SQL first 500 chars: ${sql.take(500)}")
println(" DEBUG: SQL length: ${sql.length} characters")
println(" DEBUG: SQL first 500 chars: ${sql.take(500)}")
val results = jdbcDao.queryForList(sql) val results = jdbcDao.queryForList(sql)
println("🔍 DEBUG: Results type: ${results.javaClass.name}")
println("🔍 DEBUG: Results size: ${results.size}")
println(" DEBUG: Results type: ${results.javaClass.name}")
println(" DEBUG: Results size: ${results.size}")
if (results.isNotEmpty()) { if (results.isNotEmpty()) {
println("🔍 DEBUG: First result keys: ${results[0].keys}")
println("🔍 DEBUG: First result: ${results[0]}")
println(" DEBUG: First result keys: ${results[0].keys}")
println(" DEBUG: First result: ${results[0]}")
} }
val sortedIds = results.mapNotNull { row -> val sortedIds = results.mapNotNull { row ->
(row["id"] as? Number)?.toLong() (row["id"] as? Number)?.toLong()
} }
println("🔍 DEBUG: Query returned ${sortedIds.size} sorted IDs")
println("🔍 DEBUG: First 10 sorted IDs: ${sortedIds.take(10)}")
println(" DEBUG: Query returned ${sortedIds.size} sorted IDs")
println(" DEBUG: First 10 sorted IDs: ${sortedIds.take(10)}")
return if (sortedIds.isEmpty()) { return if (sortedIds.isEmpty()) {
println("⚠️ WARNING: No sorted IDs, using original order") println("⚠️ WARNING: No sorted IDs, using original order")
@@ -518,7 +518,7 @@ class DoReleaseCoordinatorService(
try { try {
println("📦 Starting batch release for ${ids.size} orders") println("📦 Starting batch release for ${ids.size} orders")
val sortedIds = getOrderedDeliveryOrderIds(ids) val sortedIds = getOrderedDeliveryOrderIds(ids)
println("🔍 DEBUG: Got ${sortedIds.size} sorted orders")
println(" DEBUG: Got ${sortedIds.size} sorted orders")


val releaseResults = mutableListOf<ReleaseDoResult>() val releaseResults = mutableListOf<ReleaseDoResult>()


@@ -538,7 +538,7 @@ class DoReleaseCoordinatorService(
) )
releaseResults.add(result) releaseResults.add(result)
status.success.incrementAndGet() status.success.incrementAndGet()
println("🔍 DO $id -> Success")
println(" DO $id -> Success")
} catch (e: Exception) { } catch (e: Exception) {
synchronized(status.failed) { synchronized(status.failed) {
status.failed.add(id to (e.message ?: "Exception")) status.failed.add(id to (e.message ?: "Exception"))
@@ -587,13 +587,13 @@ class DoReleaseCoordinatorService(
Triple(it.estimatedArrivalDate, it.preferredFloor, it.shopId) Triple(it.estimatedArrivalDate, it.preferredFloor, it.shopId)
} }


println("🔍 DEBUG: Grouped into ${grouped.size} DoPickOrders")
println(" DEBUG: Grouped into ${grouped.size} DoPickOrders")


// 第三步:为每组创建一个 DoPickOrder 和多条 DoPickOrderLine // 第三步:为每组创建一个 DoPickOrder 和多条 DoPickOrderLine
grouped.forEach { (key, group) -> grouped.forEach { (key, group) ->
try { try {
createMergedDoPickOrder(group) createMergedDoPickOrder(group)
println("🔍 DEBUG: Created DoPickOrder for ${group.size} DOs")
println(" DEBUG: Created DoPickOrder for ${group.size} DOs")
} catch (e: Exception) { } catch (e: Exception) {
println("❌ Error creating DoPickOrder: ${e.message}") println("❌ Error creating DoPickOrder: ${e.message}")
e.printStackTrace() e.printStackTrace()
@@ -653,7 +653,7 @@ class DoReleaseCoordinatorService(
// 直接使用 doPickOrderRepository.save() 而不是 doPickOrderService.save() // 直接使用 doPickOrderRepository.save() 而不是 doPickOrderService.save()
val saved = doPickOrderRepository.save(doPickOrder) val saved = doPickOrderRepository.save(doPickOrder)
println("🔍 DEBUG: Saved DoPickOrder - ID: ${saved.id}, Ticket: ${saved.ticketNo}")
println(" DEBUG: Saved DoPickOrder - ID: ${saved.id}, Ticket: ${saved.ticketNo}")
// 创建多条 DoPickOrderLine(每个 DO 一条) // 创建多条 DoPickOrderLine(每个 DO 一条)
@@ -674,7 +674,7 @@ class DoReleaseCoordinatorService(
status = "pending" // 初始状态 status = "pending" // 初始状态
} }
doPickOrderLineRepository.save(line) doPickOrderLineRepository.save(line)
println("🔍 DEBUG: Created DoPickOrderLine for pick order ${result.pickOrderId}")
println(" DEBUG: Created DoPickOrderLine for pick order ${result.pickOrderId}")
} }
// 现在检查整个 DoPickOrder 是否有库存问题 // 现在检查整个 DoPickOrder 是否有库存问题
@@ -686,10 +686,10 @@ class DoReleaseCoordinatorService(
line.status = "issue" line.status = "issue"
} }
doPickOrderLineRepository.saveAll(doPickOrderLines) doPickOrderLineRepository.saveAll(doPickOrderLines)
println("🔍 DEBUG: Updated ${doPickOrderLines.size} DoPickOrderLine records to 'issue' status")
println(" DEBUG: Updated ${doPickOrderLines.size} DoPickOrderLine records to 'issue' status")
} }
println("🔍 DEBUG: Created ${results.size} DoPickOrderLine records")
println(" DEBUG: Created ${results.size} DoPickOrderLine records")
} }
private fun checkPickOrderHasStockIssues(doPickOrderId: Long): Boolean { private fun checkPickOrderHasStockIssues(doPickOrderId: Long): Boolean {
try { try {
@@ -724,7 +724,7 @@ class DoReleaseCoordinatorService(
// 3. 只有当所有 pick orders 都有问题时才算 issue // 3. 只有当所有 pick orders 都有问题时才算 issue
val hasAllPickOrdersIssues = (totalPickOrders > 0) && (issuePickOrders == totalPickOrders) val hasAllPickOrdersIssues = (totalPickOrders > 0) && (issuePickOrders == totalPickOrders)
println("🔍 DEBUG: DoPickOrder $doPickOrderId - Total pick orders: $totalPickOrders, Issue pick orders: $issuePickOrders, All pick orders have issues: $hasAllPickOrdersIssues")
println(" DEBUG: DoPickOrder $doPickOrderId - Total pick orders: $totalPickOrders, Issue pick orders: $issuePickOrders, All pick orders have issues: $hasAllPickOrdersIssues")
return hasAllPickOrdersIssues return hasAllPickOrdersIssues
@@ -811,7 +811,7 @@ class DoReleaseCoordinatorService(
status = "pending" status = "pending"
} }
doPickOrderLineRepository.save(line) doPickOrderLineRepository.save(line)
println("🔍 DEBUG: Created DoPickOrderLine for existing DoPickOrder ${existingDoPickOrder.id}")
println(" DEBUG: Created DoPickOrderLine for existing DoPickOrder ${existingDoPickOrder.id}")
} }
} else { } else {
// 如果不存在,创建新的 do_pick_order // 如果不存在,创建新的 do_pick_order
@@ -843,7 +843,7 @@ class DoReleaseCoordinatorService(
status = "pending" status = "pending"
} }
doPickOrderLineRepository.save(line) doPickOrderLineRepository.save(line)
println("🔍 DEBUG: Created new DoPickOrder with releaseType=single")
println(" DEBUG: Created new DoPickOrder with releaseType=single")
} }
// 更新 ticket numbers(只更新 single 类型的) // 更新 ticket numbers(只更新 single 类型的)
@@ -873,11 +873,11 @@ class DoReleaseCoordinatorService(
} }
if (tempTickets.isEmpty()) { if (tempTickets.isEmpty()) {
println("🔍 No single release type tickets to update")
println(" No single release type tickets to update")
return return
} }
println("🔍 DEBUG: Found ${tempTickets.size} single release type tickets to update")
println(" DEBUG: Found ${tempTickets.size} single release type tickets to update")
// 2. 按日期和 storeId 分组 // 2. 按日期和 storeId 分组
val grouped = tempTickets.groupBy { ticket -> val grouped = tempTickets.groupBy { ticket ->
@@ -918,7 +918,7 @@ class DoReleaseCoordinatorService(
} else null } else null
}.toMutableSet() }.toMutableSet()
println("🔍 DEBUG: Group ($date, $storeId) - Existing ticket numbers: $existingTickets, Existing numbers: $existingNumbers")
println(" DEBUG: Group ($date, $storeId) - Existing ticket numbers: $existingTickets, Existing numbers: $existingNumbers")
// 5. 在组内按 truckDepartureTime, truckLanceCode, loadingSequence, doOrderId 排序 // 5. 在组内按 truckDepartureTime, truckLanceCode, loadingSequence, doOrderId 排序
val sortedTickets = tickets.sortedWith( val sortedTickets = tickets.sortedWith(
@@ -948,7 +948,7 @@ class DoReleaseCoordinatorService(
existingNumbers.add(nextNumber) existingNumbers.add(nextNumber)
nextNumber++ nextNumber++
println("🔍 DEBUG: Updated ticket ${ticket.id} to $newTicketNo")
println(" DEBUG: Updated ticket ${ticket.id} to $newTicketNo")
} }
} }


+ 10
- 10
src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt Просмотреть файл

@@ -260,7 +260,7 @@ open class JoPickOrderService(
statusList statusList
).filter { it.jobOrder != null } // Only pick orders with joId ).filter { it.jobOrder != null } // Only pick orders with joId


println("🔍 DEBUG: Found ${allAssignedPickOrders.size} job order pick orders assigned to user $userId")
println(" DEBUG: Found ${allAssignedPickOrders.size} job order pick orders assigned to user $userId")


// Filter based on assignment and status // Filter based on assignment and status
val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) { val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) {
@@ -271,7 +271,7 @@ open class JoPickOrderService(


if (assignedReleasedOrders.isNotEmpty()) { if (assignedReleasedOrders.isNotEmpty()) {
// If there are assigned RELEASED orders, show only those // If there are assigned RELEASED orders, show only those
println("🔍 DEBUG: Found ${assignedReleasedOrders.size} assigned RELEASED job orders, showing only those")
println(" DEBUG: Found ${assignedReleasedOrders.size} assigned RELEASED job orders, showing only those")
assignedReleasedOrders assignedReleasedOrders
} else { } else {
// If no assigned RELEASED orders, show only the latest COMPLETED order // If no assigned RELEASED orders, show only the latest COMPLETED order
@@ -279,10 +279,10 @@ open class JoPickOrderService(
if (completedOrders.isNotEmpty()) { if (completedOrders.isNotEmpty()) {
val latestCompleted = val latestCompleted =
completedOrders.maxByOrNull { it.completeDate ?: it.modified ?: LocalDateTime.MIN } completedOrders.maxByOrNull { it.completeDate ?: it.modified ?: LocalDateTime.MIN }
println("🔍 DEBUG: No assigned RELEASED job orders, showing latest completed order: ${latestCompleted?.code}")
println(" DEBUG: No assigned RELEASED job orders, showing latest completed order: ${latestCompleted?.code}")
listOfNotNull(latestCompleted) listOfNotNull(latestCompleted)
} else { } else {
println("🔍 DEBUG: No job orders found")
println(" DEBUG: No job orders found")
emptyList() emptyList()
} }
} }
@@ -569,7 +569,7 @@ open class JoPickOrderService(
.findAllByAssignToIdAndStatusIn(userId, listOf(PickOrderStatus.COMPLETED)) .findAllByAssignToIdAndStatusIn(userId, listOf(PickOrderStatus.COMPLETED))
.filter { it.jobOrder != null } .filter { it.jobOrder != null }
println("🔍 DEBUG: Found ${completedPickOrders.size} completed job order pick orders assigned to user $userId")
println(" DEBUG: Found ${completedPickOrders.size} completed job order pick orders assigned to user $userId")
if (completedPickOrders.isEmpty()) { if (completedPickOrders.isEmpty()) {
return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>()) return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>())
@@ -580,7 +580,7 @@ open class JoPickOrderService(
it.completeDate ?: it.modified ?: LocalDateTime.MIN it.completeDate ?: it.modified ?: LocalDateTime.MIN
} ?: return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>()) } ?: return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>())
println("🔍 DEBUG: Using latest completed order: ${latestCompletedOrder.code}")
println(" DEBUG: Using latest completed order: ${latestCompletedOrder.code}")
val pickOrder = latestCompletedOrder val pickOrder = latestCompletedOrder
val jobOrder = pickOrder.jobOrder!! val jobOrder = pickOrder.jobOrder!!
@@ -1524,8 +1524,8 @@ open fun getCompletedJobOrderPickOrderLotDetails(pickOrderId: Long): List<Map<St
il.lotNo ASC il.lotNo ASC
""".trimIndent() """.trimIndent()
println("🔍 Executing SQL for Job Order pick order lot details: $sql")
println("🔍 With parameters: pickOrderId = $pickOrderId")
println(" Executing SQL for Job Order pick order lot details: $sql")
println(" With parameters: pickOrderId = $pickOrderId")
val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId)) val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId))
@@ -1733,8 +1733,8 @@ open fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId: Lo
il.lotNo ASC il.lotNo ASC
""".trimIndent() """.trimIndent()
println("🔍 Executing SQL for completed pick order lot details: $sql")
println("🔍 With parameters: pickOrderId = $pickOrderId")
println(" Executing SQL for completed pick order lot details: $sql")
println(" With parameters: pickOrderId = $pickOrderId")
val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId)) val results = jdbcDao.queryForList(sql, mapOf("pickOrderId" to pickOrderId))


+ 74
- 74
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt Просмотреть файл

@@ -1286,8 +1286,8 @@ open class PickOrderService(
doPickOrderLineRepository.findByPickOrderIdAndDeletedFalse(pickOrderId) doPickOrderLineRepository.findByPickOrderIdAndDeletedFalse(pickOrderId)
val doPickOrderIds = doPickOrderLines.mapNotNull { it.doPickOrderId }.distinct() val doPickOrderIds = doPickOrderLines.mapNotNull { it.doPickOrderId }.distinct()


println("🔍 DEBUG: Found ${doPickOrderLines.size} do_pick_order_line records for pick order $pickOrderId")
println("🔍 DEBUG: Unique do_pick_order IDs: $doPickOrderIds")
println(" DEBUG: Found ${doPickOrderLines.size} do_pick_order_line records for pick order $pickOrderId")
println(" DEBUG: Unique do_pick_order IDs: $doPickOrderIds")


if (doPickOrderIds.isEmpty()) { if (doPickOrderIds.isEmpty()) {
println("ℹ️ INFO: No do_pick_order records found - skipping record copying") println("ℹ️ INFO: No do_pick_order records found - skipping record copying")
@@ -1302,13 +1302,13 @@ open class PickOrderService(
return@forEach return@forEach
} }
println("🔍 Processing do_pick_order ID: ${dpo.id}, ticket: ${dpo.ticketNo}")
println(" Processing do_pick_order ID: ${dpo.id}, ticket: ${dpo.ticketNo}")
// 新增:检查这个 do_pick_order 下是否还有其他未完成的 pick orders // 新增:检查这个 do_pick_order 下是否还有其他未完成的 pick orders
val allDoPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(dpo.id!!) val allDoPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(dpo.id!!)
val allPickOrderIdsInDpo = allDoPickOrderLines.mapNotNull { it.pickOrderId }.distinct() val allPickOrderIdsInDpo = allDoPickOrderLines.mapNotNull { it.pickOrderId }.distinct()
println("🔍 DEBUG: This do_pick_order has ${allPickOrderIdsInDpo.size} pick orders")
println(" DEBUG: This do_pick_order has ${allPickOrderIdsInDpo.size} pick orders")
// 检查每个 pick order 的状态 // 检查每个 pick order 的状态
val pickOrderStatuses = allPickOrderIdsInDpo.map { poId -> val pickOrderStatuses = allPickOrderIdsInDpo.map { poId ->
@@ -1317,7 +1317,7 @@ open class PickOrderService(
} }
pickOrderStatuses.forEach { (poId, status) -> pickOrderStatuses.forEach { (poId, status) ->
println("🔍 DEBUG: Pick order $poId status: $status")
println(" DEBUG: Pick order $poId status: $status")
} }
// 只有当所有 pick orders 都是 COMPLETED 状态时,才移动到 record 表 // 只有当所有 pick orders 都是 COMPLETED 状态时,才移动到 record 表
@@ -1327,7 +1327,7 @@ open class PickOrderService(
if (!allPickOrdersCompleted) { if (!allPickOrdersCompleted) {
println("⏳ Not all pick orders in this do_pick_order are completed, keeping do_pick_order alive") println("⏳ Not all pick orders in this do_pick_order are completed, keeping do_pick_order alive")
println("🔍 DEBUG: Completed pick orders: ${pickOrderStatuses.count { it.second == PickOrderStatus.COMPLETED }}/${pickOrderStatuses.size}")
println(" DEBUG: Completed pick orders: ${pickOrderStatuses.count { it.second == PickOrderStatus.COMPLETED }}/${pickOrderStatuses.size}")
return@forEach // 跳过这个 do_pick_order,不删除它 return@forEach // 跳过这个 do_pick_order,不删除它
} }
@@ -1654,7 +1654,7 @@ open class PickOrderService(


// 添加检查是否需要 resuggest 的方法 // 添加检查是否需要 resuggest 的方法
private fun checkIfNeedsResuggest(pickOrderLineId: Long): Boolean { private fun checkIfNeedsResuggest(pickOrderLineId: Long): Boolean {
println("🔍 checkIfNeedsResuggest called with pickOrderLineId: $pickOrderLineId")
println(" checkIfNeedsResuggest called with pickOrderLineId: $pickOrderLineId")


// 首先执行一个调试查询来查看实际的数值 // 首先执行一个调试查询来查看实际的数值
val debugSql = """ val debugSql = """
@@ -1680,9 +1680,9 @@ open class PickOrderService(
WHERE spl.pickOrderLineId = :pickOrderLineId WHERE spl.pickOrderLineId = :pickOrderLineId
""".trimIndent() """.trimIndent()


println("🔍 Debug SQL: $debugSql")
println(" Debug SQL: $debugSql")
val debugResult = jdbcDao.queryForList(debugSql, mapOf("pickOrderLineId" to pickOrderLineId)) val debugResult = jdbcDao.queryForList(debugSql, mapOf("pickOrderLineId" to pickOrderLineId))
println("🔍 Debug result:")
println(" Debug result:")
debugResult.forEach { row -> debugResult.forEach { row ->
println(" SuggestedPickLotId: ${row["suggestedPickLotId"]}") println(" SuggestedPickLotId: ${row["suggestedPickLotId"]}")
println(" SuggestedQty: ${row["suggestedQty"]}") println(" SuggestedQty: ${row["suggestedQty"]}")
@@ -1730,12 +1730,12 @@ open class PickOrderService(
WHERE spl.pickOrderLineId = :pickOrderLineId WHERE spl.pickOrderLineId = :pickOrderLineId
""".trimIndent() """.trimIndent()


println("🔍 Executing SQL: $checkSql")
println("🔍 With parameters: pickOrderLineId = $pickOrderLineId")
println(" Executing SQL: $checkSql")
println(" With parameters: pickOrderLineId = $pickOrderLineId")


val result = jdbcDao.queryForList(checkSql, mapOf("pickOrderLineId" to pickOrderLineId)) val result = jdbcDao.queryForList(checkSql, mapOf("pickOrderLineId" to pickOrderLineId))


println("🔍 SQL result size: ${result.size}")
println(" SQL result size: ${result.size}")


if (result.isNotEmpty()) { if (result.isNotEmpty()) {
val row = result[0] val row = result[0]
@@ -1767,7 +1767,7 @@ open class PickOrderService(
println("Needs resuggest: $needsResuggest") println("Needs resuggest: $needsResuggest")
return needsResuggest return needsResuggest
} else { } else {
println("🔍 No results returned from SQL query")
println(" No results returned from SQL query")
} }


return false return false
@@ -1839,7 +1839,7 @@ open class PickOrderService(
).filter { it.deliveryOrder != null } ).filter { it.deliveryOrder != null }


if (userExistingOrders.isNotEmpty()) { if (userExistingOrders.isNotEmpty()) {
println("🔍 DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress")
println(" DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress")
return MessageResponse( return MessageResponse(
id = null, id = null,
name = "User already has pick orders", name = "User already has pick orders",
@@ -1961,14 +1961,14 @@ open class PickOrderService(


// Update do_pick_order_record entries // Update do_pick_order_record entries
val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!) val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!)
println("🔍 DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}")
println(" DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}")


if (existingRecords.isNotEmpty()) { if (existingRecords.isNotEmpty()) {
existingRecords.forEach { record -> existingRecords.forEach { record ->
record.handledBy = user.id record.handledBy = user.id
record.ticketStatus = DoPickOrderStatus.released record.ticketStatus = DoPickOrderStatus.released
record.ticketReleaseTime = LocalDateTime.now() // 添加这行 record.ticketReleaseTime = LocalDateTime.now() // 添加这行
println("🔍 DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released")
println(" DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released")
} }
doPickOrderRecordRepository.saveAll(existingRecords) doPickOrderRecordRepository.saveAll(existingRecords)
println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries") println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries")
@@ -2108,7 +2108,7 @@ open class PickOrderService(
i.code ASC i.code ASC
""".trimIndent() """.trimIndent()


println("🔍 Executing optimized SQL: $sql")
println(" Executing optimized SQL: $sql")


val result = jdbcDao.queryForList(sql, emptyMap<String, Any>()) val result = jdbcDao.queryForList(sql, emptyMap<String, Any>())


@@ -2234,7 +2234,7 @@ open class PickOrderService(
// Fix: Store consoCode in local variable to avoid smart cast issues // Fix: Store consoCode in local variable to avoid smart cast issues
val consoCode = pickOrder.consoCode val consoCode = pickOrder.consoCode
if (consoCode == null) { if (consoCode == null) {
println("🔍 Checking pick order ${pickOrder.code} (consoCode: null)")
println(" Checking pick order ${pickOrder.code} (consoCode: null)")
println(" ⚠️ No consoCode - considering as active") println(" ⚠️ No consoCode - considering as active")
true // No consoCode means not completed true // No consoCode means not completed
} else { } else {
@@ -2501,9 +2501,9 @@ open class PickOrderService(
).filter { it.deliveryOrder != null } ).filter { it.deliveryOrder != null }


if (userExistingOrders.isNotEmpty()) { if (userExistingOrders.isNotEmpty()) {
println("🔍 DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress:")
println(" DEBUG: User $userId already has ${userExistingOrders.size} pick orders in progress:")
userExistingOrders.forEach { po -> userExistingOrders.forEach { po ->
println("🔍 DEBUG: Existing order ${po.id}: code=${po.code}, status=${po.status}")
println(" DEBUG: Existing order ${po.id}: code=${po.code}, status=${po.status}")
} }
return MessageResponse( return MessageResponse(
id = null, id = null,
@@ -2624,15 +2624,15 @@ open class PickOrderService(
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now() val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"))


println("🔍 DEBUG: Target date: $targetDate, Date prefix: $datePrefix")
println(" DEBUG: Target date: $targetDate, Date prefix: $datePrefix")


// Find truck by shop ID with earliest departure time // Find truck by shop ID with earliest departure time
val truck = deliveryOrder.shop?.id?.let { shopId -> val truck = deliveryOrder.shop?.id?.let { shopId ->
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
println(" DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId) val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
println(" DEBUG: Found ${trucks.size} trucks for shop $shopId")
val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX } val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX }
println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
println(" DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
selectedTruck selectedTruck
} }


@@ -2645,13 +2645,13 @@ open class PickOrderService(


// Get next ticket number for this date and store // Get next ticket number for this date and store
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, determinedStoreId) val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix, determinedStoreId)
println("🔍 DEBUG: Next ticket number: $nextTicketNumber")
println(" DEBUG: Next ticket number: $nextTicketNumber")


println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines")
println(" DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines")


// UPDATE existing do_pick_order_record entries instead of creating new ones // UPDATE existing do_pick_order_record entries instead of creating new ones
val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!) val existingRecords = doPickOrderRecordRepository.findByPickOrderId(selected.id!!)
println("🔍 DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}")
println(" DEBUG: Found ${existingRecords.size} existing DoPickOrderRecord entries for pick order ${selected.id}")


if (existingRecords.isNotEmpty()) { if (existingRecords.isNotEmpty()) {
// Update existing records // Update existing records
@@ -2664,7 +2664,7 @@ open class PickOrderService(
record.shopCode = deliveryOrder.shop?.code record.shopCode = deliveryOrder.shop?.code
record.shopName = deliveryOrder.shop?.name record.shopName = deliveryOrder.shop?.name
record.requiredDeliveryDate = targetDate record.requiredDeliveryDate = targetDate
println("🔍 DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released")
println(" DEBUG: Updating existing DoPickOrderRecord ID: ${record.id} - handledBy: ${user.id}, status: released")
} }
doPickOrderRecordRepository.saveAll(existingRecords) doPickOrderRecordRepository.saveAll(existingRecords)
println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries") println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries")
@@ -2672,7 +2672,7 @@ open class PickOrderService(
// Only create new records if none exist (fallback) // Only create new records if none exist (fallback)
println("⚠️ No existing DoPickOrderRecord entries found, creating new ones") println("⚠️ No existing DoPickOrderRecord entries found, creating new ones")
deliveryOrder.deliveryOrderLines.forEach { line -> deliveryOrder.deliveryOrderLines.forEach { line ->
println("🔍 DEBUG: Processing line - Store ID: $determinedStoreId")
println(" DEBUG: Processing line - Store ID: $determinedStoreId")


val doPickOrderRecord = DoPickOrderRecord( val doPickOrderRecord = DoPickOrderRecord(
id=dopickorder.id, id=dopickorder.id,
@@ -2691,10 +2691,10 @@ open class PickOrderService(
requiredDeliveryDate = targetDate requiredDeliveryDate = targetDate
) )


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


val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord) val savedDoPickOrderRecord = doPickOrderRecordRepository.save(doPickOrderRecord)
println("🔍 DEBUG: Saved new DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}")
println(" DEBUG: Saved new DoPickOrderRecord - ID: ${savedDoPickOrderRecord.id}")
} }
} }
} }
@@ -2747,9 +2747,9 @@ open class PickOrderService(
listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED) listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED)


).filter { it.deliveryOrder != null } // Only pick orders with doId ).filter { it.deliveryOrder != null } // Only pick orders with doId
println("🔍 DEBUG: All assigned pick orders: ${allAssignedPickOrders.size}")
println(" DEBUG: All assigned pick orders: ${allAssignedPickOrders.size}")
val pickOrderIds = allAssignedPickOrders.map { it.id!! } val pickOrderIds = allAssignedPickOrders.map { it.id!! }
println("🔍 DEBUG: All assigned pick orders: ${pickOrderIds.size}")
println(" DEBUG: All assigned pick orders: ${pickOrderIds.size}")
println(" Pick order IDs to fetch: $pickOrderIds") println(" Pick order IDs to fetch: $pickOrderIds")


if (pickOrderIds.isEmpty()) { if (pickOrderIds.isEmpty()) {
@@ -2883,7 +2883,7 @@ open class PickOrderService(
il.lotNo ASC il.lotNo ASC
""".trimIndent() """.trimIndent()


println("🔍 Executing SQL for all pick order lots with details: $sql")
println(" Executing SQL for all pick order lots with details: $sql")
println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr")


val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) val results = jdbcDao.queryForList(sql, mapOf("userId" to userId))
@@ -2903,7 +2903,7 @@ open class PickOrderService(


open fun getFgPickOrders(): List<Map<String, Any?>> { open fun getFgPickOrders(): List<Map<String, Any?>> {
try { try {
println("🔍 Starting getFgPickOrders method - using repository")
println(" Starting getFgPickOrders method - using repository")


// Use repository to find pick orders with type 'do' // Use repository to find pick orders with type 'do'
val pickOrders = pickOrderRepository.findAll().filter { val pickOrders = pickOrderRepository.findAll().filter {
@@ -2911,7 +2911,7 @@ open class PickOrderService(
it.status?.value in listOf("assigned", "released", "picking") it.status?.value in listOf("assigned", "released", "picking")
} }


println("🔍 Found ${pickOrders.size} FG pick orders using repository")
println(" Found ${pickOrders.size} FG pick orders using repository")


val results = pickOrders.map { po -> val results = pickOrders.map { po ->
val deliveryOrder = po.deliveryOrder val deliveryOrder = po.deliveryOrder
@@ -2968,7 +2968,7 @@ open class PickOrderService(


open fun getFgPickOrdersByUserId(userId: Long): List<Map<String, Any?>> { open fun getFgPickOrdersByUserId(userId: Long): List<Map<String, Any?>> {
try { try {
println("🔍 Starting getFgPickOrdersByUserId with userId: $userId")
println(" Starting getFgPickOrdersByUserId with userId: $userId")


// 修复:从 do_pick_order_line 获取 pick order 信息 // 修复:从 do_pick_order_line 获取 pick order 信息
val sql = """ val sql = """
@@ -3018,8 +3018,8 @@ open class PickOrderService(
ORDER BY MIN(po.targetDate) DESC, MIN(po.code) ASC ORDER BY MIN(po.targetDate) DESC, MIN(po.code) ASC
""".trimIndent() """.trimIndent()


println("🔍 Executing SQL for FG pick orders by userId: $sql")
println("🔍 With parameters: userId = $userId")
println(" Executing SQL for FG pick orders by userId: $sql")
println(" With parameters: userId = $userId")


val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) val results = jdbcDao.queryForList(sql, mapOf("userId" to userId))


@@ -3028,11 +3028,11 @@ open class PickOrderService(
return emptyList() return emptyList()
} }


println("🔍 Found ${results.size} active FG pick orders for user: $userId")
println(" Found ${results.size} active FG pick orders for user: $userId")


// 添加调试信息 // 添加调试信息
results.forEachIndexed { index, row -> results.forEachIndexed { index, row ->
println("🔍 DEBUG: Result $index:")
println(" DEBUG: Result $index:")
println(" - doPickOrderId: ${row["doPickOrderId"]}") println(" - doPickOrderId: ${row["doPickOrderId"]}")
println(" - pickOrderIds: ${row["pickOrderIds"]}") println(" - pickOrderIds: ${row["pickOrderIds"]}")
println(" - numberOfPickOrders: ${row["numberOfPickOrders"]}") println(" - numberOfPickOrders: ${row["numberOfPickOrders"]}")
@@ -3088,7 +3088,7 @@ open class PickOrderService(


open fun getFgPickOrdersByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { open fun getFgPickOrdersByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> {
try { try {
println("🔍 Starting getFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId")
println(" Starting getFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId")


val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null)


@@ -3097,7 +3097,7 @@ open class PickOrderService(
return emptyList() return emptyList()
} }


println("🔍 Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}")
println(" Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}")


if (pickOrder.type?.value != "do") { if (pickOrder.type?.value != "do") {
println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}") println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}")
@@ -3117,16 +3117,16 @@ open class PickOrderService(
val supplier = deliveryOrder?.supplier val supplier = deliveryOrder?.supplier


println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}") println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}")
println("🔍 Shop ID: ${shop?.id}")
println(" Shop ID: ${shop?.id}")


// Get truck information using repository with detailed debugging // Get truck information using repository with detailed debugging
val truck = if (shop?.id != null) { val truck = if (shop?.id != null) {
try { try {
println("🔍 Querying truck repository for shopId: ${shop.id}")
println(" Querying truck repository for shopId: ${shop.id}")


// Get all trucks for this shop // Get all trucks for this shop
val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id) val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id)
println("🔍 Trucks for shop ${shop.id}: ${trucksForShop.size}")
println(" Trucks for shop ${shop.id}: ${trucksForShop.size}")
trucksForShop.forEach { t -> trucksForShop.forEach { t ->
println(" - Truck ID: ${t.id}, truckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}") println(" - Truck ID: ${t.id}, truckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}")
} }
@@ -3153,7 +3153,7 @@ open class PickOrderService(
val ticketNo = try { val ticketNo = try {
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: "" val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: ""
println("🔍 Found ticket number: $ticketNo for pick order $pickOrderId")
println(" Found ticket number: $ticketNo for pick order $pickOrderId")
ticketNo ticketNo
} catch (e: Exception) { } catch (e: Exception) {
println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}") println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}")
@@ -3200,7 +3200,7 @@ open class PickOrderService(


open fun getnewFgPickOrdersByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { open fun getnewFgPickOrdersByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> {
try { try {
println("🔍 Starting getnewFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId")
println(" Starting getnewFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId")


val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null)


@@ -3209,7 +3209,7 @@ open class PickOrderService(
return emptyList() return emptyList()
} }


println("🔍 Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}")
println(" Found pick order: ${pickOrder.code}, type: ${pickOrder.type?.value}, status: ${pickOrder.status?.value}")


if (pickOrder.type?.value != "do") { if (pickOrder.type?.value != "do") {
println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}") println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}")
@@ -3229,16 +3229,16 @@ open class PickOrderService(
val supplier = deliveryOrder?.supplier val supplier = deliveryOrder?.supplier


println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}") println(" Delivery order: ${deliveryOrder?.code}, Shop: ${shop?.name}, Supplier: ${supplier?.code}")
println("🔍 Shop ID: ${shop?.id}")
println(" Shop ID: ${shop?.id}")


// Get truck information using repository with detailed debugging // Get truck information using repository with detailed debugging
val truck = if (shop?.id != null) { val truck = if (shop?.id != null) {
try { try {
println("🔍 Querying truck repository for shopId: ${shop.id}")
println(" Querying truck repository for shopId: ${shop.id}")


// Get all trucks for this shop // Get all trucks for this shop
val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id) val trucksForShop = truckRepository.findByShopIdAndDeletedFalse(shop.id)
println("🔍 Trucks for shop ${shop.id}: ${trucksForShop.size}")
println(" Trucks for shop ${shop.id}: ${trucksForShop.size}")
trucksForShop.forEach { t -> trucksForShop.forEach { t ->
println(" - Truck ID: ${t.id}, TruckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}") println(" - Truck ID: ${t.id}, TruckLanceCode: ${t.truckLanceCode}, ShopId: ${t.shop?.id}, Deleted: ${t.deleted}")
} }
@@ -3265,7 +3265,7 @@ open class PickOrderService(
val ticketNo = try { val ticketNo = try {
val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId) val doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: "" val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: ""
println("🔍 Found ticket number: $ticketNo for pick order $pickOrderId")
println(" Found ticket number: $ticketNo for pick order $pickOrderId")
ticketNo ticketNo
} catch (e: Exception) { } catch (e: Exception) {
println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}") println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}")
@@ -3342,9 +3342,9 @@ open class PickOrderService(
user, user,
listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED) listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED)
).filter { it.deliveryOrder != null } // Only pick orders with doId ).filter { it.deliveryOrder != null } // Only pick orders with doId
println("🔍 DEBUG: Found ${allAssignedPickOrders.size} pick orders assigned to user $userId")
println(" DEBUG: Found ${allAssignedPickOrders.size} pick orders assigned to user $userId")
allAssignedPickOrders.forEach { po -> allAssignedPickOrders.forEach { po ->
println("🔍 DEBUG: Pick order ${po.id}: code=${po.code}, status=${po.status}, assignTo=${po.assignTo?.id}, doId=${po.deliveryOrder?.id}")
println(" DEBUG: Pick order ${po.id}: code=${po.code}, status=${po.status}, assignTo=${po.assignTo?.id}, doId=${po.deliveryOrder?.id}")
} }
// NEW LOGIC: Filter based on assignment and status // NEW LOGIC: Filter based on assignment and status
val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) { val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) {
@@ -3355,7 +3355,7 @@ open class PickOrderService(


if (assignedReleasedOrders.isNotEmpty()) { if (assignedReleasedOrders.isNotEmpty()) {
// If there are assigned RELEASED orders, show only those // If there are assigned RELEASED orders, show only those
println("🔍 DEBUG: Found ${assignedReleasedOrders.size} assigned RELEASED orders, showing only those")
println(" DEBUG: Found ${assignedReleasedOrders.size} assigned RELEASED orders, showing only those")
assignedReleasedOrders assignedReleasedOrders
} else { } else {
// If no assigned RELEASED orders, show only the latest COMPLETED order // If no assigned RELEASED orders, show only the latest COMPLETED order
@@ -3366,7 +3366,7 @@ open class PickOrderService(
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) listOfNotNull(latestCompleted)
} else { } else {
println("🔍 DEBUG: No orders found")
println(" DEBUG: No orders found")
emptyList() emptyList()
} }
} }
@@ -3523,7 +3523,7 @@ ORDER BY
il.lotNo ASC il.lotNo ASC
""".trimIndent() """.trimIndent()


println("🔍 Executing SQL for all pick order lots with details (no auto-assign): $sql")
println(" Executing SQL for all pick order lots with details (no auto-assign): $sql")
println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr") println(" With parameters: userId = $userId, pickOrderIds = $pickOrderIdsStr")


val results = jdbcDao.queryForList(sql, mapOf("userId" to userId)) val results = jdbcDao.queryForList(sql, mapOf("userId" to userId))
@@ -3630,7 +3630,7 @@ ORDER BY
) )
} }
println("🔍 Found ${userPickOrders.size} pick orders assigned to user $userId")
println(" Found ${userPickOrders.size} pick orders assigned to user $userId")
val pickOrderIds = userPickOrders.mapNotNull { it.id } val pickOrderIds = userPickOrders.mapNotNull { it.id }
// Step 2: 通过 do_pick_order_line 找到相关的 do_pick_order // Step 2: 通过 do_pick_order_line 找到相关的 do_pick_order
@@ -3648,7 +3648,7 @@ ORDER BY
) )
} }
println("🔍 Found ${doPickOrderIds.size} do_pick_order records")
println(" Found ${doPickOrderIds.size} do_pick_order records")
// Step 3: 获取第一个 do_pick_order 的详细信息(用于构建 fgInfo) // Step 3: 获取第一个 do_pick_order 的详细信息(用于构建 fgInfo)
val doPickOrder = doPickOrderRepository.findById(doPickOrderIds.first()).orElse(null) val doPickOrder = doPickOrderRepository.findById(doPickOrderIds.first()).orElse(null)
@@ -3661,13 +3661,13 @@ ORDER BY
} }
val doPickOrderId = doPickOrder.id!! val doPickOrderId = doPickOrder.id!!
println("🔍 Using do_pick_order ID: $doPickOrderId")
println(" Using do_pick_order ID: $doPickOrderId")
// Step 4: 使用 Repository 加载 pick orders 及其关联数据 // Step 4: 使用 Repository 加载 pick orders 及其关联数据
val pickOrders = pickOrderRepository.findAllById(pickOrderIds) val pickOrders = pickOrderRepository.findAllById(pickOrderIds)
.filter { it.deleted == false } .filter { it.deleted == false }
println("🔍 Loaded ${pickOrders.size} pick orders")
println(" Loaded ${pickOrders.size} pick orders")
// 收集所有需要的数据 // 收集所有需要的数据
// 收集所有需要的数据 // 收集所有需要的数据
@@ -4037,7 +4037,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String
} }
val doPickOrderId = (doPickOrderInfo["do_pick_order_id"] as? Number)?.toLong() val doPickOrderId = (doPickOrderInfo["do_pick_order_id"] as? Number)?.toLong()
println("🔍 Found do_pick_order ID: $doPickOrderId")
println(" Found do_pick_order ID: $doPickOrderId")
val doTicketStatus = doPickOrderInfo["ticket_status"] val doTicketStatus = doPickOrderInfo["ticket_status"]
// Step 2: 获取该 do_pick_order 下的所有 pick orders // Step 2: 获取该 do_pick_order 下的所有 pick orders
val pickOrdersSql = """ val pickOrdersSql = """
@@ -4058,7 +4058,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String
""".trimIndent() """.trimIndent()
val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderId" to doPickOrderId)) val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderId" to doPickOrderId))
println("🔍 Found ${pickOrdersInfo.size} pick orders")
println(" Found ${pickOrdersInfo.size} pick orders")
// Step 3: 为每个 pick order 获取 lines 和 lots // Step 3: 为每个 pick order 获取 lines 和 lots
val allPickOrderLines = mutableListOf<Map<String, Any?>>() val allPickOrderLines = mutableListOf<Map<String, Any?>>()
@@ -4201,7 +4201,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String
""".trimIndent() """.trimIndent()
val linesResults = jdbcDao.queryForList(linesSql, mapOf("pickOrderId" to pickOrderId)) val linesResults = jdbcDao.queryForList(linesSql, mapOf("pickOrderId" to pickOrderId))
println("🔍 Pick order $pickOrderId has ${linesResults.size} line-lot records")
println(" Pick order $pickOrderId has ${linesResults.size} line-lot records")
println("DEBUG polIds in linesResults: " + linesResults.map { it["pickOrderLineId"] }.distinct()) println("DEBUG polIds in linesResults: " + linesResults.map { it["pickOrderLineId"] }.distinct())
println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["stockOutLineId"]?.let { _ -> it["pickOrderLineId"] } }.distinct()) println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["stockOutLineId"]?.let { _ -> it["pickOrderLineId"] } }.distinct())
// 按 pickOrderLineId 分组 // 按 pickOrderLineId 分组
@@ -4377,8 +4377,8 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto
ORDER BY orderDate ASC ORDER BY orderDate ASC
""".trimIndent() """.trimIndent()


println("🔍 Executing SQL: $sql")
println("🔍 With parameters: storeId = $storeId")
println(" Executing SQL: $sql")
println(" With parameters: storeId = $storeId")


val results = jdbcDao.queryForList(sql, mapOf("storeId" to storeId)) val results = jdbcDao.queryForList(sql, mapOf("storeId" to storeId))
println(" Found ${results.size} records") println(" Found ${results.size} records")
@@ -4743,7 +4743,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
""".trimIndent() """.trimIndent()
val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderRecordId" to doPickOrderRecordId)) val pickOrdersInfo = jdbcDao.queryForList(pickOrdersSql, mapOf("doPickOrderRecordId" to doPickOrderRecordId))
println("🔍 Found ${pickOrdersInfo.size} pick orders in do_pick_order_record")
println(" Found ${pickOrdersInfo.size} pick orders in do_pick_order_record")
// Step 3: 为每个 pick order 获取 lines 和 lots // Step 3: 为每个 pick order 获取 lines 和 lots
val pickOrders = pickOrdersInfo.map { poInfo -> val pickOrders = pickOrdersInfo.map { poInfo ->
@@ -5082,7 +5082,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
pickOrders = emptyList() pickOrders = emptyList()
) )
println("🔍 Found DoPickOrderRecord: id=${dpor.id}, ticketNo=${dpor.ticketNo}")
println(" Found DoPickOrderRecord: id=${dpor.id}, ticketNo=${dpor.ticketNo}")
// 2) 构建 fgInfo // 2) 构建 fgInfo
val fgInfo = FgInfoResponse( val fgInfo = FgInfoResponse(
@@ -5097,7 +5097,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
// 3) 通过 DoPickOrderLineRecord 获取 pickOrderIds // 3) 通过 DoPickOrderLineRecord 获取 pickOrderIds
val lineRecords = doPickOrderLineRecordRepository.findByDoPickOrderIdAndDeletedFalse(dpor.recordId!!) val lineRecords = doPickOrderLineRecordRepository.findByDoPickOrderIdAndDeletedFalse(dpor.recordId!!)
println("🔍 Found ${lineRecords.size} DoPickOrderLineRecord records")
println(" Found ${lineRecords.size} DoPickOrderLineRecord records")
var pickOrderIds = lineRecords.mapNotNull { it.pickOrderId }.distinct() var pickOrderIds = lineRecords.mapNotNull { it.pickOrderId }.distinct()
@@ -5115,7 +5115,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
) )
} }
println("🔍 Using pickOrderIds: $pickOrderIds")
println(" Using pickOrderIds: $pickOrderIds")
// 4) 批量加载所有相关数据 // 4) 批量加载所有相关数据
val pickOrders = pickOrderRepository.findAllById(pickOrderIds) val pickOrders = pickOrderRepository.findAllById(pickOrderIds)
@@ -5129,7 +5129,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
) )
} }
println("🔍 Found ${pickOrders.size} pick orders")
println(" Found ${pickOrders.size} pick orders")
// 5) 收集所有 pickOrderLineIds // 5) 收集所有 pickOrderLineIds
val allPickOrderLineIds = pickOrders val allPickOrderLineIds = pickOrders
@@ -5137,7 +5137,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
.filter { !it.deleted } .filter { !it.deleted }
.mapNotNull { it.id } .mapNotNull { it.id }
println("🔍 Found ${allPickOrderLineIds.size} pick order lines")
println(" Found ${allPickOrderLineIds.size} pick order lines")
// 6) 批量加载 suggestions 和 stock out lines // 6) 批量加载 suggestions 和 stock out lines
val allSuggestions = if (allPickOrderLineIds.isNotEmpty()) { val allSuggestions = if (allPickOrderLineIds.isNotEmpty()) {
@@ -5317,7 +5317,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
// 新增:从 do_pick_order_record 表查询(用于已完成的 pick orders) // 新增:从 do_pick_order_record 表查询(用于已完成的 pick orders)
open fun getFgPickOrdersFromRecordByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> { open fun getFgPickOrdersFromRecordByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> {
try { try {
println("🔍 Starting getFgPickOrdersFromRecordByPickOrderId with pickOrderId: $pickOrderId")
println(" Starting getFgPickOrdersFromRecordByPickOrderId with pickOrderId: $pickOrderId")


val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null)
if (pickOrder == null) { if (pickOrder == null) {


+ 7
- 7
src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt Просмотреть файл

@@ -83,14 +83,14 @@ open class ProductProcessService(
} }
open fun findById(id: Long): ProductProcess { open fun findById(id: Long): ProductProcess {
println("🔍 Service: Finding ProductProcess by ID: $id")
println(" Service: Finding ProductProcess by ID: $id")


return productProcessRepository.findById(id) return productProcessRepository.findById(id)
.orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") } .orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") }
} }
open fun findByCode(code: String): ProductProcess { open fun findByCode(code: String): ProductProcess {
println("🔍 Service: Finding ProductProcess by code: $code")
println(" Service: Finding ProductProcess by code: $code")
return productProcessRepository.findByProductProcessCode(code) return productProcessRepository.findByProductProcessCode(code)
.orElseThrow { IllegalArgumentException("ProductProcess not found with code: $code") } .orElseThrow { IllegalArgumentException("ProductProcess not found with code: $code") }
} }
@@ -126,7 +126,7 @@ open class ProductProcessService(
// 4. 查询 BOM 的所有工序步骤 // 4. 查询 BOM 的所有工序步骤
val bomProcesses = bomProcessRepository.findByBomIdOrderBySeqNo(request.bomId) val bomProcesses = bomProcessRepository.findByBomIdOrderBySeqNo(request.bomId)
println("🔍 Service: Found ${bomProcesses.size} BOM processes")
println(" Service: Found ${bomProcesses.size} BOM processes")
// 5. 为每个 BOM Process 创建 ProductProcessLine // 5. 为每个 BOM Process 创建 ProductProcessLine
bomProcesses.forEachIndexed { index, bomProcess -> // 修复 forEach bomProcesses.forEachIndexed { index, bomProcess -> // 修复 forEach
@@ -274,14 +274,14 @@ open class ProductProcessService(
return issues return issues
} }
open fun findByJobOrderId(jobOrderId: Long): List<ProductProcess> { open fun findByJobOrderId(jobOrderId: Long): List<ProductProcess> {
println("🔍 Service: Finding ProductProcess by jobOrderId: $jobOrderId")
println(" Service: Finding ProductProcess by jobOrderId: $jobOrderId")
val result = productProcessRepository.findByJobOrder_Id(jobOrderId) val result = productProcessRepository.findByJobOrder_Id(jobOrderId)
println(" Service: Found ${result.size} processes") println(" Service: Found ${result.size} processes")
return result return result
} }
open fun findByJobOrderIdWithLines(jobOrderId: Long): List<ProductProcessWithLinesResponse> { open fun findByJobOrderIdWithLines(jobOrderId: Long): List<ProductProcessWithLinesResponse> {
println("🔍 Service: Finding ProductProcess with lines by jobOrderId: $jobOrderId")
println(" Service: Finding ProductProcess with lines by jobOrderId: $jobOrderId")
val processes = productProcessRepository.findByJobOrder_Id(jobOrderId) val processes = productProcessRepository.findByJobOrder_Id(jobOrderId)
val result = processes.map { process -> val result = processes.map { process ->
@@ -338,7 +338,7 @@ open class ProductProcessService(
} }
open fun findByIdAsDto(id: Long): ProductProcessSimpleResponse { open fun findByIdAsDto(id: Long): ProductProcessSimpleResponse {
println("🔍 Service: Finding ProductProcess by ID: $id as DTO")
println(" Service: Finding ProductProcess by ID: $id as DTO")
val entity = productProcessRepository.findById(id) val entity = productProcessRepository.findById(id)
.orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") } .orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") }
@@ -480,7 +480,7 @@ open class ProductProcessService(
return saved return saved
} }
open fun findPendingLinesByHandlerId(handlerId: Long): List<ProductProcessLine> { open fun findPendingLinesByHandlerId(handlerId: Long): List<ProductProcessLine> {
println("🔍 Service: Finding pending lines for handlerId: $handlerId")
println(" Service: Finding pending lines for handlerId: $handlerId")
val lines = productProcessLineRepository.findByHandler_IdAndStartTimeIsNotNullAndEndTimeIsNull(handlerId) val lines = productProcessLineRepository.findByHandler_IdAndStartTimeIsNotNullAndEndTimeIsNull(handlerId)
println(" Service: Found ${lines.size} pending lines") println(" Service: Found ${lines.size} pending lines")
return lines return lines


+ 4
- 4
src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt Просмотреть файл

@@ -25,7 +25,7 @@ class ProductProcessController(


@GetMapping("/{id}") @GetMapping("/{id}")
fun findById(@PathVariable id: Long): ProductProcessSimpleResponse { // 改为返回 DTO fun findById(@PathVariable id: Long): ProductProcessSimpleResponse { // 改为返回 DTO
println("🔍 Controller: GET /product-process/$id")
println(" Controller: GET /product-process/$id")
val result = productProcessService.findByIdAsDto(id) // 使用新方法 val result = productProcessService.findByIdAsDto(id) // 使用新方法
println(" Controller: Found: ${result.productProcessCode}") println(" Controller: Found: ${result.productProcessCode}")
return result return result
@@ -33,7 +33,7 @@ class ProductProcessController(


@GetMapping("/code/{code}") @GetMapping("/code/{code}")
fun findByCode(@PathVariable code: String): ProductProcess { fun findByCode(@PathVariable code: String): ProductProcess {
println("🔍 Controller: GET /product-process/code/$code")
println(" Controller: GET /product-process/code/$code")
val result = productProcessService.findByCode(code) val result = productProcessService.findByCode(code)
println(" Controller: Found ID: ${result.id}") println(" Controller: Found ID: ${result.id}")
return result return result
@@ -128,7 +128,7 @@ class ProductProcessController(


@GetMapping("/by-job-order/{jobOrderId}") @GetMapping("/by-job-order/{jobOrderId}")
fun findByJobOrderId(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> { // 改为返回 DTO fun findByJobOrderId(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> { // 改为返回 DTO
println("🔍 Controller: GET /product-process/by-job-order/$jobOrderId")
println(" Controller: GET /product-process/by-job-order/$jobOrderId")
val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) // 直接使用 with-lines 方法 val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) // 直接使用 with-lines 方法
println(" Controller: Found ${result.size} processes for Job Order $jobOrderId") println(" Controller: Found ${result.size} processes for Job Order $jobOrderId")
return result return result
@@ -137,7 +137,7 @@ class ProductProcessController(
// 额外添加:获取带 lines 的完整数据 // 额外添加:获取带 lines 的完整数据
@GetMapping("/by-job-order/{jobOrderId}/with-lines") @GetMapping("/by-job-order/{jobOrderId}/with-lines")
fun findByJobOrderIdWithLines(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> { fun findByJobOrderIdWithLines(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> {
println("🔍 Controller: GET /product-process/by-job-order/$jobOrderId/with-lines")
println(" Controller: GET /product-process/by-job-order/$jobOrderId/with-lines")
val result = productProcessService.findByJobOrderIdWithLines(jobOrderId) val result = productProcessService.findByJobOrderIdWithLines(jobOrderId)
println(" Controller: Found ${result.size} processes with lines for Job Order $jobOrderId") println(" Controller: Found ${result.size} processes with lines for Job Order $jobOrderId")
return result return result


+ 7
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/InventoryLotLineRepository.kt Просмотреть файл

@@ -63,4 +63,11 @@ fun findAllByWarehouseIdInAndDeletedIsFalse(@Param("warehouseIds") warehouseIds:
ORDER BY ill.inventoryLot.item.code, ill.inventoryLot.lotNo ORDER BY ill.inventoryLot.item.code, ill.inventoryLot.lotNo
""") """)
fun findAllByWarehouseCodeAndDeletedIsFalse(@Param("warehouseCode") warehouseCode: String): List<InventoryLotLine> fun findAllByWarehouseCodeAndDeletedIsFalse(@Param("warehouseCode") warehouseCode: String): List<InventoryLotLine>
@Query("""
SELECT COUNT(DISTINCT ill.inventoryLot.item.id)
FROM InventoryLotLine ill
WHERE ill.warehouse.id IN :warehouseIds
AND ill.deleted = false
""")
fun countDistinctItemsByWarehouseIds(@Param("warehouseIds") warehouseIds: List<Long>): Long
} }

+ 3
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/StockInLine.kt Просмотреть файл

@@ -108,6 +108,9 @@ open class StockInLine : BaseEntity<Long>() {
@Column(name = "remarks") @Column(name = "remarks")
open var remarks: String? = null open var remarks: String? = null


@Column(name = "type")
open var type: String? = null

@JsonManagedReference @JsonManagedReference
@OneToMany(mappedBy = "stockInLine", cascade = [CascadeType.ALL], orphanRemoval = true) @OneToMany(mappedBy = "stockInLine", cascade = [CascadeType.ALL], orphanRemoval = true)
open var escalationLog: MutableList<EscalationLog>? = mutableListOf() open var escalationLog: MutableList<EscalationLog>? = mutableListOf()


+ 3
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLine.kt Просмотреть файл

@@ -45,4 +45,7 @@ open class StockOutLine: BaseEntity<Long>() {
@ManyToOne @ManyToOne
@JoinColumn(name = "pickOrderLineId") @JoinColumn(name = "pickOrderLineId")
open var pickOrderLine: PickOrderLine? = null open var pickOrderLine: PickOrderLine? = null

@Column(name = "type")
open var type: String? = null
} }

+ 237
- 117
src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt Просмотреть файл

@@ -97,9 +97,9 @@ class StockTakeRecordService(
.filter { it.status == StockTakeStatus.COMPLETED && it.actualEnd != null } .filter { it.status == StockTakeStatus.COMPLETED && it.actualEnd != null }
.sortedByDescending { it.actualEnd } .sortedByDescending { it.actualEnd }
val lastStockTakeDate = completedStockTakes.firstOrNull()?.actualEnd?.toLocalDate()
val lastStockTakeDate = completedStockTakes.firstOrNull()?.actualEnd
// 7. 获取 status:获取最新的 stock_take 记录(按 actualStart 或 planStart 排序)
val latestStockTake = stockTakesForSection val latestStockTake = stockTakesForSection
.maxByOrNull { it.actualStart ?: it.planStart ?: LocalDateTime.MIN } .maxByOrNull { it.actualStart ?: it.planStart ?: LocalDateTime.MIN }
@@ -108,17 +108,65 @@ class StockTakeRecordService(
} else { } else {
"no_cycle" "no_cycle"
} }
val stockTakerName = if (latestStockTake != null) {
// 从该 stock take 的 records 中获取最新的 stockTakerName
val recordsForStockTake = allStockTakeRecords
.filter {
it.stockTake?.id == latestStockTake.id &&
it.stockTakeSection == stockTakeSection &&
it.stockTakerName != null
}
.sortedByDescending { it.stockTakeStartTime ?: LocalDateTime.MIN }
recordsForStockTake.firstOrNull()?.stockTakerName
} else {
null
}
val approverName = if (latestStockTake != null) {
// 从该 stock take 的 records 中获取最新的 approverName
val recordsForStockTake = allStockTakeRecords
.filter {
it.stockTake?.id == latestStockTake.id &&
it.stockTakeSection == stockTakeSection &&
it.approverName != null
}
.sortedByDescending { it.stockTakeStartTime ?: LocalDateTime.MIN }
recordsForStockTake.firstOrNull()?.approverName
} else {
null
}
// 9. 计算 TotalItemNumber:获取该 section 下所有 InventoryLotLine,按 item 分组,计算不同的 item 数量
val totalItemNumber = inventoryLotLineRepository.countDistinctItemsByWarehouseIds(warehouseIds).toInt()
// 8. 使用 stockTakeSection 作为 stockTakeSession // 8. 使用 stockTakeSection 作为 stockTakeSession
val reStockTakeTrueFalse = if (latestStockTake != null) {
// 检查该 stock take 下该 section 的记录中是否有 notMatch 状态
val hasNotMatch = allStockTakeRecords.any {
!it.deleted &&
it.stockTake?.id == latestStockTake.id &&
it.stockTakeSection == stockTakeSection &&
it.status == "notMatch"
}
hasNotMatch
} else {
false
}
result.add( result.add(
AllPickedStockTakeListReponse( AllPickedStockTakeListReponse(
id = idCounter++, id = idCounter++,
stockTakeSession = stockTakeSection, stockTakeSession = stockTakeSection,
lastStockTakeDate = lastStockTakeDate,
status = status,
currentStockTakeItemNumber = 0, // 临时设为 0,测试性能
totalInventoryLotNumber = 0, // 临时设为 0,测试性能
stockTakeId = latestStockTake?.id ?: 0
lastStockTakeDate = latestStockTake?.actualStart?.toLocalDate(),
status = status?:"",
currentStockTakeItemNumber = 0,
totalInventoryLotNumber = 0,
stockTakeId = latestStockTake?.id ?: 0,
stockTakerName = stockTakerName,
TotalItemNumber = totalItemNumber,
approverName = approverName,
startTime = latestStockTake?.actualStart,
endTime = latestStockTake?.actualEnd,
ReStockTakeTrueFalse = reStockTakeTrueFalse

) )
) )
} }
@@ -196,17 +244,65 @@ class StockTakeRecordService(
} else { } else {
null null
} }
val stockTakerName = if (latestStockTake != null) {
// 从该 stock take 的 records 中获取最新的 stockTakerName
val recordsForStockTake = allStockTakeRecords
.filter {
it.stockTake?.id == latestStockTake.id &&
it.stockTakeSection == stockTakeSection &&
it.stockTakerName != null
}
.sortedByDescending { it.stockTakeStartTime ?: LocalDateTime.MIN }
recordsForStockTake.firstOrNull()?.stockTakerName
} else {
null
}
val approverName = if (latestStockTake != null) {
// 从该 stock take 的 records 中获取最新的 approverName
val recordsForStockTake = allStockTakeRecords
.filter {
it.stockTake?.id == latestStockTake.id &&
it.stockTakeSection == stockTakeSection &&
it.approverName != null
}
.sortedByDescending { it.stockTakeStartTime ?: LocalDateTime.MIN }
recordsForStockTake.firstOrNull()?.approverName
} else {
null
}
val reStockTakeTrueFalse = if (latestStockTake != null) {
// 检查该 stock take 下该 section 的记录中是否有 notMatch 状态
val hasNotMatch = allStockTakeRecords.any {
!it.deleted &&
it.stockTake?.id == latestStockTake.id &&
it.stockTakeSection == stockTakeSection &&
it.status == "notMatch"
}
hasNotMatch
} else {
false
}
// 9. 计算 TotalItemNumber:获取该 section 下所有 InventoryLotLine,按 item 分组,计算不同的 item 数量
val totalItemNumber = inventoryLotLineRepository.countDistinctItemsByWarehouseIds(warehouseIds).toInt()
// 9. 使用 stockTakeSection 作为 stockTakeSession // 9. 使用 stockTakeSection 作为 stockTakeSession
result.add( result.add(
AllPickedStockTakeListReponse( AllPickedStockTakeListReponse(
id = idCounter++, id = idCounter++,
stockTakeSession = stockTakeSection, stockTakeSession = stockTakeSection,
lastStockTakeDate = lastStockTakeDate,
lastStockTakeDate = latestStockTake?.actualStart?.toLocalDate(),
status = status?:"", status = status?:"",
currentStockTakeItemNumber = 0, // 临时设为 0,测试性能 currentStockTakeItemNumber = 0, // 临时设为 0,测试性能
totalInventoryLotNumber = 0, // 临时设为 0,测试性能 totalInventoryLotNumber = 0, // 临时设为 0,测试性能
stockTakeId = latestStockTake?.id ?: 0
stockTakeId = latestStockTake?.id ?: 0,
stockTakerName = stockTakerName,
approverName = approverName,
TotalItemNumber = totalItemNumber,
startTime = latestStockTake?.actualStart,
endTime = latestStockTake?.actualEnd,
ReStockTakeTrueFalse = reStockTakeTrueFalse
) )
) )
} }
@@ -414,11 +510,10 @@ class StockTakeRecordService(
} }
existingRecord existingRecord
} else { } else {
// 创建新记录(第一次盘点)
// 第一次盘点不验证 QTY + Bad QTY 是否匹配,允许不匹配的情况
// 如果匹配,status = "1",如果不匹配,status = "2"

val totalInputQty = request.qty.add(request.badQty) val totalInputQty = request.qty.add(request.badQty)
val isMatched = totalInputQty.compareTo(availableQty) == 0 val isMatched = totalInputQty.compareTo(availableQty) == 0
val isCompled=inventoryLotLine.inQty==inventoryLotLine.outQty
val varianceQty = availableQty-request.qty-request.badQty val varianceQty = availableQty-request.qty-request.badQty
StockTakeRecord().apply { StockTakeRecord().apply {
this.itemId = item.id this.itemId = item.id
@@ -435,7 +530,7 @@ class StockTakeRecordService(
this.varianceQty = varianceQty this.varianceQty = varianceQty
this.uom = inventoryLotLine.stockUom?.uom?.udfudesc this.uom = inventoryLotLine.stockUom?.uom?.udfudesc
this.date = java.time.LocalDate.now() this.date = java.time.LocalDate.now()
this.status = if (isMatched) "pass" else "notMatch"
this.status = if (isCompled) "completed" else "pass"
this.remarks = request.remark this.remarks = request.remark
this.itemCode = item.code this.itemCode = item.code
this.itemName = item.name this.itemName = item.name
@@ -447,7 +542,23 @@ class StockTakeRecordService(
val savedRecord = stockTakeRecordRepository.save(stockTakeRecord) val savedRecord = stockTakeRecordRepository.save(stockTakeRecord)
if (request.stockTakeRecordId == null) {
val existingRecordsCount = stockTakeRecordRepository.findAll()
.filter {
!it.deleted &&
it.stockTake?.id == stockTakeId &&
it.id != savedRecord.id // 排除刚创建的这条记录
}
.count()
if (existingRecordsCount == 0 && stockTake.actualStart == null) {
stockTake.actualStart = java.time.LocalDateTime.now()
stockTake.status = StockTakeStatus.STOCKTAKING
stockTakeRepository.save(stockTake)
println("Stock take $stockTakeId actualStart updated - first record created")
}
}
val stockTakeSection = savedRecord.stockTakeSection val stockTakeSection = savedRecord.stockTakeSection
if (stockTakeSection != null) { if (stockTakeSection != null) {
@@ -541,6 +652,7 @@ open fun batchSaveStockTakeRecords(
val totalInputQty = qty.add(badQty) val totalInputQty = qty.add(badQty)
val isMatched = totalInputQty.compareTo(availableQty) == 0 val isMatched = totalInputQty.compareTo(availableQty) == 0
val varianceQty = availableQty-qty-badQty val varianceQty = availableQty-qty-badQty
val isCompleted = (ill.inQty ?: BigDecimal.ZERO) == (ill.outQty ?: BigDecimal.ZERO)
// 创建新记录 // 创建新记录
val stockTakeRecord = StockTakeRecord().apply { val stockTakeRecord = StockTakeRecord().apply {
this.itemId = itemEntity.id this.itemId = itemEntity.id
@@ -557,7 +669,7 @@ open fun batchSaveStockTakeRecords(
this.varianceQty = varianceQty this.varianceQty = varianceQty
this.uom = ill.stockUom?.uom?.udfudesc this.uom = ill.stockUom?.uom?.udfudesc
this.date = java.time.LocalDate.now() this.date = java.time.LocalDate.now()
this.status = if (isMatched) "pass" else "notMatch"
this.status = if (isCompleted) "completed" else "pass"
this.remarks = null this.remarks = null
this.itemCode = itemEntity.code this.itemCode = itemEntity.code
this.itemName = itemEntity.name this.itemName = itemEntity.name
@@ -577,6 +689,12 @@ open fun batchSaveStockTakeRecords(
} }
} }
if (successCount > 0) { if (successCount > 0) {
val existingRecordsCount = stockTakeRecordRepository.findAll()
.filter {
!it.deleted &&
it.stockTake?.id == request.stockTakeId
}
.count()
checkAndUpdateStockTakeStatus(request.stockTakeId, request.stockTakeSection) checkAndUpdateStockTakeStatus(request.stockTakeId, request.stockTakeSection)
} }
println("batchSaveStockTakeRecords completed: success=$successCount, errors=$errorCount") println("batchSaveStockTakeRecords completed: success=$successCount, errors=$errorCount")
@@ -586,10 +704,7 @@ open fun batchSaveStockTakeRecords(
errors = errors errors = errors
) )
} }
// ... existing code ...


// 检查并更新 stock take 状态
// 检查并更新 stock take 状态
open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: String): Map<String, Any> { open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: String): Map<String, Any> {
try { try {
val stockTake = stockTakeRepository.findByIdAndDeletedIsFalse(stockTakeId) val stockTake = stockTakeRepository.findByIdAndDeletedIsFalse(stockTakeId)
@@ -629,20 +744,29 @@ open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: Stri
} }
} }
// 5. 检查是否所有记录的状态都是 "pass"
val allRecordsPassed = stockTakeRecords.isNotEmpty() && val allRecordsPassed = stockTakeRecords.isNotEmpty() &&
stockTakeRecords.all { it.status == "pass" }
stockTakeRecords.all { it.status == "pass" || it.status == "completed" }
val allRecordsCompleted = stockTakeRecords.isNotEmpty() &&
stockTakeRecords.all { it.status == "completed" }
// 6. 如果所有记录都已创建且都是 "pass",更新 stock take 状态为 "approving" // 6. 如果所有记录都已创建且都是 "pass",更新 stock take 状态为 "approving"
if (allLinesHaveRecords && allRecordsPassed) { if (allLinesHaveRecords && allRecordsPassed) {
stockTake.status = StockTakeStatus.APPROVING stockTake.status = StockTakeStatus.APPROVING
stockTake.actualEnd = java.time.LocalDateTime.now()
stockTakeRepository.save(stockTake) stockTakeRepository.save(stockTake)

println("Stock take $stockTakeId status updated to APPROVING - all records are pass") println("Stock take $stockTakeId status updated to APPROVING - all records are pass")
return mapOf( return mapOf(
"success" to true, "success" to true,
"message" to "Stock take status updated to APPROVING", "message" to "Stock take status updated to APPROVING",
"updated" to true "updated" to true
) )
} else if (allLinesHaveRecords && allRecordsCompleted) {
stockTake.status = StockTakeStatus.COMPLETED
stockTake.planEnd = java.time.LocalDateTime.now()
stockTakeRepository.save(stockTake)
println("Stock take $stockTakeId status updated to COMPLETED - all records are completed")
return mapOf("success" to true, "message" to "Stock take status updated to COMPLETED", "updated" to true)
} else { } else {
return mapOf( return mapOf(
"success" to true, "success" to true,
@@ -713,58 +837,60 @@ open fun saveApproverStockTakeRecord(
) ?: throw IllegalArgumentException("Inventory lot not found") ) ?: throw IllegalArgumentException("Inventory lot not found")


if (varianceQty !=BigDecimal.ZERO ) { if (varianceQty !=BigDecimal.ZERO ) {
val stockTakeLine = StockTakeLine().apply {
this.stockTake = stockTake
this.inventoryLotLine = inventoryLotLine
this.initialQty = stockTakeRecord.bookQty
this.finalQty = finalQty
this.status = StockTakeLineStatus.COMPLETED
this.completeDate = java.time.LocalDateTime.now()
val stockTakeLine = StockTakeLine().apply {
this.stockTake = stockTake
this.inventoryLotLine = inventoryLotLine
this.initialQty = stockTakeRecord.bookQty
this.finalQty = finalQty
this.status = StockTakeLineStatus.COMPLETED
this.completeDate = java.time.LocalDateTime.now()


}
stockTakeLineRepository.save(stockTakeLine)
if (varianceQty < BigDecimal.ZERO ) {
val stockOut=StockOut().apply {
this.type="stockTake"
this.status="completed"
this.handler=request.approverId
}
stockOutRepository.save(stockOut)
}
stockTakeLineRepository.save(stockTakeLine)


val stockOutLine = StockOutLine().apply {
this.item=inventoryLot.item
this.qty=(-varianceQty)?.toDouble()
this.stockOut = stockOut
this.inventoryLotLine = inventoryLotLine
this.status = "completed"
if (varianceQty < BigDecimal.ZERO ) {
val stockOut=StockOut().apply {
this.type="stockTake"
this.status="completed"
this.handler=request.approverId
}
stockOutRepository.save(stockOut)


}
stockOutLineRepository.save(stockOutLine)
val stockOutLine = StockOutLine().apply {
this.item=inventoryLot.item
this.qty=(-varianceQty)?.toDouble()
this.stockOut = stockOut
this.inventoryLotLine = inventoryLotLine
this.status = "completed"
this.type = "ADJ"
}
stockOutLineRepository.save(stockOutLine)
} }
if (varianceQty > BigDecimal.ZERO ) { if (varianceQty > BigDecimal.ZERO ) {
val stockIn=StockIn().apply {
this.code=stockTake.code
this.status="completed"
this.stockTake=stockTake
}
stockInRepository.save(stockIn)
val stockInLine = StockInLine().apply {
this.stockTakeLine=stockTakeLine
this.item=inventoryLot.item
this.itemNo=stockTakeRecord.itemCode
this.stockIn = stockIn
this.demandQty=finalQty
this.acceptedQty=finalQty
this.expiryDate=inventoryLot.expiryDate
this.inventoryLot=inventoryLot
this.inventoryLotLine=inventoryLotLine
this.lotNo=inventoryLot.lotNo
this.status = "completed"
val stockIn=StockIn().apply {
this.code=stockTake.code
this.status="completed"
this.stockTake=stockTake
}
stockInRepository.save(stockIn)
val stockInLine = StockInLine().apply {
this.stockTakeLine=stockTakeLine
this.item=inventoryLot.item
this.itemNo=stockTakeRecord.itemCode
this.stockIn = stockIn
this.demandQty=finalQty
this.acceptedQty=finalQty
this.expiryDate=inventoryLot.expiryDate
this.inventoryLot=inventoryLot
this.inventoryLotLine=inventoryLotLine
this.lotNo=inventoryLot.lotNo
this.status = "completed"
this.type = "ADJ"


}
stockInLineRepository.save(stockInLine)
}
stockInLineRepository.save(stockInLine)
} }
// val currentInQty = inventoryLotLine.inQty ?: BigDecimal.ZERO // val currentInQty = inventoryLotLine.inQty ?: BigDecimal.ZERO
// val newInQty = currentInQty.add(variance) // val newInQty = currentInQty.add(variance)
@@ -782,7 +908,10 @@ open fun saveApproverStockTakeRecord(
) )
inventoryLotLineService.saveInventoryLotLine(updateRequest) inventoryLotLineService.saveInventoryLotLine(updateRequest)
} }
val stockTakeSection = savedRecord.stockTakeSection
if (stockTakeSection != null) {
checkAndUpdateStockTakeStatus(stockTakeId, stockTakeSection)
}
return savedRecord return savedRecord
} }


@@ -797,15 +926,15 @@ open fun batchSaveApproverStockTakeRecords(
?: throw IllegalArgumentException("Stock take not found: ${request.stockTakeId}") ?: throw IllegalArgumentException("Stock take not found: ${request.stockTakeId}")
// 2. Get all stock take records for this section where: // 2. Get all stock take records for this section where:
// - secondStockTakeQty is null/0 (no second input)
// - pickerFirstStockTakeQty is not 0 // - pickerFirstStockTakeQty is not 0
// - approverStockTakeQty is null (not yet approved)
val stockTakeRecords = stockTakeRecordRepository.findAll() val stockTakeRecords = stockTakeRecordRepository.findAll()
.filter { .filter {
!it.deleted && !it.deleted &&
it.stockTake?.id == request.stockTakeId && it.stockTake?.id == request.stockTakeId &&
it.stockTakeSection == request.stockTakeSection && it.stockTakeSection == request.stockTakeSection &&
(it.pickerSecondStockTakeQty == null || it.pickerSecondStockTakeQty == BigDecimal.ZERO) &&
it.pickerFirstStockTakeQty != null && it.pickerFirstStockTakeQty!! > BigDecimal.ZERO
it.pickerFirstStockTakeQty != null && it.pickerFirstStockTakeQty!! > BigDecimal.ZERO &&
it.approverStockTakeQty == null // 只处理未审批的记录
} }
println("Found ${stockTakeRecords.size} records to process") println("Found ${stockTakeRecords.size} records to process")
@@ -817,61 +946,47 @@ open fun batchSaveApproverStockTakeRecords(
// 3. Process each record // 3. Process each record
var successCount = 0 var successCount = 0
var errorCount = 0 var errorCount = 0
var skippedCount = 0
val errors = mutableListOf<String>() val errors = mutableListOf<String>()
stockTakeRecords.forEach { record -> stockTakeRecords.forEach { record ->
try { try {
// Use first qty/badQty as approver selection
val qty = record.pickerFirstStockTakeQty ?: BigDecimal.ZERO
val badQty = record.pickerFirstBadQty ?: BigDecimal.ZERO
// Update approver fields
record.apply {
this.approverId = request.approverId
this.approverName = user?.name
this.approverStockTakeQty = qty
this.approverBadQty = badQty
val qty: BigDecimal
val badQty: BigDecimal
if (record.pickerSecondStockTakeQty != null && record.pickerSecondStockTakeQty!! > BigDecimal.ZERO) {
qty = record.pickerSecondStockTakeQty!!
badQty = record.pickerSecondBadQty ?: BigDecimal.ZERO
} else {
qty = record.pickerFirstStockTakeQty ?: BigDecimal.ZERO
badQty = record.pickerFirstBadQty ?: BigDecimal.ZERO
} }
stockTakeRecordRepository.save(record)
// Create stock_take_line and update inventoryLotLine
val inventoryLotLine = record.inventoryLotId?.let {
inventoryLotLineRepository.findByIdAndDeletedIsFalse(it)
} ?: throw IllegalArgumentException("Inventory lot line not found")
val bookQty = record.bookQty ?: BigDecimal.ZERO
val varianceQty = qty.subtract(bookQty)
// Create stock take line
val stockTakeLine = StockTakeLine().apply {
this.stockTake = stockTake
this.inventoryLotLine = inventoryLotLine
this.initialQty = record.bookQty
this.finalQty = qty.add(badQty)
this.status = StockTakeLineStatus.COMPLETED
this.completeDate = java.time.LocalDateTime.now()
this.remarks = "Batch approved by approver"
if (varianceQty.compareTo(BigDecimal.ZERO) != 0) {
skippedCount++
println("Skipping record ${record.id}: variance = $varianceQty (qty=$qty, bookQty=$bookQty)")
return@forEach
} }
stockTakeLineRepository.save(stockTakeLine)
// Update inventoryLotLine
val variance = qty.add(badQty).subtract(record.bookQty ?: BigDecimal.ZERO)
if (variance.compareTo(BigDecimal.ZERO) != 0) {
val currentInQty = inventoryLotLine.inQty ?: BigDecimal.ZERO
val newInQty = currentInQty.add(variance)
val updateRequest = SaveInventoryLotLineRequest(
id = inventoryLotLine.id,
inventoryLotId = inventoryLotLine.inventoryLot?.id,
warehouseId = inventoryLotLine.warehouse?.id,
stockUomId = inventoryLotLine.stockUom?.id,
inQty = newInQty,
outQty = inventoryLotLine.outQty,
holdQty = inventoryLotLine.holdQty,
status = inventoryLotLine.status?.value,
remarks = inventoryLotLine.remarks
)
inventoryLotLineService.saveInventoryLotLine(updateRequest)
// variance = 0,批量保存并设置为 completed
record.apply {
this.approverId = request.approverId
this.approverName = user?.name
this.approverStockTakeQty = qty
this.approverBadQty = badQty
this.varianceQty = varianceQty // 应该是 0
this.status = "completed"
} }
stockTakeRecordRepository.save(record)
successCount++ successCount++
} catch (e: Exception) { } catch (e: Exception) {
errorCount++ errorCount++
@@ -881,14 +996,19 @@ open fun batchSaveApproverStockTakeRecords(
} }
} }
println("batchSaveApproverStockTakeRecords completed: success=$successCount, errors=$errorCount")
// 只在最后调用一次 checkAndUpdateStockTakeStatus
if (successCount > 0) {
checkAndUpdateStockTakeStatus(request.stockTakeId, request.stockTakeSection)
}
println("batchSaveApproverStockTakeRecords completed: success=$successCount, skipped=$skippedCount, errors=$errorCount")
return BatchSaveApproverStockTakeRecordResponse( return BatchSaveApproverStockTakeRecordResponse(
successCount = successCount, successCount = successCount,
errorCount = errorCount, errorCount = errorCount,
errors = errors errors = errors
) )
} }
// 在文件末尾,batchSaveApproverStockTakeRecords 方法之后添加


open fun updateStockTakeRecordStatusToNotMatch(stockTakeRecordId: Long): StockTakeRecord { open fun updateStockTakeRecordStatusToNotMatch(stockTakeRecordId: Long): StockTakeRecord {
println("updateStockTakeRecordStatusToNotMatch called with stockTakeRecordId: $stockTakeRecordId") println("updateStockTakeRecordStatusToNotMatch called with stockTakeRecordId: $stockTakeRecordId")


+ 12
- 1
src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt Просмотреть файл

@@ -1,16 +1,27 @@
// StockTakeRecordReponse.kt // StockTakeRecordReponse.kt
package com.ffii.fpsms.modules.stock.web.model package com.ffii.fpsms.modules.stock.web.model
import com.fasterxml.jackson.annotation.JsonFormat
import java.time.LocalDate import java.time.LocalDate
import java.math.BigDecimal import java.math.BigDecimal
import java.time.LocalDateTime
data class AllPickedStockTakeListReponse( data class AllPickedStockTakeListReponse(
val id: Long, val id: Long,
val stockTakeSession: String, val stockTakeSession: String,
@JsonFormat(pattern = "yyyy-MM-dd")
val lastStockTakeDate: LocalDate?, val lastStockTakeDate: LocalDate?,
val status: String, val status: String,
val currentStockTakeItemNumber: Int, val currentStockTakeItemNumber: Int,
val totalInventoryLotNumber: Int, val totalInventoryLotNumber: Int,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val startTime: LocalDateTime?,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val endTime: LocalDateTime?,
val stockTakeId: Long, val stockTakeId: Long,
val stockTakerName: String?,
val approverName: String?,
val TotalItemNumber: Int,
val ReStockTakeTrueFalse: Boolean,

) )
data class InventoryLotDetailResponse( data class InventoryLotDetailResponse(
val id: Long, val id: Long,


+ 8
- 0
src/main/resources/db/changelog/changes/20260109_enson/01_alter_table.sql Просмотреть файл

@@ -0,0 +1,8 @@
--liquibase formatted sql
--changeset author:add_time_fields_to_productprocessline

ALTER TABLE `stock_in_line`
ADD COLUMN `type` VARCHAR(255) NULL AFTER `remarks`;

ALTER TABLE `stock_out_line`
ADD COLUMN `type` VARCHAR(255) NULL AFTER `pickerId`;

Загрузка…
Отмена
Сохранить