|
|
@@ -21,6 +21,16 @@ import java.math.BigDecimal |
|
|
import java.time.LocalDate |
|
|
import java.time.LocalDate |
|
|
import java.time.LocalDateTime |
|
|
import java.time.LocalDateTime |
|
|
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository |
|
|
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository |
|
|
|
|
|
import com.ffii.core.support.JdbcDao |
|
|
|
|
|
import com.ffii.fpsms.modules.stock.entity.StockOutRepository |
|
|
|
|
|
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLineRepository |
|
|
|
|
|
import com.ffii.fpsms.modules.deliveryOrder.service.DoPickOrderService |
|
|
|
|
|
import com.ffii.fpsms.modules.jobOrder.entity.JoPickOrderRepository |
|
|
|
|
|
import com.ffii.fpsms.modules.jobOrder.entity.JoPickOrderRecordRepository |
|
|
|
|
|
import com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus |
|
|
|
|
|
import com.ffii.fpsms.modules.stock.web.model.StockOutStatus |
|
|
|
|
|
import com.ffii.fpsms.modules.pickOrder.enums.PickOrderLineStatus |
|
|
|
|
|
import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus |
|
|
@Service |
|
|
@Service |
|
|
open class PickExecutionIssueService( |
|
|
open class PickExecutionIssueService( |
|
|
private val pickExecutionIssueRepository: PickExecutionIssueRepository, |
|
|
private val pickExecutionIssueRepository: PickExecutionIssueRepository, |
|
|
@@ -28,7 +38,14 @@ open class PickExecutionIssueService( |
|
|
private val inventoryLotLineRepository: InventoryLotLineRepository, |
|
|
private val inventoryLotLineRepository: InventoryLotLineRepository, |
|
|
private val inventoryRepository: InventoryRepository, |
|
|
private val inventoryRepository: InventoryRepository, |
|
|
private val suggestedPickLotService: SuggestedPickLotService, |
|
|
private val suggestedPickLotService: SuggestedPickLotService, |
|
|
private val pickOrderRepository: PickOrderRepository |
|
|
|
|
|
|
|
|
private val pickOrderRepository: PickOrderRepository, |
|
|
|
|
|
private val jdbcDao: JdbcDao, |
|
|
|
|
|
private val stockOutRepository: StockOutRepository, |
|
|
|
|
|
private val pickOrderLineRepository: PickOrderLineRepository, |
|
|
|
|
|
private val doPickOrderService: DoPickOrderService, |
|
|
|
|
|
private val joPickOrderRepository: JoPickOrderRepository, |
|
|
|
|
|
private val joPickOrderRecordRepository: JoPickOrderRecordRepository |
|
|
|
|
|
|
|
|
) { |
|
|
) { |
|
|
|
|
|
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
@@ -137,7 +154,19 @@ open class PickExecutionIssueService( |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val pickOrderForCompletion = pickOrderRepository.findById(request.pickOrderId).orElse(null) |
|
|
|
|
|
val consoCode = pickOrderForCompletion?.consoCode |
|
|
|
|
|
|
|
|
|
|
|
if (consoCode != null) { |
|
|
|
|
|
println("🔍 Checking if pick order $consoCode should be completed after lot rejection...") |
|
|
|
|
|
try { |
|
|
|
|
|
checkAndCompletePickOrder(consoCode) |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
println("⚠️ Error checking pick order completion: ${e.message}") |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return MessageResponse( |
|
|
return MessageResponse( |
|
|
id = savedIssue.id, |
|
|
id = savedIssue.id, |
|
|
name = "Pick execution issue recorded successfully", |
|
|
name = "Pick execution issue recorded successfully", |
|
|
@@ -185,6 +214,137 @@ open class PickExecutionIssueService( |
|
|
// 格式化为 SKO-YYMM-001 |
|
|
// 格式化为 SKO-YYMM-001 |
|
|
return "SKO-${yearMonth}-${nextSequence.toString().padStart(3, '0')}" |
|
|
return "SKO-${yearMonth}-${nextSequence.toString().padStart(3, '0')}" |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) |
|
|
|
|
|
private fun checkAndCompletePickOrder(consoCode: String) { |
|
|
|
|
|
println("=== DEBUG: checkAndCompletePickOrder ===") |
|
|
|
|
|
println("consoCode: $consoCode") |
|
|
|
|
|
|
|
|
|
|
|
// 1. 查找 StockOut |
|
|
|
|
|
val stockOut = stockOutRepository.findByConsoPickOrderCode(consoCode).orElse(null) |
|
|
|
|
|
if (stockOut == null) { |
|
|
|
|
|
println("❌ No stock_out found for consoCode: $consoCode") |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 2. 查找所有相关的 stock out lines |
|
|
|
|
|
val stockOutLinesSql = """ |
|
|
|
|
|
SELECT sol.* |
|
|
|
|
|
FROM stock_out_line sol |
|
|
|
|
|
JOIN pick_order_line pol ON pol.id = sol.pickOrderLineId |
|
|
|
|
|
JOIN pick_order po ON po.id = pol.poId |
|
|
|
|
|
WHERE po.consoCode = :consoCode |
|
|
|
|
|
AND sol.deleted = false |
|
|
|
|
|
""".trimIndent() |
|
|
|
|
|
|
|
|
|
|
|
val stockOutLinesResult = jdbcDao.queryForList(stockOutLinesSql, mapOf("consoCode" to consoCode)) |
|
|
|
|
|
val stockOutLineIds = stockOutLinesResult.mapNotNull { row -> |
|
|
|
|
|
when (val id = row["id"]) { |
|
|
|
|
|
is Number -> id.toLong() |
|
|
|
|
|
is String -> id.toLongOrNull() |
|
|
|
|
|
else -> null |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
val stockOutLines = if (stockOutLineIds.isNotEmpty()) { |
|
|
|
|
|
stockOutLineRepository.findAllById(stockOutLineIds) |
|
|
|
|
|
} else { |
|
|
|
|
|
emptyList() |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
println("Total stock out lines for consoCode $consoCode: ${stockOutLines.size}") |
|
|
|
|
|
|
|
|
|
|
|
// 3. 检查是否有未完成的行 |
|
|
|
|
|
val unfinishedLines = stockOutLines.filter { |
|
|
|
|
|
it.status != StockOutLineStatus.COMPLETE.status |
|
|
|
|
|
&& it.status != StockOutLineStatus.REJECTED.status |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
println("📊 Stock out lines: ${stockOutLines.size}, Unfinished: ${unfinishedLines.size}") |
|
|
|
|
|
|
|
|
|
|
|
// 4. 如果所有行都完成或被拒绝,则完成 pick order |
|
|
|
|
|
if (unfinishedLines.isEmpty()) { |
|
|
|
|
|
println("✅ All stock out lines completed or rejected, completing pick order...") |
|
|
|
|
|
|
|
|
|
|
|
// 4.1 更新 StockOut 状态 |
|
|
|
|
|
stockOut.status = StockOutStatus.COMPLETE.status |
|
|
|
|
|
stockOutRepository.saveAndFlush(stockOut) |
|
|
|
|
|
|
|
|
|
|
|
// 4.2 更新所有 pick order lines 状态 |
|
|
|
|
|
val completedPickOrderLineIds = stockOutLines.mapNotNull { it.pickOrderLine?.id } |
|
|
|
|
|
println("Completed pick order line IDs: $completedPickOrderLineIds") |
|
|
|
|
|
|
|
|
|
|
|
if (completedPickOrderLineIds.isNotEmpty()) { |
|
|
|
|
|
val pickOrderLines = pickOrderLineRepository.findAllById(completedPickOrderLineIds) |
|
|
|
|
|
pickOrderLines.forEach { line -> |
|
|
|
|
|
line.status = PickOrderLineStatus.COMPLETED |
|
|
|
|
|
println("Updated pick order line ${line.id} to COMPLETED") |
|
|
|
|
|
} |
|
|
|
|
|
pickOrderLineRepository.saveAll(pickOrderLines) |
|
|
|
|
|
println("✅ Updated ${pickOrderLines.size} pick order lines to COMPLETED status") |
|
|
|
|
|
|
|
|
|
|
|
// 4.3 获取所有受影响的 pick orders |
|
|
|
|
|
val pickOrderIds = pickOrderLines.mapNotNull { it.pickOrder?.id }.distinct() |
|
|
|
|
|
println("Affected pick order IDs: $pickOrderIds") |
|
|
|
|
|
|
|
|
|
|
|
// 4.4 检查每个 pick order 是否完全完成 |
|
|
|
|
|
pickOrderIds.forEach { pickOrderId -> |
|
|
|
|
|
val pickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) |
|
|
|
|
|
if (pickOrder != null) { |
|
|
|
|
|
// 检查这个 pick order 的所有行是否都完成了 |
|
|
|
|
|
val allLines = pickOrder.pickOrderLines |
|
|
|
|
|
val completedLines = allLines.filter { it.status == PickOrderLineStatus.COMPLETED } |
|
|
|
|
|
|
|
|
|
|
|
println("Pick order ${pickOrder.code}: ${completedLines.size}/${allLines.size} lines completed") |
|
|
|
|
|
|
|
|
|
|
|
if (completedLines.size == allLines.size && allLines.isNotEmpty()) { |
|
|
|
|
|
// 所有行都完成了,更新 pick order 状态 |
|
|
|
|
|
pickOrder.status = PickOrderStatus.COMPLETED |
|
|
|
|
|
pickOrder.completeDate = LocalDateTime.now() |
|
|
|
|
|
pickOrderRepository.save(pickOrder) |
|
|
|
|
|
println("✅ Updated pick order ${pickOrder.code} to COMPLETED status") |
|
|
|
|
|
|
|
|
|
|
|
// 4.5 处理 DO pick order 相关记录 |
|
|
|
|
|
try { |
|
|
|
|
|
val removedCount = doPickOrderService.removeDoPickOrdersForPickOrder(pickOrderId) |
|
|
|
|
|
println("✅ Removed $removedCount do_pick_order records for completed pick order ${pickOrderId}") |
|
|
|
|
|
|
|
|
|
|
|
doPickOrderService.completeDoPickOrderRecordsForPickOrder(pickOrderId) |
|
|
|
|
|
println("✅ Updated do_pick_order_record status to COMPLETED for pick order ${pickOrderId}") |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
println("⚠️ Error updating DO pick order records: ${e.message}") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 4.6 处理 JO pick order 相关记录 |
|
|
|
|
|
if (pickOrder.jobOrder != null) { |
|
|
|
|
|
try { |
|
|
|
|
|
val joPickOrders = joPickOrderRepository.findByPickOrderId(pickOrderId) |
|
|
|
|
|
joPickOrders.forEach { |
|
|
|
|
|
it.ticketCompleteTime = LocalDateTime.now() |
|
|
|
|
|
} |
|
|
|
|
|
joPickOrderRepository.saveAll(joPickOrders) |
|
|
|
|
|
|
|
|
|
|
|
val joPickOrderRecords = joPickOrderRecordRepository.findByPickOrderId(pickOrderId) |
|
|
|
|
|
joPickOrderRecords.forEach { |
|
|
|
|
|
it.ticketCompleteTime = LocalDateTime.now() |
|
|
|
|
|
} |
|
|
|
|
|
joPickOrderRecordRepository.saveAll(joPickOrderRecords) |
|
|
|
|
|
|
|
|
|
|
|
println("✅ Set jo_pick_order ticketCompleteTime for pick order ${pickOrderId}") |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
println("⚠️ Error updating JO pick order records: ${e.message}") |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
println("🎉 Pick order completed successfully!") |
|
|
|
|
|
} else { |
|
|
|
|
|
println("⏳ Still have ${unfinishedLines.size} unfinished lines, pick order not completed yet") |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
// FPSMS-backend/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt |
|
|
// FPSMS-backend/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt |
|
|
// ✅ 修复:处理有部分拣货但有 miss item 的情况 |
|
|
// ✅ 修复:处理有部分拣货但有 miss item 的情况 |
|
|
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) |
|
|
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) |
|
|
|