diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt index b3e0d2c..4521ebb 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt @@ -691,51 +691,30 @@ open class PickOrderService( } else { emptyMap() } - + + // ✅ Pre-calculate available quantities for each item ONCE + val itemAvailableQtyMap = mutableMapOf() + itemIds.forEach { itemId -> + val inventory = inventories[itemId] + val totalAvailableQty = inventory?.sumOf { i -> + val inQty = i.inQty ?: zero + val outQty = i.outQty ?: zero + val holdQty = i.holdQty ?: zero + inQty.minus(outQty).minus(holdQty) + } ?: zero + itemAvailableQtyMap[itemId] = totalAvailableQty + } + // Pick Orders - val releasePickOrderInfos = pos + val releasePickOrderLineInfos = pos .map { po -> val releasePickOrderLineInfos = po.pickOrderLines.map { pol -> - val inventory = pol.item?.id?.let { inventories[it] } - val itemUom = pol.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } + val itemId = pol.item?.id + val availableQty = itemId?.let { itemAvailableQtyMap[it] } ?: zero // ✅ Move stockOutLines declaration inside the pol loop val stockOutLines = stockOutLinesByPickOrderLineId[pol.id] ?: emptyList() - // ✅ Fix: Convert availableQty from base units to sales units - val convertedAvailableQty = inventory?.sumOf { i -> - val inQty = i.inQty ?: zero - val outQty = i.outQty ?: zero - val holdQty = i.holdQty ?: zero - val baseQty = inQty.minus(outQty).minus(holdQty) - - // ✅ NEW: Subtract completed picked quantities for this specific inventory lot line - val completedPickedQty = stockOutLines - .filter { it.status == "completed" || it.status == "COMPLETE" } - .filter { stockOutLine -> - // ✅ Check if this stock out line is for the current inventory lot line - stockOutLine.inventoryLotLineId == i.id - } - .sumOf { it.qty ?: zero } - - val adjustedBaseQty = baseQty.minus(completedPickedQty) - - println("Item ID: ${i.item?.id}, BaseQty: $baseQty, CompletedPicked: $completedPickedQty, Adjusted: $adjustedBaseQty") - - // Apply unit conversion if needed - //val itemUom = pol.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } - // val ratioN = itemUom?.ratioN - // val ratioD = itemUom?.ratioD - - // val convertedQty: BigDecimal = if (ratioN != null && ratioD != null && ratioD != zero) { - // adjustedBaseQty.divide(ratioN.divide(ratioD, 10, java.math.RoundingMode.HALF_UP), 2, java.math.RoundingMode.HALF_UP) - // } else { - // adjustedBaseQty - //} - - adjustedBaseQty - } - // ✅ Calculate total picked quantity from stock out lines println("=== PICKED QTY DEBUG: Line ${pol.id} ===") println("Stock Out Lines: ${stockOutLines.map { "${it.id}(status=${it.status}, qty=${it.qty})" }}") @@ -754,7 +733,7 @@ open class PickOrderService( itemId = pol.item?.id, itemCode = pol.item?.code, itemName = pol.item?.name, - availableQty = convertedAvailableQty, // ✅ Use adjusted available quantity + availableQty = availableQty, // ✅ Use pre-calculated value requiredQty = pol.qty, uomCode = pol.uom?.code, uomDesc = pol.uom?.udfudesc, @@ -786,8 +765,7 @@ open class PickOrderService( item.second.let { val convertedAvailableQty = inventory?.sumOf { i -> val baseQty = (i.availableQty ?: zero) - baseQty - + baseQty } it.availableQty = convertedAvailableQty @@ -797,7 +775,7 @@ open class PickOrderService( val consoCode = pos.firstOrNull()?.consoCode return GetPickOrderInfoResponse( consoCode = consoCode, - pickOrders = releasePickOrderInfos, + pickOrders = releasePickOrderLineInfos, items = currentInventoryInfos, ) } diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt index 9354e4f..778ef60 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt @@ -32,6 +32,7 @@ import java.time.format.DateTimeFormatter import java.util.Optional import kotlin.jvm.optionals.getOrNull import com.ffii.fpsms.modules.master.web.models.MessageResponse +import com.ffii.fpsms.modules.stock.web.model.UpdateInventoryLotLineQuantitiesRequest @Service open class InventoryLotLineService( private val inventoryLotLineRepository: InventoryLotLineRepository, @@ -177,4 +178,68 @@ open class InventoryLotLineService( "fileName" to qrCodeInfo[0].poCode ); } + + @Transactional +open fun updateInventoryLotLineQuantities(request: UpdateInventoryLotLineQuantitiesRequest): MessageResponse { + try { + val inventoryLotLine = inventoryLotLineRepository.findById(request.inventoryLotLineId).orElseThrow() + + // Handle quantity updates based on operation + var newHoldQty = inventoryLotLine.holdQty ?: BigDecimal.ZERO + var newOutQty = inventoryLotLine.outQty ?: BigDecimal.ZERO + + when (request.operation) { + "pick" -> { + // Move from hold_qty to out_qty + newHoldQty = newHoldQty.minus(request.qty) + newOutQty = newOutQty.plus(request.qty) + } + "release" -> { + // Move from out_qty back to hold_qty (if needed) + newOutQty = newOutQty.minus(request.qty) + newHoldQty = newHoldQty.plus(request.qty) + } + else -> { + throw IllegalArgumentException("Unknown operation: ${request.operation}") + } + } + + // Validate quantities + if (newHoldQty < BigDecimal.ZERO || newOutQty < BigDecimal.ZERO) { + throw IllegalArgumentException("Invalid quantities: holdQty=$newHoldQty, outQty=$newOutQty") + } + + val updateRequest = SaveInventoryLotLineRequest( + id = inventoryLotLine.id, + inventoryLotId = inventoryLotLine.inventoryLot?.id, + warehouseId = inventoryLotLine.warehouse?.id, + stockUomId = inventoryLotLine.stockUom?.id, + inQty = inventoryLotLine.inQty, + outQty = newOutQty, + holdQty = newHoldQty, + status = inventoryLotLine.status?.value, // Keep existing status + remarks = inventoryLotLine.remarks + ) + + val updatedInventoryLotLine = saveInventoryLotLine(updateRequest) + + return MessageResponse( + id = updatedInventoryLotLine.id, + name = "Inventory lot line quantities updated", + code = "SUCCESS", + type = "inventory_lot_line", + message = "Updated: holdQty=${newHoldQty}, outQty=${newOutQty}, operation=${request.operation}", + errorPosition = null + ) + } catch (e: Exception) { + return MessageResponse( + id = null, + name = "Failed to update inventory lot line quantities", + code = "ERROR", + type = "inventory_lot_line", + message = "Error: ${e.message}", + errorPosition = null + ) + } +} } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/PickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/PickOrderService.kt new file mode 100644 index 0000000..b28b04f --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/PickOrderService.kt @@ -0,0 +1,3 @@ + + + diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt index 4f682b6..6da7204 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt @@ -376,7 +376,9 @@ private fun getStockOutIdFromPickOrderLine(pickOrderLineId: Long): Long { // Update quantity if provided if (request.qty != null) { - stockOutLine.qty = request.qty + val currentQty = stockOutLine.qty?.toDouble() ?: 0.0 + val newQty = currentQty + request.qty + stockOutLine.qty = (newQty) } val savedStockOutLine = stockOutLineRepository.saveAndFlush(stockOutLine) diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt index e263e9d..712149b 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt @@ -11,6 +11,7 @@ import com.ffii.fpsms.modules.stock.service.StockInLineService import com.ffii.fpsms.modules.stock.web.model.ExportQrCodeRequest import com.ffii.fpsms.modules.stock.web.model.LotLineInfo import com.ffii.fpsms.modules.stock.web.model.SearchInventoryLotLineInfoRequest +import com.ffii.fpsms.modules.stock.web.model.UpdateInventoryLotLineQuantitiesRequest import jakarta.servlet.http.HttpServletResponse import jakarta.validation.Valid import net.sf.jasperreports.engine.JasperExportManager @@ -81,4 +82,9 @@ class InventoryLotLineController ( fun updateInventoryLotLineStatus(@RequestBody request: UpdateInventoryLotLineStatusRequest): MessageResponse { return inventoryLotLineService.updateInventoryLotLineStatus(request) } + + @PostMapping("/updateQuantities") + fun updateInventoryLotLineQuantities(@RequestBody request: UpdateInventoryLotLineQuantitiesRequest): MessageResponse { + return inventoryLotLineService.updateInventoryLotLineQuantities(request) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/model/UpdateInventoryLotLineQuantitiesRequest.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/model/UpdateInventoryLotLineQuantitiesRequest.kt new file mode 100644 index 0000000..b21bc9b --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/model/UpdateInventoryLotLineQuantitiesRequest.kt @@ -0,0 +1,9 @@ +package com.ffii.fpsms.modules.stock.web.model + +import java.math.BigDecimal + +data class UpdateInventoryLotLineQuantitiesRequest( + val inventoryLotLineId: Long, + val qty: BigDecimal, + val operation: String +) \ No newline at end of file