| @@ -871,7 +871,8 @@ open class PickOrderService( | |||
| CASE | |||
| WHEN ill.status != 'available' THEN 'unavailable' | |||
| WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) THEN 'expired' | |||
| WHEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) < (spl.qty * (sales_iu.ratioN / sales_iu.ratioD)) THEN 'insufficient_stock' | |||
| -- WHEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) < (spl.qty * (sales_iu.ratioN / sales_iu.ratioD)) THEN 'insufficient_stock' | |||
| WHEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) < (spl.qty) THEN 'insufficient_stock' | |||
| ELSE 'available' | |||
| END as lotAvailability | |||
| FROM fpsmsdb.suggested_pick_lot spl | |||
| @@ -1014,7 +1015,7 @@ open class PickOrderService( | |||
| ) | |||
| val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) | |||
| pickOrderRepository.saveAll(pickOrders) | |||
| val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn( | |||
| @@ -1243,11 +1244,12 @@ open class PickOrderService( | |||
| (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as baseAvailableQty, | |||
| sales_iu.ratioN, | |||
| sales_iu.ratioD, | |||
| CASE | |||
| WHEN sales_iu.ratioN IS NOT NULL AND sales_iu.ratioD IS NOT NULL AND sales_iu.ratioD != 0 | |||
| THEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) / (sales_iu.ratioN / sales_iu.ratioD) | |||
| ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) | |||
| END as convertedAvailableQty | |||
| -- CASE | |||
| -- WHEN sales_iu.ratioN IS NOT NULL AND sales_iu.ratioD IS NOT NULL AND sales_iu.ratioD != 0 | |||
| -- THEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) / (sales_iu.ratioN / sales_iu.ratioD) | |||
| -- ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) | |||
| -- END as convertedAvailableQty | |||
| COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0) as convertedAvailableQty | |||
| FROM fpsmsdb.suggested_pick_lot spl | |||
| JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId | |||
| JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId | |||
| @@ -1281,12 +1283,15 @@ open class PickOrderService( | |||
| COUNT(CASE WHEN ill.status != 'available' THEN 1 END) as unavailableLots, | |||
| COUNT(CASE WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) THEN 1 END) as expiredLots, | |||
| -- ✅ 修复:使用销售单位进行比较 | |||
| -- COUNT(CASE WHEN | |||
| -- CASE | |||
| -- WHEN sales_iu.ratioN IS NOT NULL AND sales_iu.ratioD IS NOT NULL AND sales_iu.ratioD != 0 | |||
| -- THEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) / (sales_iu.ratioN / sales_iu.ratioD) | |||
| -- ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) | |||
| -- END < spl.qty | |||
| -- THEN 1 END) as insufficientStockLots, | |||
| COUNT(CASE WHEN | |||
| CASE | |||
| WHEN sales_iu.ratioN IS NOT NULL AND sales_iu.ratioD IS NOT NULL AND sales_iu.ratioD != 0 | |||
| THEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) / (sales_iu.ratioN / sales_iu.ratioD) | |||
| ELSE (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) | |||
| END < spl.qty | |||
| (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) < spl.qty | |||
| THEN 1 END) as insufficientStockLots, | |||
| COUNT(CASE WHEN sol.status IN ('rejected', 'lot-change', 'determine1') THEN 1 END) as problematicStockOutLines, | |||
| -- ✅ 检查单位不一致问题 | |||
| @@ -350,14 +350,14 @@ open class StockInLineService( | |||
| // TODO: check all status to prevent reverting progress due to multiple users access to the same po? | |||
| // return list of stock in line, update data grid with the list | |||
| stockInLine.apply { | |||
| this.productionDate = request.productionDate?.atStartOfDay() // maybe need to change the request to LocalDateTime | |||
| this.productLotNo = request.productLotNo | |||
| this.dnNo = request.dnNo | |||
| this.dnDate = request.dnDate?.atStartOfDay() | |||
| this.productionDate = request.productionDate?.atStartOfDay() ?: this.productionDate// maybe need to change the request to LocalDateTime | |||
| this.productLotNo = request.productLotNo ?: this.productLotNo | |||
| this.dnNo = request.dnNo ?: this.dnNo | |||
| this.dnDate = request.dnDate?.atStartOfDay() ?: this.dnDate | |||
| this.acceptedQty = request.acceptedQty | |||
| this.demandQty = request.acceptQty | |||
| this.invoiceNo = request.invoiceNo | |||
| this.receiptDate = request.receiptDate?.atStartOfDay() | |||
| this.receiptDate = request.receiptDate?.atStartOfDay() ?: this.receiptDate | |||
| // this.status = request.status | |||
| this.expiryDate = stockInLine.expiryDate ?: request.expiryDate | |||
| this.remarks = stockInLine.remarks ?: request.remarks | |||
| @@ -378,7 +378,8 @@ open class StockInLineService( | |||
| BigDecimal.ONE | |||
| } | |||
| if (inventoryLotLines.sumOf { it.inQty ?: BigDecimal.ZERO } >= request.acceptQty?.times(ratio)) { | |||
| // if (inventoryLotLines.sumOf { it.inQty ?: BigDecimal.ZERO } >= request.acceptQty?.times(ratio)) { | |||
| if (request.inventoryLotLines?.isEmpty() == true) { // Clicked proceed in PO Modal -- TODO improve | |||
| stockInLine.apply { | |||
| this.status = if (request.acceptQty?.compareTo(request.acceptedQty) == 0) | |||
| StockInLineStatus.COMPLETE.status else StockInLineStatus.PARTIALLY_COMPLETE.status | |||
| @@ -88,7 +88,7 @@ open class SuggestedPickLotService( | |||
| pols.forEach { line -> | |||
| val salesUnit = line.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } | |||
| val lotLines = availableInventoryLotLines[line.item?.id].orEmpty() | |||
| val ratio = (salesUnit?.ratioN ?: one).divide(salesUnit?.ratioD ?: one, 10, RoundingMode.HALF_UP) | |||
| val ratio = one // (salesUnit?.ratioN ?: one).divide(salesUnit?.ratioD ?: one, 10, RoundingMode.HALF_UP) | |||
| // ✅ 修复:remainingQty 应该是销售单位,不需要乘以 ratio | |||
| var remainingQty = line.qty ?: zero | |||
| @@ -11,6 +11,10 @@ import org.springframework.web.bind.annotation.PostMapping | |||
| import org.springframework.web.bind.annotation.RequestMapping | |||
| import org.springframework.web.bind.annotation.RestController | |||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
| import com.ffii.fpsms.modules.pickOrder.entity.PickOrder | |||
| import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotForPolRequest | |||
| import kotlin.jvm.optionals.getOrDefault | |||
| import kotlin.jvm.optionals.getOrNull | |||
| @RequestMapping("/suggestedPickLot") | |||
| @RestController | |||
| @@ -25,6 +29,13 @@ class SuggestedPickLotController( | |||
| // return suggestedPickLotService.suggestionForPickOrderLines(test1) | |||
| // } | |||
| @GetMapping("/test/{pickOrderId}") | |||
| fun test(@PathVariable pickOrderId: Long): Any { | |||
| val test1 = pickOrderRepository.findById(pickOrderId).getOrDefault(PickOrder()) | |||
| return suggestedPickLotService.suggestionForPickOrderLines(SuggestedPickLotForPolRequest(pickOrderLines = test1.pickOrderLines)) | |||
| } | |||
| @PostMapping("/resuggest/{pickOrderId}") | |||
| fun resuggestPickOrder(@PathVariable pickOrderId: Long): MessageResponse { | |||
| return suggestedPickLotService.resuggestPickOrder(pickOrderId) | |||