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