| @@ -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 -> | ||||