| @@ -4493,75 +4493,68 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto | |||||
| @Transactional(rollbackFor = [java.lang.Exception::class]) | @Transactional(rollbackFor = [java.lang.Exception::class]) | ||||
| open fun confirmLotSubstitution(req: LotSubstitutionConfirmRequest): MessageResponse { | open fun confirmLotSubstitution(req: LotSubstitutionConfirmRequest): MessageResponse { | ||||
| val zero = BigDecimal.ZERO | val zero = BigDecimal.ZERO | ||||
| // Validate entities | |||||
| // Validate pick order line | |||||
| val pol = req.pickOrderLineId.let { pickOrderLineRepository.findById(it).orElse(null) } | val pol = req.pickOrderLineId.let { pickOrderLineRepository.findById(it).orElse(null) } | ||||
| ?: return MessageResponse( | ?: return MessageResponse( | ||||
| id = null, name = "Pick order line not found", code = "ERROR", type = "pickorder", | id = null, name = "Pick order line not found", code = "ERROR", type = "pickorder", | ||||
| message = "Pick order line ${req.pickOrderLineId} not found", errorPosition = null | message = "Pick order line ${req.pickOrderLineId} not found", errorPosition = null | ||||
| ) | ) | ||||
| val newIll = req.newInventoryLotLineId.let { inventoryLotLineRepository.findById(it).orElse(null) } | |||||
| val polItemId = pol.item?.id | |||||
| if (polItemId == null) { | |||||
| return MessageResponse( | |||||
| id = null, name = "Item not found", code = "ERROR", type = "pickorder", | |||||
| message = "Pick order line item is null", errorPosition = null | |||||
| ) | |||||
| } | |||||
| // ✅ 根据 lotNo 和 itemId 查找新的 InventoryLotLine | |||||
| val newIll = inventoryLotLineRepository.findByLotNoAndItemId(req.newInventoryLotNo, polItemId) | |||||
| ?: return MessageResponse( | ?: return MessageResponse( | ||||
| id = null, name = "New lot line not found", code = "ERROR", type = "pickorder", | id = null, name = "New lot line not found", code = "ERROR", type = "pickorder", | ||||
| message = "Inventory lot line ${req.newInventoryLotLineId} not found", errorPosition = null | |||||
| message = "Inventory lot line with lotNo '${req.newInventoryLotNo}' and itemId ${polItemId} not found", | |||||
| errorPosition = null | |||||
| ) | ) | ||||
| // Item consistency check | |||||
| val polItemId = pol.item?.id | |||||
| // Item consistency check (应该已经通过上面的查询保证了,但再次确认) | |||||
| val newItemId = newIll.inventoryLot?.item?.id | val newItemId = newIll.inventoryLot?.item?.id | ||||
| if (polItemId == null || newItemId == null || polItemId != newItemId) { | |||||
| if (newItemId == null || polItemId != newItemId) { | |||||
| return MessageResponse( | return MessageResponse( | ||||
| id = null, name = "Item mismatch", code = "ERROR", type = "pickorder", | id = null, name = "Item mismatch", code = "ERROR", type = "pickorder", | ||||
| message = "New lot line item does not match pick order line item", errorPosition = null | message = "New lot line item does not match pick order line item", errorPosition = null | ||||
| ) | ) | ||||
| } | } | ||||
| val newIllId = newIll.id ?: return MessageResponse( | |||||
| id = null, name = "Invalid lot line", code = "ERROR", type = "pickorder", | |||||
| message = "New inventory lot line has no ID", errorPosition = null | |||||
| ) | |||||
| // 1) Update suggested pick lot (if provided): move holdQty from old ILL to new ILL and re-point the suggestion | // 1) Update suggested pick lot (if provided): move holdQty from old ILL to new ILL and re-point the suggestion | ||||
| if (req.originalSuggestedPickLotId != null && req.originalSuggestedPickLotId > 0) { | if (req.originalSuggestedPickLotId != null && req.originalSuggestedPickLotId > 0) { | ||||
| // Get current suggested ILL id and qty | |||||
| val row = jdbcDao.queryForMap( | |||||
| """ | |||||
| SELECT spl.suggestedLotLineId AS oldIllId, COALESCE(spl.qty,0) AS qty | |||||
| FROM suggested_pick_lot spl | |||||
| WHERE spl.id = :splId | |||||
| """.trimIndent(), mapOf("splId" to req.originalSuggestedPickLotId) | |||||
| ).orElse(null) | |||||
| if (row != null) { | |||||
| val oldIllId = (row["oldIllId"] as Number?)?.toLong() | |||||
| val qty = when (val qtyObj = row["qty"]) { | |||||
| is BigDecimal -> qtyObj | |||||
| is Number -> qtyObj.toDouble().toBigDecimal() | |||||
| is String -> qtyObj.toBigDecimalOrNull() ?: zero | |||||
| else -> zero | |||||
| } | |||||
| if (oldIllId != null && oldIllId != req.newInventoryLotLineId) { | |||||
| // ✅ 使用 repository 而不是 SQL | |||||
| val originalSpl = suggestPickLotRepository.findById(req.originalSuggestedPickLotId).orElse(null) | |||||
| if (originalSpl != null) { | |||||
| val oldIll = originalSpl.suggestedLotLine | |||||
| val qty = originalSpl.qty ?: zero | |||||
| if (oldIll != null && oldIll.id != newIllId) { | |||||
| // Decrease hold on old, increase on new | // Decrease hold on old, increase on new | ||||
| val oldIll = inventoryLotLineRepository.findById(oldIllId).orElse(null) | |||||
| if (oldIll != null) { | |||||
| oldIll.holdQty = (oldIll.holdQty ?: zero).minus(qty).max(zero) | |||||
| inventoryLotLineRepository.save(oldIll) | |||||
| } | |||||
| val newIllEntity = inventoryLotLineRepository.findById(req.newInventoryLotLineId).orElse(null) | |||||
| if (newIllEntity != null) { | |||||
| newIllEntity.holdQty = (newIllEntity.holdQty ?: zero).plus(qty) | |||||
| inventoryLotLineRepository.save(newIllEntity) | |||||
| } | |||||
| oldIll.holdQty = (oldIll.holdQty ?: zero).minus(qty).max(zero) | |||||
| inventoryLotLineRepository.save(oldIll) | |||||
| newIll.holdQty = (newIll.holdQty ?: zero).plus(qty) | |||||
| inventoryLotLineRepository.save(newIll) | |||||
| } | } | ||||
| // Re-point suggestion to new ILL | |||||
| jdbcDao.executeUpdate( | |||||
| """ | |||||
| UPDATE suggested_pick_lot | |||||
| SET suggestedLotLineId = :newIllId | |||||
| WHERE id = :splId | |||||
| """.trimIndent(), mapOf("newIllId" to req.newInventoryLotLineId, "splId" to req.originalSuggestedPickLotId) | |||||
| ) | |||||
| // ✅ 使用 repository 更新 suggestion | |||||
| originalSpl.suggestedLotLine = newIll | |||||
| suggestPickLotRepository.save(originalSpl) | |||||
| } | } | ||||
| } | } | ||||
| // 2) Update stock out line (if provided): re-point to new ILL; keep qty and status unchanged | // 2) Update stock out line (if provided): re-point to new ILL; keep qty and status unchanged | ||||
| if (req.stockOutLineId != null && req.stockOutLineId > 0) { | if (req.stockOutLineId != null && req.stockOutLineId > 0) { | ||||
| val sol = stockOutLIneRepository.findById(req.stockOutLineId).orElse(null) | val sol = stockOutLIneRepository.findById(req.stockOutLineId).orElse(null) | ||||
| @@ -4571,13 +4564,13 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto | |||||
| stockOutLIneRepository.save(sol) | stockOutLIneRepository.save(sol) | ||||
| } | } | ||||
| } | } | ||||
| return MessageResponse( | return MessageResponse( | ||||
| id = null, | id = null, | ||||
| name = "Lot substitution confirmed", | name = "Lot substitution confirmed", | ||||
| code = "SUCCESS", | code = "SUCCESS", | ||||
| type = "pickorder", | type = "pickorder", | ||||
| message = "Updated suggestion and stock out line to new lot line ${req.newInventoryLotLineId}", | |||||
| message = "Updated suggestion and stock out line to new lot line with lotNo '${req.newInventoryLotNo}'", | |||||
| errorPosition = null | errorPosition = null | ||||
| ) | ) | ||||
| } | } | ||||
| @@ -5,5 +5,5 @@ data class LotSubstitutionConfirmRequest( | |||||
| val pickOrderLineId: Long, | val pickOrderLineId: Long, | ||||
| val stockOutLineId: Long?, // optional | val stockOutLineId: Long?, // optional | ||||
| val originalSuggestedPickLotId: Long?, // optional | val originalSuggestedPickLotId: Long?, // optional | ||||
| val newInventoryLotLineId: Long | |||||
| val newInventoryLotNo: String | |||||
| ) | ) | ||||
| @@ -579,7 +579,8 @@ open class ProductProcessService( | |||||
| scrapRate = bom?.scrapRate?:-1, | scrapRate = bom?.scrapRate?:-1, | ||||
| allergicSubstance = calculateAllergicSubstanceScore(bom?.allergicSubstances), | allergicSubstance = calculateAllergicSubstanceScore(bom?.allergicSubstances), | ||||
| outputQtyUom = bom?.outputQtyUom?:"", | outputQtyUom = bom?.outputQtyUom?:"", | ||||
| outputQty = bom?.outputQty?.toInt()?:0, | |||||
| //outputQty = bom?.outputQty?.toInt()?:0, | |||||
| outputQty = jobOrder?.reqQty?.toInt()?:0, | |||||
| productProcessCode = process.productProcessCode?:"", | productProcessCode = process.productProcessCode?:"", | ||||
| status = process.status?:ProductProcessStatus.PENDING, | status = process.status?:ProductProcessStatus.PENDING, | ||||
| startTime = process.startTime?:LocalDateTime.now(), | startTime = process.startTime?:LocalDateTime.now(), | ||||
| @@ -43,4 +43,13 @@ interface InventoryLotLineRepository : AbstractRepository<InventoryLotLine, Long | |||||
| fun findAllByInventoryLotItemIdAndStatus(itemId: Long, status: String): List<InventoryLotLine> | fun findAllByInventoryLotItemIdAndStatus(itemId: Long, status: String): List<InventoryLotLine> | ||||
| fun findAllByInventoryLotItemIdAndStatus(itemId: Long, status: InventoryLotLineStatus): List<InventoryLotLine> | fun findAllByInventoryLotItemIdAndStatus(itemId: Long, status: InventoryLotLineStatus): List<InventoryLotLine> | ||||
| @Query("SELECT ill FROM InventoryLotLine ill WHERE ill.inventoryLot.item.id IN :itemIds") | |||||
| fun findAllByItemIdIn(@Param("itemIds") itemIds: List<Long>): List<InventoryLotLine> | |||||
| @Query(""" | |||||
| SELECT ill FROM InventoryLotLine ill | |||||
| WHERE ill.inventoryLot.lotNo = :lotNo | |||||
| AND ill.inventoryLot.item.id = :itemId | |||||
| AND ill.deleted = false | |||||
| """) | |||||
| fun findByLotNoAndItemId(lotNo: String, itemId: Long): InventoryLotLine? | |||||
| } | } | ||||
| @@ -16,4 +16,11 @@ interface InventoryLotRepository: AbstractRepository<InventoryLot, Long> { | |||||
| """) | """) | ||||
| fun findLatestLotNoByPrefix(prefix: String): String? | fun findLatestLotNoByPrefix(prefix: String): String? | ||||
| fun findAllByIdIn(ids: List<Long>): List<InventoryLot> | fun findAllByIdIn(ids: List<Long>): List<InventoryLot> | ||||
| @Query(""" | |||||
| SELECT il FROM InventoryLot il | |||||
| WHERE il.lotNo = :lotNo | |||||
| AND il.item.id = :itemId | |||||
| AND il.deleted = false | |||||
| """) | |||||
| fun findByLotNoAndItemId(lotNo: String, itemId: Long): InventoryLot? | |||||
| } | } | ||||
| @@ -31,6 +31,7 @@ import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecord | |||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRecord | import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRecord | ||||
| import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus | ||||
| import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRecordRepository | import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRecordRepository | ||||
| import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineStatusByQRCodeAndLotNoRequest | |||||
| import com.ffii.fpsms.modules.common.CodeGenerator | import com.ffii.fpsms.modules.common.CodeGenerator | ||||
| import org.springframework.context.annotation.Lazy | import org.springframework.context.annotation.Lazy | ||||
| @@ -53,6 +54,7 @@ private val doPickOrderRecordRepository: DoPickOrderRecordRepository, | |||||
| private val deliveryOrderRepository: DeliveryOrderRepository, | private val deliveryOrderRepository: DeliveryOrderRepository, | ||||
| private val doPickOrderLineRepository: DoPickOrderLineRepository, | private val doPickOrderLineRepository: DoPickOrderLineRepository, | ||||
| private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository, | private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository, | ||||
| private val inventoryLotLineService: InventoryLotLineService | |||||
| ): AbstractBaseEntityService<StockOutLine, Long, StockOutLIneRepository>(jdbcDao, stockOutLineRepository) { | ): AbstractBaseEntityService<StockOutLine, Long, StockOutLIneRepository>(jdbcDao, stockOutLineRepository) { | ||||
| @Throws(IOException::class) | @Throws(IOException::class) | ||||
| @Transactional | @Transactional | ||||
| @@ -686,7 +688,7 @@ open fun batchSubmit(request: QrPickBatchSubmitRequest): MessageResponse { | |||||
| val errors = mutableListOf<String>() | val errors = mutableListOf<String>() | ||||
| val processedIds = mutableListOf<Long>() | val processedIds = mutableListOf<Long>() | ||||
| request.lines.forEach { line -> | |||||
| request.lines.forEach { line:QrPickSubmitLineRequest -> | |||||
| val lineStartTime = System.currentTimeMillis() | val lineStartTime = System.currentTimeMillis() | ||||
| try { | try { | ||||
| // 1) noLot 情况:等价于前端 handleSubmitAllScanned 里 noLot 分支 | // 1) noLot 情况:等价于前端 handleSubmitAllScanned 里 noLot 分支 | ||||
| @@ -920,4 +922,157 @@ open fun updateStockOutLineStatusByQRCodeAndLotNo(request: UpdateStockOutLineSta | |||||
| ) | ) | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| @Transactional(rollbackFor = [Exception::class]) | |||||
| open fun newBatchSubmit(request: QrPickBatchSubmitRequest): MessageResponse { | |||||
| val startTime = System.currentTimeMillis() | |||||
| println("=== BATCH SUBMIT START ===") | |||||
| println("Start time: ${java.time.LocalDateTime.now()}") | |||||
| println("Request lines count: ${request.lines.size}") | |||||
| if (request.lines.isEmpty()) { | |||||
| return MessageResponse( | |||||
| id = null, | |||||
| name = "No lines", | |||||
| code = "EMPTY", | |||||
| type = "batch_submit", | |||||
| message = "No scanned lines", | |||||
| errorPosition = null | |||||
| ) | |||||
| } | |||||
| val errors = mutableListOf<String>() | |||||
| val processedIds = mutableListOf<Long>() | |||||
| try { | |||||
| // 1) Bulk load all lot lines and inventories | |||||
| val lotLineIds = request.lines.mapNotNull { it.inventoryLotLineId } | |||||
| println("Loading ${lotLineIds.size} lot lines...") | |||||
| val lotLines = if (lotLineIds.isNotEmpty()) { | |||||
| inventoryLotLineRepository.findAllById(lotLineIds).associateBy { it.id } | |||||
| } else { | |||||
| emptyMap() | |||||
| } | |||||
| val itemIds = lotLines.values.mapNotNull { it.inventoryLot?.item?.id } | |||||
| println("Loading ${itemIds.size} inventories...") | |||||
| val inventories = itemIds.mapNotNull { itemId -> | |||||
| inventoryRepository.findByItemId(itemId).orElse(null) | |||||
| }.associateBy { it.item?.id } | |||||
| // 2) Bulk load all stock out lines to get current quantities | |||||
| val stockOutLineIds = request.lines.map { it.stockOutLineId } | |||||
| println("Loading ${stockOutLineIds.size} stock out lines...") | |||||
| val stockOutLines = stockOutLineRepository.findAllById(stockOutLineIds).associateBy { it.id } | |||||
| // 3) Process each request line | |||||
| request.lines.forEach { line: QrPickSubmitLineRequest -> | |||||
| try { | |||||
| println("Processing line: stockOutLineId=${line.stockOutLineId}, noLot=${line.noLot}") | |||||
| if (line.noLot) { | |||||
| // noLot branch | |||||
| updateStatus(UpdateStockOutLineStatusRequest( | |||||
| id = line.stockOutLineId, | |||||
| status = "completed", | |||||
| qty = 0.0 | |||||
| )) | |||||
| processedIds += line.stockOutLineId | |||||
| println(" ✓ noLot item processed") | |||||
| return@forEach | |||||
| } | |||||
| // 修复:从数据库获取当前实际数量 | |||||
| val stockOutLine = stockOutLines[line.stockOutLineId] | |||||
| ?: throw IllegalStateException("StockOutLine ${line.stockOutLineId} not found") | |||||
| // 修复:qty 是 Double?,需要转换为 BigDecimal | |||||
| val currentActual = (stockOutLine.qty ?: 0.0).toBigDecimal() | |||||
| val targetActual = line.actualPickQty ?: BigDecimal.ZERO | |||||
| val required = line.requiredQty ?: BigDecimal.ZERO | |||||
| println(" Current qty: $currentActual, Target qty: $targetActual, Required: $required") | |||||
| // 修复:计算增量(前端发送的 actualPickQty 是目标累计值) | |||||
| val submitQty = targetActual - currentActual | |||||
| println(" Submit qty (increment): $submitQty") | |||||
| // 修复:使用前端发送的状态,而不是重新计算 | |||||
| val newStatus = line.stockOutLineStatus ?: if (targetActual >= required) "completed" else "partially_completed" | |||||
| // 修复:updateStatus 期望增量,所以传入 submitQty | |||||
| updateStatus(UpdateStockOutLineStatusRequest( | |||||
| id = line.stockOutLineId, | |||||
| status = newStatus, | |||||
| qty = submitQty.toDouble() | |||||
| )) | |||||
| // Inventory updates - 修复:使用增量数量 | |||||
| if (submitQty > BigDecimal.ZERO && line.inventoryLotLineId != null) { | |||||
| println(" Updating inventory lot line ${line.inventoryLotLineId} with qty $submitQty") | |||||
| inventoryLotLineService.updateInventoryLotLineQuantities( | |||||
| UpdateInventoryLotLineQuantitiesRequest( | |||||
| inventoryLotLineId = line.inventoryLotLineId, | |||||
| qty = submitQty, | |||||
| operation = "pick" | |||||
| ) | |||||
| ) | |||||
| } | |||||
| processedIds += line.stockOutLineId | |||||
| println(" ✓ Line processed successfully") | |||||
| } catch (e: Exception) { | |||||
| println(" ✗ Error processing line ${line.stockOutLineId}: ${e.message}") | |||||
| e.printStackTrace() | |||||
| errors += "stockOutLineId=${line.stockOutLineId}: ${e.message}" | |||||
| } | |||||
| } | |||||
| // 4) 移除:不需要保存 lotLines 和 inventories,因为它们没有被修改 | |||||
| // inventoryLotLineRepository.saveAll(lotLines.values.toList()) | |||||
| // inventoryRepository.saveAll(inventories.values.toList()) | |||||
| val msg = if (errors.isEmpty()) { | |||||
| "Batch submit success (${processedIds.size} lines)." | |||||
| } else { | |||||
| "Batch submit partial success (${processedIds.size} lines), errors: ${errors.joinToString("; ")}" | |||||
| } | |||||
| val totalTime = System.currentTimeMillis() - startTime | |||||
| println("Processed: ${processedIds.size}/${request.lines.size} items") | |||||
| println("Total time: ${totalTime}ms (${totalTime / 1000.0}s)") | |||||
| println("Average time per item: ${if (processedIds.isNotEmpty()) totalTime / processedIds.size else 0}ms") | |||||
| println("End time: ${java.time.LocalDateTime.now()}") | |||||
| println("=== BATCH SUBMIT END ===") | |||||
| return MessageResponse( | |||||
| id = null, | |||||
| name = "batch_submit", | |||||
| code = if (errors.isEmpty()) "SUCCESS" else "PARTIAL_SUCCESS", | |||||
| type = "batch_submit", | |||||
| message = msg, | |||||
| errorPosition = null, | |||||
| entity = mapOf( | |||||
| "processedIds" to processedIds, | |||||
| "errors" to errors | |||||
| ) | |||||
| ) | |||||
| } catch (e: Exception) { | |||||
| println("=== BATCH SUBMIT ERROR ===") | |||||
| println("Error: ${e.message}") | |||||
| e.printStackTrace() | |||||
| return MessageResponse( | |||||
| id = null, | |||||
| name = "batch_submit", | |||||
| code = "ERROR", | |||||
| type = "batch_submit", | |||||
| message = "Error: ${e.message}", | |||||
| errorPosition = null, | |||||
| entity = mapOf( | |||||
| "processedIds" to processedIds, | |||||
| "errors" to listOf(e.message ?: "Unknown error") | |||||
| ) | |||||
| ) | |||||
| } | |||||
| }} | |||||
| @@ -10,11 +10,12 @@ import com.ffii.fpsms.modules.stock.web.model.CreateStockOutLineRequest | |||||
| import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineRequest | import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineRequest | ||||
| import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineStatusRequest | import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineStatusRequest | ||||
| import jakarta.validation.Valid | import jakarta.validation.Valid | ||||
| import com.ffii.fpsms.modules.stock.web.model.QrPickBatchSubmitRequest | |||||
| import org.springframework.web.bind.annotation.* | import org.springframework.web.bind.annotation.* | ||||
| import com.ffii.fpsms.modules.stock.web.model.CreateStockOutLineWithoutConsoRequest | import com.ffii.fpsms.modules.stock.web.model.CreateStockOutLineWithoutConsoRequest | ||||
| import com.ffii.fpsms.modules.stock.web.model.QrPickBatchSubmitRequest | |||||
| import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineStatusByQRCodeAndLotNoRequest | import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineStatusByQRCodeAndLotNoRequest | ||||
| @RestController | @RestController | ||||
| @RequestMapping("/stockOutLine") | @RequestMapping("/stockOutLine") | ||||
| class StockOutLineController( | class StockOutLineController( | ||||
| @@ -45,16 +46,16 @@ class StockOutLineController( | |||||
| } | } | ||||
| @PostMapping("/batchQrSubmit") | |||||
| @PostMapping("/batchSubmitList") | |||||
| fun batchQrSubmit(@Valid @RequestBody request: QrPickBatchSubmitRequest): MessageResponse { | fun batchQrSubmit(@Valid @RequestBody request: QrPickBatchSubmitRequest): MessageResponse { | ||||
| return stockOutLineService.batchSubmit(request) | |||||
| return stockOutLineService.newBatchSubmit(request) | |||||
| } | } | ||||
| @PostMapping("/updateStatusByQRCodeAndLotNo") | @PostMapping("/updateStatusByQRCodeAndLotNo") | ||||
| fun updateStatusByQRCodeAndLotNo(@Valid @RequestBody request: UpdateStockOutLineStatusByQRCodeAndLotNoRequest): MessageResponse { | fun updateStatusByQRCodeAndLotNo(@Valid @RequestBody request: UpdateStockOutLineStatusByQRCodeAndLotNoRequest): MessageResponse { | ||||
| try { | try { | ||||
| println("=== 📥 CONTROLLER: updateStatusByQRCodeAndLotNo called ===") | |||||
| println("📋 Request received:") | |||||
| println(" - stockOutLineId: ${request.stockOutLineId}") | |||||
| println("=== CONTROLLER: updateStatusByQRCodeAndLotNo called ===") | |||||
| println(" Request received:") | |||||
| println(" - stockOutLineId: ${request.stockOutLineId}") | |||||
| println(" - pickOrderLineId: ${request.pickOrderLineId}") | println(" - pickOrderLineId: ${request.pickOrderLineId}") | ||||
| println(" - inventoryLotNo: ${request.inventoryLotNo}") | println(" - inventoryLotNo: ${request.inventoryLotNo}") | ||||
| println(" - itemId: ${request.itemId}") | println(" - itemId: ${request.itemId}") | ||||
| @@ -62,11 +63,11 @@ class StockOutLineController( | |||||
| val result = stockOutLineService.updateStockOutLineStatusByQRCodeAndLotNo(request) | val result = stockOutLineService.updateStockOutLineStatusByQRCodeAndLotNo(request) | ||||
| println("✅ CONTROLLER: Service call completed, returning result") | |||||
| println(" CONTROLLER: Service call completed, returning result") | |||||
| return result | return result | ||||
| } catch (e: Exception) { | } catch (e: Exception) { | ||||
| println("❌ CONTROLLER ERROR: ${e.message}") | |||||
| println("❌ Exception type: ${e.javaClass.simpleName}") | |||||
| println(" CONTROLLER ERROR: ${e.message}") | |||||
| println(" Exception type: ${e.javaClass.simpleName}") | |||||
| e.printStackTrace() | e.printStackTrace() | ||||
| // 返回错误响应而不是抛出异常 | // 返回错误响应而不是抛出异常 | ||||
| @@ -61,6 +61,13 @@ data class UpdateStockOutLineStatusRequest( | |||||
| val qty: Double? = null, | val qty: Double? = null, | ||||
| val remarks: String? = null | val remarks: String? = null | ||||
| ) | ) | ||||
| data class UpdateStockOutLineStatusByQRCodeAndLotNoRequest( | |||||
| val pickOrderLineId: Long, | |||||
| val inventoryLotNo: String, | |||||
| val stockOutLineId: Long, | |||||
| val itemId: Long, | |||||
| val status: String | |||||
| ) | |||||
| data class QrPickSubmitLineRequest( | data class QrPickSubmitLineRequest( | ||||
| val stockOutLineId: Long, | val stockOutLineId: Long, | ||||
| val pickOrderLineId: Long, | val pickOrderLineId: Long, | ||||
| @@ -76,10 +83,4 @@ data class QrPickBatchSubmitRequest( | |||||
| val userId: Long, | val userId: Long, | ||||
| val lines: List<QrPickSubmitLineRequest> | val lines: List<QrPickSubmitLineRequest> | ||||
| ) | ) | ||||
| data class UpdateStockOutLineStatusByQRCodeAndLotNoRequest( | |||||
| val pickOrderLineId: Long, | |||||
| val inventoryLotNo: String, | |||||
| val stockOutLineId: Long, | |||||
| val itemId: Long, | |||||
| val status: String | |||||
| ) | |||||