@@ -74,9 +74,23 @@ open class PickExecutionIssueService(
@Value("\${pick.execution.auto-resuggest-on-rejection:false}")
@Value("\${pick.execution.auto-resuggest-on-rejection:false}")
private val autoResuggestOnLotRejection: Boolean = false
private val autoResuggestOnLotRejection: Boolean = false
@Transactional(rollbackFor = [Exception::class])
open fun recordPickExecutionIssue(request: PickExecutionIssueRequest): MessageResponse {
open fun recordPickExecutionIssue(request: PickExecutionIssueRequest): MessageResponse {
try {
try {
println("=== recordPickExecutionIssue: START ===")
println("Request details:")
println(" pickOrderId: ${request.pickOrderId}")
println(" pickOrderLineId: ${request.pickOrderLineId}")
println(" itemId: ${request.itemId}")
println(" itemCode: ${request.itemCode}")
println(" lotId: ${request.lotId}")
println(" lotNo: ${request.lotNo}")
println(" requiredQty: ${request.requiredQty}")
println(" actualPickQty: ${request.actualPickQty}")
println(" missQty: ${request.missQty}")
println(" badItemQty: ${request.badItemQty}")
println(" badReason: ${request.badReason}")
println(" issueCategory: ${request.issueCategory}")
println("========================================")
// 1. 检查是否已经存在相同的 pick execution issue 记录
// 1. 检查是否已经存在相同的 pick execution issue 记录
val existingIssues = pickExecutionIssueRepository.findByPickOrderLineIdAndLotIdAndDeletedFalse(
val existingIssues = pickExecutionIssueRepository.findByPickOrderLineIdAndLotIdAndDeletedFalse(
@@ -84,7 +98,14 @@ open class PickExecutionIssueService(
request.lotId ?: 0L
request.lotId ?: 0L
)
)
println("Checking for existing issues...")
println(" Found ${existingIssues.size} existing issues")
existingIssues.forEachIndexed { index, issue ->
println(" Existing[$index]: id=${issue.id}, issueNo=${issue.issueNo}, handleStatus=${issue.handleStatus}, issueQty=${issue.issueQty}")
}
if (existingIssues.isNotEmpty()) {
if (existingIssues.isNotEmpty()) {
println("❌ Duplicate issue found - returning DUPLICATE error")
return MessageResponse(
return MessageResponse(
id = null,
id = null,
name = "Pick execution issue already exists",
name = "Pick execution issue already exists",
@@ -96,18 +117,24 @@ open class PickExecutionIssueService(
}
}
val pickOrder = pickOrderRepository.findById(request.pickOrderId).orElse(null)
val pickOrder = pickOrderRepository.findById(request.pickOrderId).orElse(null)
println("Pick order: id=${pickOrder?.id}, code=${pickOrder?.code}, type=${pickOrder?.type?.value}")
// 2. 获取 inventory_lot_line 并计算账面数量 (bookQty)
// 2. 获取 inventory_lot_line 并计算账面数量 (bookQty)
val inventoryLotLine = request.lotId?.let {
val inventoryLotLine = request.lotId?.let {
inventoryLotLineRepository.findById(it).orElse(null)
inventoryLotLineRepository.findById(it).orElse(null)
}
}
println("Inventory lot line: id=${inventoryLotLine?.id}, lotNo=${inventoryLotLine?.inventoryLot?.lotNo}")
// 计算账面数量(创建 issue 时的快照)
// 计算账面数量(创建 issue 时的快照)
val bookQty = if (inventoryLotLine != null) {
val bookQty = if (inventoryLotLine != null) {
val inQty = inventoryLotLine.inQty ?: BigDecimal.ZERO
val inQty = inventoryLotLine.inQty ?: BigDecimal.ZERO
val outQty = inventoryLotLine.outQty ?: BigDecimal.ZERO
val outQty = inventoryLotLine.outQty ?: BigDecimal.ZERO
inQty.subtract(outQty) // bookQty = inQty - outQty
val calculated = inQty.subtract(outQty) // bookQty = inQty - outQty
println(" BookQty calculation: inQty=$inQty, outQty=$outQty, bookQty=$calculated")
calculated
} else {
} else {
println(" No inventory lot line found, bookQty=0")
BigDecimal.ZERO
BigDecimal.ZERO
}
}
@@ -117,41 +144,53 @@ open class PickExecutionIssueService(
val missQty = request.missQty ?: BigDecimal.ZERO
val missQty = request.missQty ?: BigDecimal.ZERO
val badItemQty = request.badItemQty ?: BigDecimal.ZERO
val badItemQty = request.badItemQty ?: BigDecimal.ZERO
val badReason = request.badReason ?: "quantity_problem"
val badReason = request.badReason ?: "quantity_problem"
println("=== Quantity Summary ===")
println(" Required Qty: $requiredQty")
println(" Actual Pick Qty: $actualPickQty")
println(" Miss Qty: $missQty")
println(" Bad Item Qty: $badItemQty")
println(" Bad Reason: $badReason")
println(" Book Qty: $bookQty")
// 4. 计算 issueQty(实际的问题数量)
// 4. 计算 issueQty(实际的问题数量)
val issueQty = when {
val issueQty = when {
// 情况1: 已拣完但有坏品
// 情况1: 已拣完但有坏品
actualPickQty == requiredQty && badItemQty > BigDecimal.ZERO -> {
actualPickQty == requiredQty && badItemQty > BigDecimal.ZERO -> {
println(" Case 1: actualPickQty == requiredQty && badItemQty > 0")
println(" issueQty = badItemQty = $badItemQty")
badItemQty // issueQty = badItemQty
badItemQty // issueQty = badItemQty
}
}
badReason == "package_problem" && badItemQty > BigDecimal.ZERO -> {
badReason == "package_problem" && badItemQty > BigDecimal.ZERO -> {
println(" Case 2: badReason == 'package_problem' && badItemQty > 0")
println(" issueQty = badItemQty = $badItemQty")
badItemQty
badItemQty
}
}
actualPickQty < requiredQty -> {
actualPickQty < requiredQty -> {
println(" Case 3: actualPickQty < requiredQty")
val calculatedIssueQty = bookQty.subtract(actualPickQty)
val calculatedIssueQty = bookQty.subtract(actualPickQty)
println(" issueQty = bookQty - actualPickQty = $bookQty - $actualPickQty = $calculatedIssueQty")
if (missQty > BigDecimal.ZERO && missQty > calculatedIssueQty) {
if (missQty > BigDecimal.ZERO && missQty > calculatedIssueQty) {
println("⚠️ Warning: User reported missQty (${ missQty} ) exceeds calculated issueQty (${ calculatedIssueQty} )")
println(" BookQty: ${ bookQty} , ActualPickQty: ${ actualPickQty} ")
println("⚠️ Warning: User reported missQty ($missQty) exceeds calculated issueQty ($calculatedIssueQty)")
println(" BookQty: $bookQty, ActualPickQty: $actualPickQty")
}
}
calculatedIssueQty
calculatedIssueQty
}
}
else -> BigDecimal.ZERO
else -> {
println(" Case 4: Default case")
println(" issueQty = 0")
BigDecimal.ZERO
}
}
}
println("=== PICK EXECUTION ISSUE PROCESSING ===")
println("Required Qty: ${requiredQty}")
println("Actual Pick Qty: ${actualPickQty}")
println("Miss Qty (Reported): ${missQty}")
println("Bad Item Qty: ${badItemQty}")
println("Book Qty (inQty - outQty): ${bookQty}")
println("Issue Qty (Calculated): ${issueQty}")
println("Bad Reason: ${request.badReason}")
println("Lot ID: ${request.lotId}")
println("Item ID: ${request.itemId}")
println("=== Final IssueQty Calculation ===")
println(" Calculated IssueQty: $issueQty")
println("================================================")
println("================================================")
// 5. 创建 pick execution issue 记录
// 5. 创建 pick execution issue 记录
val issueNo = generateIssueNo()
println("Generated issue number: $issueNo")
val pickExecutionIssue = PickExecutionIssue(
val pickExecutionIssue = PickExecutionIssue(
id = null,
id = null,
pickOrderId = request.pickOrderId,
pickOrderId = request.pickOrderId,
@@ -159,7 +198,7 @@ open class PickExecutionIssueService(
pickOrderCreateDate = request.pickOrderCreateDate,
pickOrderCreateDate = request.pickOrderCreateDate,
pickExecutionDate = request.pickExecutionDate ?: LocalDate.now(),
pickExecutionDate = request.pickExecutionDate ?: LocalDate.now(),
pickOrderLineId = request.pickOrderLineId,
pickOrderLineId = request.pickOrderLineId,
issueNo = generateIssueNo() ,
issueNo = issueNo ,
joPickOrderId = pickOrder?.jobOrder?.id,
joPickOrderId = pickOrder?.jobOrder?.id,
doPickOrderId = if (pickOrder?.type?.value == "do") pickOrder.id else null,
doPickOrderId = if (pickOrder?.type?.value == "do") pickOrder.id else null,
issueCategory = IssueCategory.valueOf(
issueCategory = IssueCategory.valueOf(
@@ -189,11 +228,18 @@ open class PickExecutionIssueService(
modifiedBy = "system",
modifiedBy = "system",
deleted = false
deleted = false
)
)
println("Creating pick execution issue record...")
val savedIssue = pickExecutionIssueRepository.save(pickExecutionIssue)
val savedIssue = pickExecutionIssueRepository.save(pickExecutionIssue)
println("✅ Issue record created successfully!")
println(" Issue ID: ${savedIssue.id}")
println(" Issue No: ${savedIssue.issueNo}")
println(" Handle Status: ${savedIssue.handleStatus}")
println(" Issue Qty: ${savedIssue.issueQty}")
// 6. NEW: Update inventory_lot_line.issueQty
// 6. NEW: Update inventory_lot_line.issueQty
if (request.lotId != null && inventoryLotLine != null) {
if (request.lotId != null && inventoryLotLine != null) {
println("Updating inventory_lot_line.issueQty...")
// ✅ 修改:如果只有 missQty,不更新 issueQty
// ✅ 修改:如果只有 missQty,不更新 issueQty
val actualPickQty = request.actualPickQty ?: BigDecimal.ZERO
val actualPickQty = request.actualPickQty ?: BigDecimal.ZERO
val missQty = request.missQty ?: BigDecimal.ZERO
val missQty = request.missQty ?: BigDecimal.ZERO
@@ -205,6 +251,9 @@ open class PickExecutionIssueService(
val hasMissItemWithPartialPick = missQty > BigDecimal.ZERO
val hasMissItemWithPartialPick = missQty > BigDecimal.ZERO
&& actualPickQty > BigDecimal.ZERO
&& actualPickQty > BigDecimal.ZERO
println(" isMissItemOnly: $isMissItemOnly")
println(" hasMissItemWithPartialPick: $hasMissItemWithPartialPick")
if (!isMissItemOnly && !hasMissItemWithPartialPick) {
if (!isMissItemOnly && !hasMissItemWithPartialPick) {
// 只有非 miss item 的情况才更新 issueQty
// 只有非 miss item 的情况才更新 issueQty
val currentIssueQty = inventoryLotLine.issueQty ?: BigDecimal.ZERO
val currentIssueQty = inventoryLotLine.issueQty ?: BigDecimal.ZERO
@@ -213,42 +262,45 @@ open class PickExecutionIssueService(
inventoryLotLine.modified = LocalDateTime.now()
inventoryLotLine.modified = LocalDateTime.now()
inventoryLotLine.modifiedBy = "system"
inventoryLotLine.modifiedBy = "system"
inventoryLotLineRepository.saveAndFlush(inventoryLotLine)
inventoryLotLineRepository.saveAndFlush(inventoryLotLine)
println("Updated inventory_lot_line ${request.lotId} issueQty: ${ currentIssueQty} -> ${ newIssueQty} ")
println("✅ Updated inventory_lot_line ${request.lotId} issueQty: $currentIssueQty -> $newIssueQty")
} else {
} else {
println("Skipped updating issueQty for miss item (lot ${request.lotId})")
println("⏭️ Skipped updating issueQty for miss item (lot ${request.lotId})")
}
}
}
}
// 7. 获取相关数据用于后续处理
// 7. 获取相关数据用于后续处理
val actualPickQtyForProcessing = request.actualPickQty ?: BigDecimal.ZERO
val actualPickQtyForProcessing = request.actualPickQty ?: BigDecimal.ZERO
val missQtyForProcessing = request.missQty ?: BigDecimal.ZERO
val missQtyForProcessing = request.missQty ?: BigDecimal.ZERO
val badItemQtyForProcessing = request.badItemQty ?: BigDecimal.ZERO
val badItemQtyForProcessing = request.badItemQty ?: BigDecimal.ZERO
val lotId = request.lotId
val lotId = request.lotId
val itemId = request.itemId
val itemId = request.itemId
println("=== PICK EXECUTION ISSUE PROCESSING (NEW LOGIC) ===")
println("Actual Pick Qty: ${ actualPickQtyForProcessing} ")
println("Miss Qty: ${ missQtyForProcessing} ")
println("Bad Item Qty: ${ badItemQtyForProcessing} ")
println("=== Processing Logic Selection ===")
println("Actual Pick Qty: $actualPickQtyForProcessing")
println("Miss Qty: $missQtyForProcessing")
println("Bad Item Qty: $badItemQtyForProcessing")
println("Bad Reason: ${request.badReason}")
println("Bad Reason: ${request.badReason}")
println("Lot ID: ${ lotId} ")
println("Item ID: ${ itemId} ")
println("Lot ID: $lotId")
println("Item ID: $itemId")
println("================================================")
println("================================================")
// 8. 新的统一处理逻辑(根据 badReason 决定处理方式)
// 8. 新的统一处理逻辑(根据 badReason 决定处理方式)
when {
when {
// 情况1: 只有 miss item (actualPickQty = 0, missQty > 0, badItemQty = 0)
// 情况1: 只有 miss item (actualPickQty = 0, missQty > 0, badItemQty = 0)
actualPickQtyForProcessing == BigDecimal.ZERO && missQtyForProcessing > BigDecimal.ZERO && badItemQtyForProcessing == BigDecimal.ZERO -> {
actualPickQtyForProcessing == BigDecimal.ZERO && missQtyForProcessing > BigDecimal.ZERO && badItemQtyForProcessing == BigDecimal.ZERO -> {
println("→ Handling: Miss Item Only")
handleMissItemOnly(request, missQtyForProcessing)
handleMissItemOnly(request, missQtyForProcessing)
}
}
// 情况2: 只有 bad item (badItemQty > 0, missQty = 0)
// 情况2: 只有 bad item (badItemQty > 0, missQty = 0)
badItemQtyForProcessing > BigDecimal.ZERO && missQtyForProcessing == BigDecimal.ZERO -> {
badItemQtyForProcessing > BigDecimal.ZERO && missQtyForProcessing == BigDecimal.ZERO -> {
println("→ Handling: Bad Item Only")
// NEW: Check bad reason
// NEW: Check bad reason
if (request.badReason == "package_problem") {
if (request.badReason == "package_problem") {
println(" Bad reason is 'package_problem' - calling handleBadItemPackageProblem")
handleBadItemPackageProblem(request, badItemQtyForProcessing)
handleBadItemPackageProblem(request, badItemQtyForProcessing)
} else {
} else {
println(" Bad reason is 'quantity_problem' - calling handleBadItemOnly")
// quantity_problem or default: handle as normal bad item
// quantity_problem or default: handle as normal bad item
handleBadItemOnly(request, badItemQtyForProcessing)
handleBadItemOnly(request, badItemQtyForProcessing)
}
}
@@ -256,29 +308,34 @@ open class PickExecutionIssueService(
// 情况3: 既有 miss item 又有 bad item
// 情况3: 既有 miss item 又有 bad item
missQtyForProcessing > BigDecimal.ZERO && badItemQtyForProcessing > BigDecimal.ZERO -> {
missQtyForProcessing > BigDecimal.ZERO && badItemQtyForProcessing > BigDecimal.ZERO -> {
println("→ Handling: Both Miss and Bad Item")
// NEW: Check bad reason
// NEW: Check bad reason
if (request.badReason == "package_problem") {
if (request.badReason == "package_problem") {
println(" Bad reason is 'package_problem' - calling handleBothMissAndBadItemPackageProblem")
handleBothMissAndBadItemPackageProblem(request, missQtyForProcessing, badItemQtyForProcessing)
handleBothMissAndBadItemPackageProblem(request, missQtyForProcessing, badItemQtyForProcessing)
} else {
} else {
println(" Bad reason is 'quantity_problem' - calling handleBothMissAndBadItem")
handleBothMissAndBadItem(request, missQtyForProcessing, badItemQtyForProcessing)
handleBothMissAndBadItem(request, missQtyForProcessing, badItemQtyForProcessing)
}
}
}
}
// 情况4: 有 miss item 的情况(无论 actualPickQty 是多少)
// 情况4: 有 miss item 的情况(无论 actualPickQty 是多少)
missQtyForProcessing > BigDecimal.ZERO -> {
missQtyForProcessing > BigDecimal.ZERO -> {
println("→ Handling: Miss Item With Partial Pick")
handleMissItemWithPartialPick(request, actualPickQtyForProcessing, missQtyForProcessing)
handleMissItemWithPartialPick(request, actualPickQtyForProcessing, missQtyForProcessing)
}
}
// 情况5: 正常拣货 (actualPickQty > 0, 没有 miss 或 bad item)
// 情况5: 正常拣货 (actualPickQty > 0, 没有 miss 或 bad item)
actualPickQtyForProcessing > BigDecimal.ZERO -> {
actualPickQtyForProcessing > BigDecimal.ZERO -> {
println("→ Handling: Normal Pick")
handleNormalPick(request, actualPickQtyForProcessing)
handleNormalPick(request, actualPickQtyForProcessing)
}
}
else -> {
else -> {
println("Unknown case: actualPickQty=${ actualPickQtyForProcessing} , missQty=${ missQtyForProcessing} , badItemQty=${ badItemQtyForProcessing} ")
println("⚠️ Unknown case: actualPickQty=$actualPickQtyForProcessing, missQty=$missQtyForProcessing, badItemQty=$badItemQtyForProcessing")
}
}
}
}
val pickOrderForCompletion = pickOrderRepository.findById(request.pickOrderId).orElse(null)
val pickOrderForCompletion = pickOrderRepository.findById(request.pickOrderId).orElse(null)
val consoCode = pickOrderForCompletion?.consoCode
val consoCode = pickOrderForCompletion?.consoCode
@@ -300,7 +357,9 @@ open class PickExecutionIssueService(
println("⚠️ Error checking pick order completion by pickOrderId: ${e.message}")
println("⚠️ Error checking pick order completion by pickOrderId: ${e.message}")
}
}
}
}
println("=== recordPickExecutionIssue: SUCCESS ===")
println("Issue ID: ${savedIssue.id}, Issue No: ${savedIssue.issueNo}")
return MessageResponse(
return MessageResponse(
id = savedIssue.id,
id = savedIssue.id,
name = "Pick execution issue recorded successfully",
name = "Pick execution issue recorded successfully",
@@ -309,9 +368,10 @@ open class PickExecutionIssueService(
message = "Pick execution issue recorded successfully",
message = "Pick execution issue recorded successfully",
errorPosition = null
errorPosition = null
)
)
} catch (e: Exception) {
} catch (e: Exception) {
println("=== ERROR IN recordPickExecutionIssue ===")
println("=== recordPickExecutionIssue: ERROR ===")
println("Error: ${e.message}")
e.printStackTrace()
e.printStackTrace()
return MessageResponse(
return MessageResponse(
id = null,
id = null,
@@ -2585,10 +2645,11 @@ open fun getLotIssueDetails(lotId: Long, itemId: Long, issueType: String): LotIs
)
)
}
}
// New: Submit with custom quantity
@Transactional(rollbackFor = [Exception::class])
open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse {
open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse {
try {
try {
println("=== submitIssueWithQty: START ===")
println("Request: lotId=${request.lotId}, itemId=${request.itemId}, issueType=${request.issueType}, submitQty=${request.submitQty}, handler=${request.handler}")
// Find all issues for this lot and item
// Find all issues for this lot and item
val issues = if (request.issueType == "miss") {
val issues = if (request.issueType == "miss") {
pickExecutionIssueRepository.findMissItemList(IssueCategory.lot_issue)
pickExecutionIssueRepository.findMissItemList(IssueCategory.lot_issue)
@@ -2606,7 +2667,13 @@ open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse
}
}
}
}
println("Found ${issues.size} issues to process")
issues.forEachIndexed { index, issue ->
println(" Issue[$index]: id=${issue.id}, issueQty=${issue.issueQty}, handleStatus=${issue.handleStatus}")
}
if (issues.isEmpty()) {
if (issues.isEmpty()) {
println("❌ No issues found for this lot")
return MessageResponse(
return MessageResponse(
id = null,
id = null,
name = "Error",
name = "Error",
@@ -2623,13 +2690,36 @@ open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse
// Use custom quantity instead of sum
// Use custom quantity instead of sum
val submitQty = request.submitQty
val submitQty = request.submitQty
if (submitQty <= BigDecimal.ZERO) {
// ✅ 修改:允许提交0,0表示"标记为已处理但无需出库"
if (submitQty < BigDecimal.ZERO) {
println("❌ Submit quantity cannot be negative: $submitQty")
return MessageResponse(
return MessageResponse(
id = null,
id = null,
name = "Error",
name = "Error",
code = "INVALID",
code = "INVALID",
type = "stock_issue",
type = "stock_issue",
message = "Submit quantity must be greater than 0",
message = "Submit quantity cannot be negative",
errorPosition = null
)
}
// ✅ 新增:如果提交数量为0,只标记issue为已处理,不创建stock_out_line
if (submitQty == BigDecimal.ZERO) {
println("ℹ️ Submit quantity is 0 - marking issues as handled without creating stock out")
// Mark all issues as handled
issues.forEach { issue ->
println(" Marking issue ${issue.id} as handled by handler $handler")
markIssueHandled(issue, handler)
}
println("✅ All issues marked as handled (no stock out created)")
return MessageResponse(
id = null,
name = "Success",
code = "SUCCESS",
type = "stock_issue",
message = "Issues marked as handled (no stock out - quantity is 0)",
errorPosition = null
errorPosition = null
)
)
}
}
@@ -2649,14 +2739,17 @@ open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse
firstIssue.issueRemark,
firstIssue.issueRemark,
handler
handler
)
)
println("Created stock out header: id=${stockOut.id}, type=${if (isMissItem) "MISS_ITEM" else "BAD_ITEM"}")
val pickOrderLine = firstIssue.pickOrderLineId?.let {
val pickOrderLine = firstIssue.pickOrderLineId?.let {
pickOrderLineRepository.findById(it).orElse(null)
pickOrderLineRepository.findById(it).orElse(null)
}
}
println("Pick order line: id=${pickOrderLine?.id}")
val lotLine = request.lotId.let {
val lotLine = request.lotId.let {
inventoryLotLineRepository.findById(it).orElse(null)
inventoryLotLineRepository.findById(it).orElse(null)
}
}
println("Lot line: id=${lotLine?.id}, lotNo=${lotLine?.inventoryLot?.lotNo}")
val item = itemsRepository.findById(request.itemId).orElse(null)
val item = itemsRepository.findById(request.itemId).orElse(null)
?: return MessageResponse(
?: return MessageResponse(
@@ -2667,6 +2760,7 @@ open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse
message = "Item not found",
message = "Item not found",
errorPosition = null
errorPosition = null
)
)
println("Item: id=${item.id}, code=${item.code}")
// Create stock_out_line with custom quantity
// Create stock_out_line with custom quantity
val stockOutLine = StockOutLine().apply {
val stockOutLine = StockOutLine().apply {
@@ -2679,21 +2773,27 @@ open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse
this.type = if (isMissItem) "Miss" else "Bad"
this.type = if (isMissItem) "Miss" else "Bad"
}
}
val savedStockOutLine = stockOutLineRepository.saveAndFlush(stockOutLine)
val savedStockOutLine = stockOutLineRepository.saveAndFlush(stockOutLine)
println("Created stock out line: id=${savedStockOutLine.id}, qty=${savedStockOutLine.qty}, status=${savedStockOutLine.status}")
if (!isMissItem && request.lotId != null) {
if (!isMissItem && request.lotId != null) {
val lotLineForReset = inventoryLotLineRepository.findById(request.lotId).orElse(null)
val lotLineForReset = inventoryLotLineRepository.findById(request.lotId).orElse(null)
if (lotLineForReset != null) {
if (lotLineForReset != null) {
val oldIssueQty = lotLineForReset.issueQty
lotLineForReset.issueQty = BigDecimal.ZERO
lotLineForReset.issueQty = BigDecimal.ZERO
inventoryLotLineRepository.saveAndFlush(lotLineForReset)
inventoryLotLineRepository.saveAndFlush(lotLineForReset)
println("✅ Reset issueQty to 0 for lot ${request.lotId} before bad item submission (submitIssueWithQty) ")
println("✅ Reset issueQty for lot ${request.lotId}: $oldIssueQty -> 0 ")
}
}
}
}
// Update inventory_lot_line with custom quantity - pass isMissItem flag
// Update inventory_lot_line with custom quantity - pass isMissItem flag
if (request.lotId != null) {
if (request.lotId != null) {
println("Updating lot line after issue: lotId=${request.lotId}, submitQty=$submitQty, isMissItem=$isMissItem")
updateLotLineAfterIssue(request.lotId, submitQty, isMissItem)
updateLotLineAfterIssue(request.lotId, submitQty, isMissItem)
}
}
// Mark all issues as handled
// Mark all issues as handled
issues.forEach { issue ->
issues.forEach { issue ->
println(" Marking issue ${issue.id} as handled by handler $handler")
markIssueHandled(issue, handler)
markIssueHandled(issue, handler)
}
}
@@ -2708,6 +2808,7 @@ open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse
createStockLedgerForStockOutWithBalance(savedStockOutLine, balance, if (isMissItem) "Miss" else "Bad")
createStockLedgerForStockOutWithBalance(savedStockOutLine, balance, if (isMissItem) "Miss" else "Bad")
println("=== submitIssueWithQty: SUCCESS ===")
return MessageResponse(
return MessageResponse(
id = stockOut.id,
id = stockOut.id,
name = "Success",
name = "Success",
@@ -2717,6 +2818,9 @@ open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse
errorPosition = null
errorPosition = null
)
)
} catch (e: Exception) {
} catch (e: Exception) {
println("=== submitIssueWithQty: ERROR ===")
println("Error: ${e.message}")
e.printStackTrace()
return MessageResponse(
return MessageResponse(
id = null,
id = null,
name = "Error",
name = "Error",