@@ -7,6 +7,7 @@ import com.ffii.fpsms.modules.common.SecurityUtils | |||||
import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository | import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository | ||||
import com.ffii.fpsms.modules.master.entity.ItemsRepository | import com.ffii.fpsms.modules.master.entity.ItemsRepository | ||||
import com.ffii.fpsms.modules.master.entity.UomConversionRepository | import com.ffii.fpsms.modules.master.entity.UomConversionRepository | ||||
import com.ffii.fpsms.modules.master.service.ItemUomService | |||||
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.pickOrder.entity.PickOrder | ||||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine | import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine | ||||
@@ -55,7 +56,8 @@ open class PickOrderService( | |||||
private val stockOutRepository: StockOutRepository, | private val stockOutRepository: StockOutRepository, | ||||
private val itemsRepository: ItemsRepository, | private val itemsRepository: ItemsRepository, | ||||
private val uomConversionRepository: UomConversionRepository, | private val uomConversionRepository: UomConversionRepository, | ||||
private val jobOrderRepository: JobOrderRepository | |||||
private val jobOrderRepository: JobOrderRepository, | |||||
private val itemUomService: ItemUomService, | |||||
): AbstractBaseEntityService<PickOrder, Long, PickOrderRepository>(jdbcDao, pickOrderRepository) { | ): AbstractBaseEntityService<PickOrder, Long, PickOrderRepository>(jdbcDao, pickOrderRepository) { | ||||
open fun create(request: SavePickOrderRequest): MessageResponse { | open fun create(request: SavePickOrderRequest): MessageResponse { | ||||
val code = assignPickCode() | val code = assignPickCode() | ||||
@@ -246,6 +248,7 @@ open class PickOrderService( | |||||
// TODO: Add actual pick lots | // TODO: Add actual pick lots | ||||
open fun consoPickOrderDetail(consoCode: String): ConsoPickOrderResponse { | open fun consoPickOrderDetail(consoCode: String): ConsoPickOrderResponse { | ||||
val zero = BigDecimal.ZERO | val zero = BigDecimal.ZERO | ||||
val one = BigDecimal.ONE | |||||
// pick orders | // pick orders | ||||
val pos = pickOrderRepository.findAllByConsoCode(consoCode) | val pos = pickOrderRepository.findAllByConsoCode(consoCode) | ||||
@@ -276,6 +279,9 @@ open class PickOrderService( | |||||
// Mapping: SuggestedPickLot -> SuggestPickLotInConso | // Mapping: SuggestedPickLot -> SuggestPickLotInConso | ||||
val finalSuggestedPickLots = suggestedPickLots.map { | val finalSuggestedPickLots = suggestedPickLots.map { | ||||
val inventoryLotLine = it.suggestedLotLine | val inventoryLotLine = it.suggestedLotLine | ||||
val salesUnit = inventoryLotLine?.inventoryLot?.item?.id?.let {_itemId -> itemUomService.findSalesUnitByItemId(_itemId) } | |||||
val ratio = (salesUnit?.ratioN ?: zero).divide(salesUnit?.ratioD ?: one) | |||||
val remainingQty = (inventoryLotLine?.inQty ?: zero) | val remainingQty = (inventoryLotLine?.inQty ?: zero) | ||||
.minus(inventoryLotLine?.outQty ?: zero) | .minus(inventoryLotLine?.outQty ?: zero) | ||||
.minus(inventoryLotLine?.holdQty ?: zero) | .minus(inventoryLotLine?.holdQty ?: zero) | ||||
@@ -285,10 +291,10 @@ open class PickOrderService( | |||||
val finalInventoryLotLine = InventoryLotLineInConso( | val finalInventoryLotLine = InventoryLotLineInConso( | ||||
id = inventoryLotLine?.id, | id = inventoryLotLine?.id, | ||||
lotNo = inventoryLotLine?.inventoryLot?.lotNo, | lotNo = inventoryLotLine?.inventoryLot?.lotNo, | ||||
inQty = inventoryLotLine?.inQty, | |||||
outQty = inventoryLotLine?.outQty, | |||||
holdQty = inventoryLotLine?.holdQty, | |||||
remainingQty = remainingQty, | |||||
inQty = (inventoryLotLine?.inQty ?: zero).multiply(ratio), | |||||
outQty = (inventoryLotLine?.outQty ?: zero).multiply(ratio), | |||||
holdQty = (inventoryLotLine?.holdQty ?: zero).multiply(ratio), | |||||
remainingQty = remainingQty.multiply(ratio), | |||||
stockUom = IdCodeDesc(stockUom?.id, stockUom?.code, stockUom?.udfudesc), | stockUom = IdCodeDesc(stockUom?.id, stockUom?.code, stockUom?.udfudesc), | ||||
status = inventoryLotLine?.status?.value, | status = inventoryLotLine?.status?.value, | ||||
remarks = inventoryLotLine?.remarks | remarks = inventoryLotLine?.remarks | ||||
@@ -14,10 +14,13 @@ interface InventoryInfo{ | |||||
@get:Value("#{target.item.type}") | @get:Value("#{target.item.type}") | ||||
val itemType: String? | val itemType: String? | ||||
// @get:Value("#{target.qty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | // @get:Value("#{target.qty / (target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[stockUnit == true && deleted == false]?.ratioD)}") | ||||
@get:Value("#{target.onHandQty / (target.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioD)}") | |||||
val onHandQty: BigDecimal? | val onHandQty: BigDecimal? | ||||
@get:Value("#{target.onHoldQty / (target.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioD)}") | |||||
val onHoldQty: BigDecimal? | val onHoldQty: BigDecimal? | ||||
@get:Value("#{target.unavailableQty / (target.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioD)}") | |||||
val unavailableQty: BigDecimal? | val unavailableQty: BigDecimal? | ||||
@get:Value("#{target.onHandQty - target.onHoldQty - target.unavailableQty}") | |||||
@get:Value("#{(target.onHandQty - target.onHoldQty - target.unavailableQty) / (target.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioN / target.item.itemUoms.^[salesUnit == true && deleted == false]?.ratioD)}") | |||||
val availableQty: BigDecimal? | val availableQty: BigDecimal? | ||||
@get:Value("#{target.item.itemUoms.^[purchaseUnit == true && deleted == false]?.uom.code}") | @get:Value("#{target.item.itemUoms.^[purchaseUnit == true && deleted == false]?.uom.code}") | ||||
val uomCode: String? | val uomCode: String? | ||||
@@ -1,5 +1,6 @@ | |||||
package com.ffii.fpsms.modules.stock.service | package com.ffii.fpsms.modules.stock.service | ||||
import com.ffii.fpsms.modules.master.service.ItemUomService | |||||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrder | import com.ffii.fpsms.modules.pickOrder.entity.PickOrder | ||||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine | import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine | ||||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLineRepository | import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLineRepository | ||||
@@ -13,6 +14,7 @@ import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotForPolRequest | |||||
import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotResponse | import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotResponse | ||||
import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
import java.math.BigDecimal | import java.math.BigDecimal | ||||
import java.time.LocalDate | |||||
import kotlin.jvm.optionals.getOrDefault | import kotlin.jvm.optionals.getOrDefault | ||||
import kotlin.jvm.optionals.getOrNull | import kotlin.jvm.optionals.getOrNull | ||||
@@ -23,6 +25,7 @@ open class SuggestedPickLotService( | |||||
val inventoryLotLineRepository: InventoryLotLineRepository, | val inventoryLotLineRepository: InventoryLotLineRepository, | ||||
val pickOrderLineRepository: PickOrderLineRepository, | val pickOrderLineRepository: PickOrderLineRepository, | ||||
val inventoryLotLineService: InventoryLotLineService, | val inventoryLotLineService: InventoryLotLineService, | ||||
val itemUomService: ItemUomService, | |||||
) { | ) { | ||||
// Calculation Available Qty / Remaining Qty | // Calculation Available Qty / Remaining Qty | ||||
open fun calculateRemainingQtyForInfo(inventoryLotLine: InventoryLotLineInfo?): BigDecimal { | open fun calculateRemainingQtyForInfo(inventoryLotLine: InventoryLotLineInfo?): BigDecimal { | ||||
@@ -62,6 +65,8 @@ open class SuggestedPickLotService( | |||||
val pols = request.pickOrderLines | val pols = request.pickOrderLines | ||||
val itemIds = pols.mapNotNull { it.item?.id } | val itemIds = pols.mapNotNull { it.item?.id } | ||||
val zero = BigDecimal.ZERO | val zero = BigDecimal.ZERO | ||||
val one = BigDecimal.ONE | |||||
val today = LocalDate.now() | |||||
val suggestedList: MutableList<SuggestedPickLot> = mutableListOf() | val suggestedList: MutableList<SuggestedPickLot> = mutableListOf() | ||||
val holdQtyMap: MutableMap<Long?, BigDecimal?> = request.holdQtyMap | val holdQtyMap: MutableMap<Long?, BigDecimal?> = request.holdQtyMap | ||||
@@ -71,13 +76,15 @@ open class SuggestedPickLotService( | |||||
.allInventoryLotLinesByItemIdIn(itemIds) | .allInventoryLotLinesByItemIdIn(itemIds) | ||||
.filter { it.status == InventoryLotLineStatus.AVAILABLE.value } | .filter { it.status == InventoryLotLineStatus.AVAILABLE.value } | ||||
.filter { (it.inQty ?: zero).minus(it.outQty ?: zero).minus(it.holdQty ?: zero) > zero } | .filter { (it.inQty ?: zero).minus(it.outQty ?: zero).minus(it.holdQty ?: zero) > zero } | ||||
.filter { it.expiryDate.isAfter(today) || it.expiryDate.isEqual(today)} | |||||
.sortedBy { it.expiryDate } | .sortedBy { it.expiryDate } | ||||
.groupBy { it.item?.id } | .groupBy { it.item?.id } | ||||
// loop for suggest pick lot line | // loop for suggest pick lot line | ||||
pols.forEach { line -> | pols.forEach { line -> | ||||
val salesUnit = line.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } | |||||
val lotLines = availableInventoryLotLines[line.item?.id].orEmpty() | val lotLines = availableInventoryLotLines[line.item?.id].orEmpty() | ||||
var remainingQty = line.qty ?: zero | |||||
var remainingQty = (line.qty ?: zero).multiply((salesUnit?.ratioN ?: zero).divide(salesUnit?.ratioD ?: one)) | |||||
val updatedLotLines = mutableListOf<InventoryLotLineInfo>() | val updatedLotLines = mutableListOf<InventoryLotLineInfo>() | ||||
lotLines.forEachIndexed { index, lotLine -> | lotLines.forEachIndexed { index, lotLine -> | ||||