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