| @@ -871,7 +871,8 @@ open class PickOrderService( | |||||
| CASE | CASE | ||||
| WHEN ill.status != 'available' THEN 'unavailable' | WHEN ill.status != 'available' THEN 'unavailable' | ||||
| WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) THEN 'expired' | 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' | ELSE 'available' | ||||
| END as lotAvailability | END as lotAvailability | ||||
| FROM fpsmsdb.suggested_pick_lot spl | FROM fpsmsdb.suggested_pick_lot spl | ||||
| @@ -1014,7 +1015,7 @@ open class PickOrderService( | |||||
| ) | ) | ||||
| val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) | val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) | ||||
| pickOrderRepository.saveAll(pickOrders) | pickOrderRepository.saveAll(pickOrders) | ||||
| val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn( | 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, | (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as baseAvailableQty, | ||||
| sales_iu.ratioN, | sales_iu.ratioN, | ||||
| sales_iu.ratioD, | 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 | FROM fpsmsdb.suggested_pick_lot spl | ||||
| JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId | JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId | ||||
| JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId | 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 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 (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 | 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, | THEN 1 END) as insufficientStockLots, | ||||
| COUNT(CASE WHEN sol.status IN ('rejected', 'lot-change', 'determine1') THEN 1 END) as problematicStockOutLines, | 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? | // 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 | // return list of stock in line, update data grid with the list | ||||
| stockInLine.apply { | 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.acceptedQty = request.acceptedQty | ||||
| this.demandQty = request.acceptQty | this.demandQty = request.acceptQty | ||||
| this.invoiceNo = request.invoiceNo | this.invoiceNo = request.invoiceNo | ||||
| this.receiptDate = request.receiptDate?.atStartOfDay() | |||||
| this.receiptDate = request.receiptDate?.atStartOfDay() ?: this.receiptDate | |||||
| // this.status = request.status | // this.status = request.status | ||||
| this.expiryDate = stockInLine.expiryDate ?: request.expiryDate | this.expiryDate = stockInLine.expiryDate ?: request.expiryDate | ||||
| this.remarks = stockInLine.remarks ?: request.remarks | this.remarks = stockInLine.remarks ?: request.remarks | ||||
| @@ -378,7 +378,8 @@ open class StockInLineService( | |||||
| BigDecimal.ONE | 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 { | stockInLine.apply { | ||||
| this.status = if (request.acceptQty?.compareTo(request.acceptedQty) == 0) | this.status = if (request.acceptQty?.compareTo(request.acceptedQty) == 0) | ||||
| StockInLineStatus.COMPLETE.status else StockInLineStatus.PARTIALLY_COMPLETE.status | StockInLineStatus.COMPLETE.status else StockInLineStatus.PARTIALLY_COMPLETE.status | ||||
| @@ -88,7 +88,7 @@ open class SuggestedPickLotService( | |||||
| pols.forEach { line -> | pols.forEach { line -> | ||||
| val salesUnit = line.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } | val salesUnit = line.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } | ||||
| val lotLines = availableInventoryLotLines[line.item?.id].orEmpty() | 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 | // ✅ 修复:remainingQty 应该是销售单位,不需要乘以 ratio | ||||
| var remainingQty = line.qty ?: zero | 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.RequestMapping | ||||
| import org.springframework.web.bind.annotation.RestController | import org.springframework.web.bind.annotation.RestController | ||||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | 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") | @RequestMapping("/suggestedPickLot") | ||||
| @RestController | @RestController | ||||
| @@ -25,6 +29,13 @@ class SuggestedPickLotController( | |||||
| // return suggestedPickLotService.suggestionForPickOrderLines(test1) | // 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}") | @PostMapping("/resuggest/{pickOrderId}") | ||||
| fun resuggestPickOrder(@PathVariable pickOrderId: Long): MessageResponse { | fun resuggestPickOrder(@PathVariable pickOrderId: Long): MessageResponse { | ||||
| return suggestedPickLotService.resuggestPickOrder(pickOrderId) | return suggestedPickLotService.resuggestPickOrder(pickOrderId) | ||||