Procházet zdrojové kódy

update stock take

master
CANCERYS\kw093 před 3 týdny
rodič
revize
47c2bf8a8a
14 změnil soubory, kde provedl 428 přidání a 276 odebrání
  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 Zobrazit soubor

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

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 pickOrderEntity = pickOrderRepository.findById(createdPickOrder.id!!).orElse(null)
@@ -450,7 +450,7 @@ open class DeliveryOrderService(
// Debug: Check pick order lines
println("�� DEBUG: Pick order has ${pickOrderEntity.pickOrderLines?.size ?: 0} pick order lines")
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)
println("🔍 DEBUG: Saved ${saveSuggestedPickLots.size} suggested pick lots")
println(" DEBUG: Saved ${saveSuggestedPickLots.size} suggested pick lots")
val insufficientCount = suggestions.suggestedList.count { it.suggestedLotLine == null }
if (insufficientCount > 0) {
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 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 ->
println("🔍 DEBUG: Looking for truck with shop ID: $shopId")
println(" DEBUG: Looking for truck with shop ID: $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 分布
// 分析 DO order lines 中的 items 分布
@@ -553,8 +553,8 @@ open class DeliveryOrderService(
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
val preferredFloor = if ((floorItemCount["4F"] ?: 0) == itemIds.size && (floorItemCount["2F"] ?: 0) == 0) {
@@ -563,13 +563,13 @@ open class DeliveryOrderService(
"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
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)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
println(" DEBUG: Found ${trucks.size} trucks for shop $shopId")


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

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

@@ -612,7 +612,7 @@ open class DeliveryOrderService(
val storeId = "$preferredFloor/F"
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(
storeId = storeId,
@@ -635,7 +635,7 @@ open class DeliveryOrderService(
)

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

@Transactional(rollbackFor = [Exception::class])
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)
?: throw NoSuchElementException("Delivery Order not found")
@@ -1233,7 +1233,7 @@ open class DeliveryOrderService(
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(" - Items with store_id: $totalItemsWithStoreId")
println(" - Items without store_id: ${itemIds.size - totalItemsWithStoreId}")
@@ -1274,15 +1274,15 @@ open class DeliveryOrderService(
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 {
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 ->
println(" - Truck ID=${t.id}, Code=${t.truckLanceCode}, Time=${t.departureTime}")
}


+ 11
- 11
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderAssignmentService.kt Zobrazit soubor

@@ -36,22 +36,22 @@ class DoPickOrderAssignmentService(
"4/F" -> "4/F"
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
println("🔍 DEBUG: assignByLane - Requested date: $requiredDate")
println(" DEBUG: assignByLane - Requested date: $requiredDate")
// 根据是否有日期参数选择不同的查询方法
val allCandidates = if (requiredDate != null) {
println("🔍 DEBUG: Filtering by date: $requiredDate")
println(" DEBUG: Filtering by date: $requiredDate")
doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
actualStoreId,
requiredDate,
listOf(DoPickOrderStatus.pending)
)
} else {
println("🔍 DEBUG: No date filter applied")
println(" DEBUG: No date filter applied")
doPickOrderRepository.findByStoreIdAndTicketStatusOrderByTruckDepartureTimeAsc(
actualStoreId,
DoPickOrderStatus.pending
@@ -60,18 +60,18 @@ class DoPickOrderAssignmentService(
.filter { it.truckLanceCode == request.truckLanceCode }
.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 的记录
val filteredCandidates = allCandidates.filter { doPickOrder ->
val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!)
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
}
println("🔍 DEBUG: After filtering, ${filteredCandidates.size} do_pick_orders remain")
println(" DEBUG: After filtering, ${filteredCandidates.size} do_pick_orders remain")
if (filteredCandidates.isEmpty()) {
return MessageResponse(
@@ -92,7 +92,7 @@ class DoPickOrderAssignmentService(
// 获取这个 do_pick_order 下的所有 pick orders 并分配给用户
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 ->
if (line.pickOrderId != null) {
@@ -101,7 +101,7 @@ class DoPickOrderAssignmentService(
pickOrder.assignTo = user
pickOrder.status = PickOrderStatus.RELEASED
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 {
println("⚠️ WARNING: Pick order ${line.pickOrderId} not found")
}
@@ -120,7 +120,7 @@ class DoPickOrderAssignmentService(
}
if (records.isNotEmpty()) {
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
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


+ 8
- 8
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderQueryService.kt Zobrazit soubor

@@ -20,7 +20,7 @@ class DoPickOrderQueryService(
fun getSummaryByStore(storeId: String, requiredDate: LocalDate?, releaseType: String): StoreLaneSummary {
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) {
"2/F" -> "2/F"
@@ -56,16 +56,16 @@ class DoPickOrderQueryService(
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)
val filteredActiveRecords = filteredActiveRecordsByReleaseType.filter { doPickOrder ->
val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!)
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
}
@@ -74,7 +74,7 @@ class DoPickOrderQueryService(
val filteredCompletedRecords = filteredCompletedRecordsByReleaseType.filter { record ->
val hasNonIssueLines = checkDoPickOrderRecordHasNonIssueLines(record.id!!)
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
}
@@ -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 }
.mapValues { (_, list) ->


+ 25
- 25
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt Zobrazit soubor

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

private fun getOrderedDeliveryOrderIds(ids: List<Long>): List<Long> {
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 sql = """
WITH DoFloorCounts AS (
@@ -470,24 +470,24 @@ class DoReleaseCoordinatorService(
""".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)
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()) {
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 ->
(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()) {
println("⚠️ WARNING: No sorted IDs, using original order")
@@ -518,7 +518,7 @@ class DoReleaseCoordinatorService(
try {
println("📦 Starting batch release for ${ids.size} orders")
val sortedIds = getOrderedDeliveryOrderIds(ids)
println("🔍 DEBUG: Got ${sortedIds.size} sorted orders")
println(" DEBUG: Got ${sortedIds.size} sorted orders")

val releaseResults = mutableListOf<ReleaseDoResult>()

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

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

// 第三步:为每组创建一个 DoPickOrder 和多条 DoPickOrderLine
grouped.forEach { (key, group) ->
try {
createMergedDoPickOrder(group)
println("🔍 DEBUG: Created DoPickOrder for ${group.size} DOs")
println(" DEBUG: Created DoPickOrder for ${group.size} DOs")
} catch (e: Exception) {
println("❌ Error creating DoPickOrder: ${e.message}")
e.printStackTrace()
@@ -653,7 +653,7 @@ class DoReleaseCoordinatorService(
// 直接使用 doPickOrderRepository.save() 而不是 doPickOrderService.save()
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 一条)
@@ -674,7 +674,7 @@ class DoReleaseCoordinatorService(
status = "pending" // 初始状态
}
doPickOrderLineRepository.save(line)
println("🔍 DEBUG: Created DoPickOrderLine for pick order ${result.pickOrderId}")
println(" DEBUG: Created DoPickOrderLine for pick order ${result.pickOrderId}")
}
// 现在检查整个 DoPickOrder 是否有库存问题
@@ -686,10 +686,10 @@ class DoReleaseCoordinatorService(
line.status = "issue"
}
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 {
try {
@@ -724,7 +724,7 @@ class DoReleaseCoordinatorService(
// 3. 只有当所有 pick orders 都有问题时才算 issue
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
@@ -811,7 +811,7 @@ class DoReleaseCoordinatorService(
status = "pending"
}
doPickOrderLineRepository.save(line)
println("🔍 DEBUG: Created DoPickOrderLine for existing DoPickOrder ${existingDoPickOrder.id}")
println(" DEBUG: Created DoPickOrderLine for existing DoPickOrder ${existingDoPickOrder.id}")
}
} else {
// 如果不存在,创建新的 do_pick_order
@@ -843,7 +843,7 @@ class DoReleaseCoordinatorService(
status = "pending"
}
doPickOrderLineRepository.save(line)
println("🔍 DEBUG: Created new DoPickOrder with releaseType=single")
println(" DEBUG: Created new DoPickOrder with releaseType=single")
}
// 更新 ticket numbers(只更新 single 类型的)
@@ -873,11 +873,11 @@ class DoReleaseCoordinatorService(
}
if (tempTickets.isEmpty()) {
println("🔍 No single release type tickets to update")
println(" No single release type tickets to update")
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 分组
val grouped = tempTickets.groupBy { ticket ->
@@ -918,7 +918,7 @@ class DoReleaseCoordinatorService(
} else null
}.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 排序
val sortedTickets = tickets.sortedWith(
@@ -948,7 +948,7 @@ class DoReleaseCoordinatorService(
existingNumbers.add(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 Zobrazit soubor

@@ -260,7 +260,7 @@ open class JoPickOrderService(
statusList
).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
val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) {
@@ -271,7 +271,7 @@ open class JoPickOrderService(

if (assignedReleasedOrders.isNotEmpty()) {
// 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
} else {
// If no assigned RELEASED orders, show only the latest COMPLETED order
@@ -279,10 +279,10 @@ open class JoPickOrderService(
if (completedOrders.isNotEmpty()) {
val latestCompleted =
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)
} else {
println("🔍 DEBUG: No job orders found")
println(" DEBUG: No job orders found")
emptyList()
}
}
@@ -569,7 +569,7 @@ open class JoPickOrderService(
.findAllByAssignToIdAndStatusIn(userId, listOf(PickOrderStatus.COMPLETED))
.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()) {
return mapOf("pickOrder" to null, "pickOrderLines" to emptyList<Map<String, Any?>>())
@@ -580,7 +580,7 @@ open class JoPickOrderService(
it.completeDate ?: it.modified ?: LocalDateTime.MIN
} ?: 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 jobOrder = pickOrder.jobOrder!!
@@ -1524,8 +1524,8 @@ open fun getCompletedJobOrderPickOrderLotDetails(pickOrderId: Long): List<Map<St
il.lotNo ASC
""".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))
@@ -1733,8 +1733,8 @@ open fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId: Lo
il.lotNo ASC
""".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))


+ 74
- 74
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt Zobrazit soubor

@@ -1286,8 +1286,8 @@ open class PickOrderService(
doPickOrderLineRepository.findByPickOrderIdAndDeletedFalse(pickOrderId)
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()) {
println("ℹ️ INFO: No do_pick_order records found - skipping record copying")
@@ -1302,13 +1302,13 @@ open class PickOrderService(
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
val allDoPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(dpo.id!!)
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 的状态
val pickOrderStatuses = allPickOrderIdsInDpo.map { poId ->
@@ -1317,7 +1317,7 @@ open class PickOrderService(
}
pickOrderStatuses.forEach { (poId, status) ->
println("🔍 DEBUG: Pick order $poId status: $status")
println(" DEBUG: Pick order $poId status: $status")
}
// 只有当所有 pick orders 都是 COMPLETED 状态时,才移动到 record 表
@@ -1327,7 +1327,7 @@ open class PickOrderService(
if (!allPickOrdersCompleted) {
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,不删除它
}
@@ -1654,7 +1654,7 @@ open class PickOrderService(

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

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

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

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

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

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

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(
id = null,
name = "User already has pick orders",
@@ -1961,14 +1961,14 @@ open class PickOrderService(

// Update do_pick_order_record entries
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()) {
existingRecords.forEach { record ->
record.handledBy = user.id
record.ticketStatus = DoPickOrderStatus.released
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)
println(" Updated ${existingRecords.size} existing DoPickOrderRecord entries")
@@ -2108,7 +2108,7 @@ open class PickOrderService(
i.code ASC
""".trimIndent()

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

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
val consoCode = pickOrder.consoCode
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")
true // No consoCode means not completed
} else {
@@ -2501,9 +2501,9 @@ open class PickOrderService(
).filter { it.deliveryOrder != null }

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 ->
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(
id = null,
@@ -2624,15 +2624,15 @@ open class PickOrderService(
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
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
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)
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 }
println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
println(" DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
selectedTruck
}

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

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

val doPickOrderRecord = DoPickOrderRecord(
id=dopickorder.id,
@@ -2691,10 +2691,10 @@ open class PickOrderService(
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)
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)

).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!! }
println("🔍 DEBUG: All assigned pick orders: ${pickOrderIds.size}")
println(" DEBUG: All assigned pick orders: ${pickOrderIds.size}")
println(" Pick order IDs to fetch: $pickOrderIds")

if (pickOrderIds.isEmpty()) {
@@ -2883,7 +2883,7 @@ open class PickOrderService(
il.lotNo ASC
""".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")

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

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

// Use repository to find pick orders with type 'do'
val pickOrders = pickOrderRepository.findAll().filter {
@@ -2911,7 +2911,7 @@ open class PickOrderService(
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 deliveryOrder = po.deliveryOrder
@@ -2968,7 +2968,7 @@ open class PickOrderService(

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

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

@@ -3028,11 +3028,11 @@ open class PickOrderService(
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 ->
println("🔍 DEBUG: Result $index:")
println(" DEBUG: Result $index:")
println(" - doPickOrderId: ${row["doPickOrderId"]}")
println(" - pickOrderIds: ${row["pickOrderIds"]}")
println(" - numberOfPickOrders: ${row["numberOfPickOrders"]}")
@@ -3088,7 +3088,7 @@ open class PickOrderService(

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

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

@@ -3097,7 +3097,7 @@ open class PickOrderService(
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") {
println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}")
@@ -3117,16 +3117,16 @@ open class PickOrderService(
val supplier = deliveryOrder?.supplier

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
val truck = if (shop?.id != null) {
try {
println("🔍 Querying truck repository for shopId: ${shop.id}")
println(" Querying truck repository for shopId: ${shop.id}")

// Get all trucks for this shop
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 ->
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 doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: ""
println("🔍 Found ticket number: $ticketNo for pick order $pickOrderId")
println(" Found ticket number: $ticketNo for pick order $pickOrderId")
ticketNo
} catch (e: Exception) {
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?>> {
try {
println("🔍 Starting getnewFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId")
println(" Starting getnewFgPickOrdersByPickOrderId method with pickOrderId: $pickOrderId")

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

@@ -3209,7 +3209,7 @@ open class PickOrderService(
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") {
println("❌ Pick order is not of type 'do': ${pickOrder.type?.value}")
@@ -3229,16 +3229,16 @@ open class PickOrderService(
val supplier = deliveryOrder?.supplier

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
val truck = if (shop?.id != null) {
try {
println("🔍 Querying truck repository for shopId: ${shop.id}")
println(" Querying truck repository for shopId: ${shop.id}")

// Get all trucks for this shop
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 ->
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 doPickOrders = doPickOrderRepository.findByPickOrderId(pickOrderId)
val ticketNo = doPickOrders.firstOrNull()?.ticketNo ?: ""
println("🔍 Found ticket number: $ticketNo for pick order $pickOrderId")
println(" Found ticket number: $ticketNo for pick order $pickOrderId")
ticketNo
} catch (e: Exception) {
println("⚠️ Error getting ticket number for pick order $pickOrderId: ${e.message}")
@@ -3342,9 +3342,9 @@ open class PickOrderService(
user,
listOf(PickOrderStatus.PENDING, PickOrderStatus.RELEASED, PickOrderStatus.COMPLETED)
).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 ->
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
val filteredPickOrders = if (allAssignedPickOrders.isNotEmpty()) {
@@ -3355,7 +3355,7 @@ open class PickOrderService(

if (assignedReleasedOrders.isNotEmpty()) {
// 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
} else {
// 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}")
listOfNotNull(latestCompleted)
} else {
println("🔍 DEBUG: No orders found")
println(" DEBUG: No orders found")
emptyList()
}
}
@@ -3523,7 +3523,7 @@ ORDER BY
il.lotNo ASC
""".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")

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 }
// 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)
val doPickOrder = doPickOrderRepository.findById(doPickOrderIds.first()).orElse(null)
@@ -3661,13 +3661,13 @@ ORDER BY
}
val doPickOrderId = doPickOrder.id!!
println("🔍 Using do_pick_order ID: $doPickOrderId")
println(" Using do_pick_order ID: $doPickOrderId")
// Step 4: 使用 Repository 加载 pick orders 及其关联数据
val pickOrders = pickOrderRepository.findAllById(pickOrderIds)
.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()
println("🔍 Found do_pick_order ID: $doPickOrderId")
println(" Found do_pick_order ID: $doPickOrderId")
val doTicketStatus = doPickOrderInfo["ticket_status"]
// Step 2: 获取该 do_pick_order 下的所有 pick orders
val pickOrdersSql = """
@@ -4058,7 +4058,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String
""".trimIndent()
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
val allPickOrderLines = mutableListOf<Map<String, Any?>>()
@@ -4201,7 +4201,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchicalold(userId: Long): Map<String
""".trimIndent()
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 sol polIds in linesResults: " + linesResults.mapNotNull { it["stockOutLineId"]?.let { _ -> it["pickOrderLineId"] } }.distinct())
// 按 pickOrderLineId 分组
@@ -4377,8 +4377,8 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto
ORDER BY orderDate ASC
""".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))
println(" Found ${results.size} records")
@@ -4743,7 +4743,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
""".trimIndent()
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
val pickOrders = pickOrdersInfo.map { poInfo ->
@@ -5082,7 +5082,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
pickOrders = emptyList()
)
println("🔍 Found DoPickOrderRecord: id=${dpor.id}, ticketNo=${dpor.ticketNo}")
println(" Found DoPickOrderRecord: id=${dpor.id}, ticketNo=${dpor.ticketNo}")
// 2) 构建 fgInfo
val fgInfo = FgInfoResponse(
@@ -5097,7 +5097,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
// 3) 通过 DoPickOrderLineRecord 获取 pickOrderIds
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()
@@ -5115,7 +5115,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
)
}
println("🔍 Using pickOrderIds: $pickOrderIds")
println(" Using pickOrderIds: $pickOrderIds")
// 4) 批量加载所有相关数据
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
val allPickOrderLineIds = pickOrders
@@ -5137,7 +5137,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
.filter { !it.deleted }
.mapNotNull { it.id }
println("🔍 Found ${allPickOrderLineIds.size} pick order lines")
println(" Found ${allPickOrderLineIds.size} pick order lines")
// 6) 批量加载 suggestions 和 stock out lines
val allSuggestions = if (allPickOrderLineIds.isNotEmpty()) {
@@ -5317,7 +5317,7 @@ open fun getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId: Long): Map<Stri
// 新增:从 do_pick_order_record 表查询(用于已完成的 pick orders)
open fun getFgPickOrdersFromRecordByPickOrderId(pickOrderId: Long): List<Map<String, Any?>> {
try {
println("🔍 Starting getFgPickOrdersFromRecordByPickOrderId with pickOrderId: $pickOrderId")
println(" Starting getFgPickOrdersFromRecordByPickOrderId with pickOrderId: $pickOrderId")

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


+ 7
- 7
src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt Zobrazit soubor

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

return productProcessRepository.findById(id)
.orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") }
}
open fun findByCode(code: String): ProductProcess {
println("🔍 Service: Finding ProductProcess by code: $code")
println(" Service: Finding ProductProcess by code: $code")
return productProcessRepository.findByProductProcessCode(code)
.orElseThrow { IllegalArgumentException("ProductProcess not found with code: $code") }
}
@@ -126,7 +126,7 @@ open class ProductProcessService(
// 4. 查询 BOM 的所有工序步骤
val bomProcesses = bomProcessRepository.findByBomIdOrderBySeqNo(request.bomId)
println("🔍 Service: Found ${bomProcesses.size} BOM processes")
println(" Service: Found ${bomProcesses.size} BOM processes")
// 5. 为每个 BOM Process 创建 ProductProcessLine
bomProcesses.forEachIndexed { index, bomProcess -> // 修复 forEach
@@ -274,14 +274,14 @@ open class ProductProcessService(
return issues
}
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)
println(" Service: Found ${result.size} processes")
return result
}
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 result = processes.map { process ->
@@ -338,7 +338,7 @@ open class ProductProcessService(
}
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)
.orElseThrow { IllegalArgumentException("ProductProcess not found with id: $id") }
@@ -480,7 +480,7 @@ open class ProductProcessService(
return saved
}
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)
println(" Service: Found ${lines.size} pending lines")
return lines


+ 4
- 4
src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt Zobrazit soubor

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

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

@GetMapping("/code/{code}")
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)
println(" Controller: Found ID: ${result.id}")
return result
@@ -128,7 +128,7 @@ class ProductProcessController(

@GetMapping("/by-job-order/{jobOrderId}")
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 方法
println(" Controller: Found ${result.size} processes for Job Order $jobOrderId")
return result
@@ -137,7 +137,7 @@ class ProductProcessController(
// 额外添加:获取带 lines 的完整数据
@GetMapping("/by-job-order/{jobOrderId}/with-lines")
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)
println(" Controller: Found ${result.size} processes with lines for Job Order $jobOrderId")
return result


+ 7
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/InventoryLotLineRepository.kt Zobrazit soubor

@@ -63,4 +63,11 @@ fun findAllByWarehouseIdInAndDeletedIsFalse(@Param("warehouseIds") warehouseIds:
ORDER BY ill.inventoryLot.item.code, ill.inventoryLot.lotNo
""")
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 Zobrazit soubor

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

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

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


+ 3
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLine.kt Zobrazit soubor

@@ -45,4 +45,7 @@ open class StockOutLine: BaseEntity<Long>() {
@ManyToOne
@JoinColumn(name = "pickOrderLineId")
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 Zobrazit soubor

@@ -97,9 +97,9 @@ class StockTakeRecordService(
.filter { it.status == StockTakeStatus.COMPLETED && it.actualEnd != null }
.sortedByDescending { it.actualEnd }
val lastStockTakeDate = completedStockTakes.firstOrNull()?.actualEnd?.toLocalDate()
val lastStockTakeDate = completedStockTakes.firstOrNull()?.actualEnd
// 7. 获取 status:获取最新的 stock_take 记录(按 actualStart 或 planStart 排序)
val latestStockTake = stockTakesForSection
.maxByOrNull { it.actualStart ?: it.planStart ?: LocalDateTime.MIN }
@@ -108,17 +108,65 @@ class StockTakeRecordService(
} else {
"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
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(
AllPickedStockTakeListReponse(
id = idCounter++,
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 {
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
result.add(
AllPickedStockTakeListReponse(
id = idCounter++,
stockTakeSession = stockTakeSection,
lastStockTakeDate = lastStockTakeDate,
lastStockTakeDate = latestStockTake?.actualStart?.toLocalDate(),
status = status?:"",
currentStockTakeItemNumber = 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
} else {
// 创建新记录(第一次盘点)
// 第一次盘点不验证 QTY + Bad QTY 是否匹配,允许不匹配的情况
// 如果匹配,status = "1",如果不匹配,status = "2"

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

// 检查并更新 stock take 状态
// 检查并更新 stock take 状态
open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: String): Map<String, Any> {
try {
val stockTake = stockTakeRepository.findByIdAndDeletedIsFalse(stockTakeId)
@@ -629,20 +744,29 @@ open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: Stri
}
}
// 5. 检查是否所有记录的状态都是 "pass"
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"
if (allLinesHaveRecords && allRecordsPassed) {
stockTake.status = StockTakeStatus.APPROVING
stockTake.actualEnd = java.time.LocalDateTime.now()
stockTakeRepository.save(stockTake)

println("Stock take $stockTakeId status updated to APPROVING - all records are pass")
return mapOf(
"success" to true,
"message" to "Stock take status updated to APPROVING",
"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 {
return mapOf(
"success" to true,
@@ -713,58 +837,60 @@ open fun saveApproverStockTakeRecord(
) ?: throw IllegalArgumentException("Inventory lot not found")

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 ) {
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 newInQty = currentInQty.add(variance)
@@ -782,7 +908,10 @@ open fun saveApproverStockTakeRecord(
)
inventoryLotLineService.saveInventoryLotLine(updateRequest)
}
val stockTakeSection = savedRecord.stockTakeSection
if (stockTakeSection != null) {
checkAndUpdateStockTakeStatus(stockTakeId, stockTakeSection)
}
return savedRecord
}

@@ -797,15 +926,15 @@ open fun batchSaveApproverStockTakeRecords(
?: throw IllegalArgumentException("Stock take not found: ${request.stockTakeId}")
// 2. Get all stock take records for this section where:
// - secondStockTakeQty is null/0 (no second input)
// - pickerFirstStockTakeQty is not 0
// - approverStockTakeQty is null (not yet approved)
val stockTakeRecords = stockTakeRecordRepository.findAll()
.filter {
!it.deleted &&
it.stockTake?.id == request.stockTakeId &&
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")
@@ -817,61 +946,47 @@ open fun batchSaveApproverStockTakeRecords(
// 3. Process each record
var successCount = 0
var errorCount = 0
var skippedCount = 0
val errors = mutableListOf<String>()
stockTakeRecords.forEach { record ->
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++
} catch (e: Exception) {
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(
successCount = successCount,
errorCount = errorCount,
errors = errors
)
}
// 在文件末尾,batchSaveApproverStockTakeRecords 方法之后添加

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


+ 12
- 1
src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt Zobrazit soubor

@@ -1,16 +1,27 @@
// StockTakeRecordReponse.kt
package com.ffii.fpsms.modules.stock.web.model
import com.fasterxml.jackson.annotation.JsonFormat
import java.time.LocalDate
import java.math.BigDecimal
import java.time.LocalDateTime
data class AllPickedStockTakeListReponse(
val id: Long,
val stockTakeSession: String,
@JsonFormat(pattern = "yyyy-MM-dd")
val lastStockTakeDate: LocalDate?,
val status: String,
val currentStockTakeItemNumber: 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 stockTakerName: String?,
val approverName: String?,
val TotalItemNumber: Int,
val ReStockTakeTrueFalse: Boolean,

)
data class InventoryLotDetailResponse(
val id: Long,


+ 8
- 0
src/main/resources/db/changelog/changes/20260109_enson/01_alter_table.sql Zobrazit soubor

@@ -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`;

Načítá se…
Zrušit
Uložit