|
|
@@ -21,7 +21,9 @@ import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository |
|
|
|
import com.ffii.fpsms.modules.stock.entity.StockOut |
|
|
|
import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository |
|
|
|
import com.ffii.fpsms.modules.stock.entity.StockOutRepository |
|
|
|
import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus |
|
|
|
import com.ffii.fpsms.modules.stock.entity.projection.CurrentInventoryItemInfo |
|
|
|
import com.ffii.fpsms.modules.stock.service.InventoryLotLineService |
|
|
|
import com.ffii.fpsms.modules.stock.service.InventoryService |
|
|
|
import com.ffii.fpsms.modules.stock.service.StockOutLineService |
|
|
|
import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService |
|
|
@@ -52,13 +54,14 @@ open class PickOrderService( |
|
|
|
private val userService: UserService, |
|
|
|
private val stockOutLIneRepository: StockOutLIneRepository, |
|
|
|
private val inventoryLotLineRepository: InventoryLotLineRepository, |
|
|
|
private val inventoryLotLineService: InventoryLotLineService, |
|
|
|
private val inventoryService: InventoryService, |
|
|
|
private val stockOutRepository: StockOutRepository, |
|
|
|
private val itemsRepository: ItemsRepository, |
|
|
|
private val uomConversionRepository: UomConversionRepository, |
|
|
|
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 { |
|
|
|
val code = assignPickCode() |
|
|
|
val jo = request.joId?.let { jobOrderRepository.findById(it).getOrNull() } |
|
|
@@ -86,13 +89,14 @@ open class PickOrderService( |
|
|
|
pickOrderLineRepository.saveAll(polEntries) |
|
|
|
return MessageResponse( |
|
|
|
id = savedPickOrder.id, |
|
|
|
name = savedPickOrder.code, |
|
|
|
code = savedPickOrder.code, |
|
|
|
type = savedPickOrder.type!!.value, |
|
|
|
message = "success", |
|
|
|
errorPosition = "", |
|
|
|
name = savedPickOrder.code, |
|
|
|
code = savedPickOrder.code, |
|
|
|
type = savedPickOrder.type!!.value, |
|
|
|
message = "success", |
|
|
|
errorPosition = "", |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
open fun localDateTimeParse(dateTime: String?, pattern: String? = "YYYY-MM-DD hh:mm:ss"): LocalDateTime? { |
|
|
|
try { |
|
|
|
val formatter = DateTimeFormatter.ofPattern(pattern!!) |
|
|
@@ -125,24 +129,26 @@ open class PickOrderService( |
|
|
|
} |
|
|
|
|
|
|
|
open fun getConsoPickOrderList(args: MutableMap<String, Any>): List<Map<String, Any>> { |
|
|
|
val sql = StringBuilder( "select" |
|
|
|
+ " po.consoCode, " |
|
|
|
+ " po.releasedDate, " |
|
|
|
+ " po.status, " |
|
|
|
+ " po.assignTo " |
|
|
|
+ " from pick_order po " |
|
|
|
+ " where po.deleted = false " |
|
|
|
+ " and po.consoCode is not null " |
|
|
|
val sql = StringBuilder( |
|
|
|
"select" |
|
|
|
+ " po.consoCode, " |
|
|
|
+ " po.releasedDate, " |
|
|
|
+ " po.status, " |
|
|
|
+ " po.assignTo " |
|
|
|
+ " from pick_order po " |
|
|
|
+ " where po.deleted = false " |
|
|
|
+ " and po.consoCode is not null " |
|
|
|
) |
|
|
|
if (args.containsKey("consoCode")){ |
|
|
|
if (args.containsKey("consoCode")) { |
|
|
|
sql.append(" AND po.consoCode like :consoCode "); |
|
|
|
} |
|
|
|
if (args.containsKey("status")){ |
|
|
|
if (args.containsKey("status")) { |
|
|
|
sql.append(" AND po.status = :status "); |
|
|
|
} |
|
|
|
sql.append(" group by po.consoCode, po.releasedDate, po.status, po.assignTo ") |
|
|
|
return jdbcDao.queryForList(sql.toString(), args); |
|
|
|
} |
|
|
|
|
|
|
|
open fun assignPickCode(): String { |
|
|
|
val suffixFormat = "%03d" |
|
|
|
val pattern = "yyyyMMdd" |
|
|
@@ -163,6 +169,7 @@ open class PickOrderService( |
|
|
|
|
|
|
|
return listOf<String>(prefix, midfix, suffix).joinToString("-") |
|
|
|
} |
|
|
|
|
|
|
|
// Consolidating Pick Orders |
|
|
|
open fun assignConsoCode(): String { |
|
|
|
val suffixFormat = "%03d" |
|
|
@@ -220,27 +227,28 @@ open class PickOrderService( |
|
|
|
if (!args.containsKey("consoCode") || args["consoCode"] == null) { |
|
|
|
throw IllegalArgumentException("consoCode must not be null") |
|
|
|
} |
|
|
|
val sql = StringBuilder("select" |
|
|
|
+ " po.status as poStatus," |
|
|
|
+ " pol.id, " |
|
|
|
+ " i.name as itemName, " |
|
|
|
+ " pol.qty as qty, " |
|
|
|
+ " max(uc.code) as uom, " |
|
|
|
+ " group_concat(ill.id) as lotLineId, " |
|
|
|
+ " group_concat(w.name) as warehouse, " |
|
|
|
+ " group_concat(il.lotNo) as suggestedLotNo, " |
|
|
|
+ " pol.status " |
|
|
|
+ " from pick_order po " |
|
|
|
+ " left join pick_order_line pol on pol.poId = po.id " |
|
|
|
+ " left join items i on i.id = pol.itemId " |
|
|
|
+ " left join suggested_pick_lot spl on spl.pickOrderLineId = pol.id " |
|
|
|
+ " left join inventory_lot_line ill on ill.id = spl.suggestedLotLineId " |
|
|
|
+ " left join warehouse w on w.id = ill.warehouseId " |
|
|
|
+ " left join inventory_lot il on il.id = ill.inventoryLotId " |
|
|
|
+ " left join uom_conversion uc on uc.id = pol.uomId " |
|
|
|
+ " where po.deleted = false " |
|
|
|
+ " and po.consoCode = :consoCode " |
|
|
|
+ " group by po.status, pol.id, i.name, pol.qty, pol.status " |
|
|
|
val sql = StringBuilder( |
|
|
|
"select" |
|
|
|
+ " po.status as poStatus," |
|
|
|
+ " pol.id, " |
|
|
|
+ " i.name as itemName, " |
|
|
|
+ " pol.qty as qty, " |
|
|
|
+ " max(uc.code) as uom, " |
|
|
|
+ " group_concat(ill.id) as lotLineId, " |
|
|
|
+ " group_concat(w.name) as warehouse, " |
|
|
|
+ " group_concat(il.lotNo) as suggestedLotNo, " |
|
|
|
+ " pol.status " |
|
|
|
+ " from pick_order po " |
|
|
|
+ " left join pick_order_line pol on pol.poId = po.id " |
|
|
|
+ " left join items i on i.id = pol.itemId " |
|
|
|
+ " left join suggested_pick_lot spl on spl.pickOrderLineId = pol.id " |
|
|
|
+ " left join inventory_lot_line ill on ill.id = spl.suggestedLotLineId " |
|
|
|
+ " left join warehouse w on w.id = ill.warehouseId " |
|
|
|
+ " left join inventory_lot il on il.id = ill.inventoryLotId " |
|
|
|
+ " left join uom_conversion uc on uc.id = pol.uomId " |
|
|
|
+ " where po.deleted = false " |
|
|
|
+ " and po.consoCode = :consoCode " |
|
|
|
+ " group by po.status, pol.id, i.name, pol.qty, pol.status " |
|
|
|
) |
|
|
|
return jdbcDao.queryForList(sql.toString(), args); |
|
|
|
} |
|
|
@@ -279,7 +287,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 salesUnit = inventoryLotLine?.inventoryLot?.item?.id?.let { _itemId -> |
|
|
|
itemUomService.findSalesUnitByItemId(_itemId) |
|
|
|
} |
|
|
|
val ratio = (salesUnit?.ratioN ?: zero).divide(salesUnit?.ratioD ?: one) |
|
|
|
|
|
|
|
val remainingQty = (inventoryLotLine?.inQty ?: zero) |
|
|
@@ -386,6 +396,7 @@ open class PickOrderService( |
|
|
|
} |
|
|
|
|
|
|
|
open fun releaseConsoPickOrderInfo(consoCode: String): ReleasePickOrderInfoResponse { |
|
|
|
val today = LocalDate.now() |
|
|
|
val zero = BigDecimal.ZERO |
|
|
|
val pos = pickOrderRepository.findAllByConsoCodeAndStatus(consoCode, PickOrderStatus.CONSOLIDATED) |
|
|
|
println(pos) |
|
|
@@ -407,13 +418,22 @@ open class PickOrderService( |
|
|
|
|
|
|
|
val itemIds = requiredItems.mapNotNull { it.first } |
|
|
|
// val inventories = inventoryLotLineRepository.findCurrentInventoryByItems(itemIds) |
|
|
|
val inventories = inventoryService.allInventoriesByItemIds(itemIds) |
|
|
|
// val inventories = inventoryService.allInventoriesByItemIds(itemIds) |
|
|
|
val inventories = inventoryLotLineService |
|
|
|
.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 } |
|
|
|
|
|
|
|
// Pick Orders |
|
|
|
val releasePickOrderInfos = pos |
|
|
|
.map { po -> |
|
|
|
val releasePickOrderLineInfos = po.pickOrderLines.map { pol -> |
|
|
|
val inventory = inventories.find { it.itemId == pol.item?.id } |
|
|
|
// if (pol.item?.id != null && pol.item!!.id!! > 0) { |
|
|
|
val inventory = pol.item?.id.let { inventories[it] } |
|
|
|
// val inventory = inventories.find { it.itemId == pol.item?.id } |
|
|
|
|
|
|
|
// Return |
|
|
|
ReleasePickOrderLineInfo( |
|
|
@@ -421,11 +441,13 @@ open class PickOrderService( |
|
|
|
itemId = pol.item?.id, |
|
|
|
itemCode = pol.item?.code, |
|
|
|
itemName = pol.item?.name, |
|
|
|
availableQty = inventory?.availableQty, |
|
|
|
// availableQty = inventory?.availableQty, |
|
|
|
availableQty = inventory?.sumOf { i -> i.availableQty ?: zero }, |
|
|
|
requiredQty = pol.qty, |
|
|
|
uomCode = pol.uom?.code, |
|
|
|
uomDesc = pol.uom?.udfudesc, |
|
|
|
) |
|
|
|
// } |
|
|
|
} |
|
|
|
|
|
|
|
// Return |
|
|
@@ -441,10 +463,13 @@ open class PickOrderService( |
|
|
|
|
|
|
|
// Items |
|
|
|
val currentInventoryInfos = requiredItems.map { item -> |
|
|
|
val inventory = inventories.find { it.itemId == item.first } |
|
|
|
// val inventory = inventories |
|
|
|
// .find { it.itemId == item.first } |
|
|
|
|
|
|
|
val inventory = item.first?.let { inventories[it] } |
|
|
|
item.second.let { |
|
|
|
it.availableQty = inventory?.availableQty |
|
|
|
// it.availableQty = inventory?.availableQty |
|
|
|
it.availableQty = inventory?.sumOf { i -> i.availableQty ?: zero } |
|
|
|
|
|
|
|
// return |
|
|
|
it |
|
|
@@ -482,17 +507,26 @@ open class PickOrderService( |
|
|
|
this.handler = currUser.id |
|
|
|
} |
|
|
|
stockOutRepository.save(stockOut) |
|
|
|
suggestions.suggestedList.forEach { |
|
|
|
println("suggest ${it.suggestedLotLine?.id}") |
|
|
|
println("pick ${it.pickOrderLine?.id}") |
|
|
|
} |
|
|
|
suggestedPickLotService.saveAll(suggestions.suggestedList) |
|
|
|
|
|
|
|
val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) |
|
|
|
pickOrderRepository.saveAll(pos) |
|
|
|
|
|
|
|
val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn(saveSuggestedPickLots.mapNotNull { it.suggestedLotLine?.id }) |
|
|
|
val inventoryLotLines = |
|
|
|
inventoryLotLineRepository.findAllByIdIn(saveSuggestedPickLots.mapNotNull { it.suggestedLotLine?.id }) |
|
|
|
|
|
|
|
logger.info(saveSuggestedPickLots) |
|
|
|
saveSuggestedPickLots.forEach { lot -> |
|
|
|
// val ratio = lot.suggestedLotLine!!.stockUom |
|
|
|
val lineIndex = inventoryLotLines.indexOf(lot.suggestedLotLine) |
|
|
|
inventoryLotLines[lineIndex].holdQty = (inventoryLotLines[lineIndex].holdQty ?: zero).plus(lot.qty ?: zero) |
|
|
|
if (lot.suggestedLotLine != null && lot.suggestedLotLine?.id != null && lot.suggestedLotLine!!.id!! > 0) { |
|
|
|
val lineIndex = inventoryLotLines.indexOf(lot.suggestedLotLine) |
|
|
|
inventoryLotLines[lineIndex].holdQty = |
|
|
|
(inventoryLotLines[lineIndex].holdQty ?: zero).plus(lot.qty ?: zero) |
|
|
|
} |
|
|
|
} |
|
|
|
// inventoryLotLines.forEach { line -> |
|
|
|
// line.holdQty = (line.holdQty ?: zero)?.plus(saveSuggestedPickLots.find { it.suggestedLotLine == line }?.qty ?: zero) |
|
|
@@ -510,7 +544,7 @@ open class PickOrderService( |
|
|
|
val stockOutLines = stockOutLIneRepository.findAllByStockOutId(stockOut.id!!) |
|
|
|
val unfinishedLines = stockOutLines.filter { |
|
|
|
it.status != StockOutLineStatus.COMPLETE.status |
|
|
|
&& it.status != StockOutLineStatus.REJECTED.status |
|
|
|
&& it.status != StockOutLineStatus.REJECTED.status |
|
|
|
} |
|
|
|
if (unfinishedLines.isEmpty()) { |
|
|
|
stockOut.apply { |
|
|
|