@@ -2,18 +2,16 @@ package com.ffii.fpsms.modules.pickOrder.service | |||
import com.ffii.core.response.RecordsRes | |||
import com.ffii.fpsms.modules.common.SecurityUtils | |||
import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrder | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository | |||
import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderInfo | |||
import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderLineInfo | |||
import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus | |||
import com.ffii.fpsms.modules.pickOrder.web.models.* | |||
import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository | |||
import com.ffii.fpsms.modules.stock.entity.projection.CurrentInventoryItemInfo | |||
import com.ffii.fpsms.modules.stock.service.StockOutLineService | |||
import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService | |||
import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotForPoRequest | |||
import com.ffii.fpsms.modules.user.service.UserService | |||
import org.springframework.context.annotation.Lazy | |||
import org.springframework.data.domain.PageRequest | |||
import org.springframework.stereotype.Service | |||
import java.io.Serializable | |||
@@ -28,7 +26,7 @@ open class PickOrderService( | |||
val pickOrderRepository: PickOrderRepository, | |||
val stockOutLineService: StockOutLineService, | |||
val suggestedPickLotService: SuggestedPickLotService, | |||
val userService: UserService, | |||
val userService: UserService, private val inventoryLotLineRepository: InventoryLotLineRepository, | |||
) { | |||
open fun localDateTimeParse(dateTime: String?, pattern: String? = "YYYY-MM-DD hh:mm:ss"): LocalDateTime? { | |||
try { | |||
@@ -69,7 +67,6 @@ open class PickOrderService( | |||
val prefix = "PICK" | |||
val midfix = LocalDate.now().format(formatter) | |||
println(midfix) | |||
val suffix = String.format(suffixFormat, 1) | |||
val latestConsoCode = pickOrderRepository.findLatestConsoCodeByPrefix("${prefix}-${midfix}") | |||
@@ -240,16 +237,43 @@ open class PickOrderService( | |||
return response | |||
} | |||
open fun releaseConsoPickOrderInfo() { | |||
open fun releaseConsoPickOrderInfo(request: ReleaseConsoPickOrderRequest): ReleasePickOrderInfoResponse { | |||
val zero = BigDecimal.ZERO | |||
val pos = pickOrderRepository.findAllByConsoCode(request.consoCode) | |||
val requiredItems = pos | |||
.flatMap { it.pickOrderLines } | |||
.groupBy { it.item?.id } | |||
.map { (key, value) -> key to object : CurrentInventoryItemInfo { | |||
override val id: Long? = value[0].item?.id | |||
override val code: String? = value[0].item?.code | |||
override val name: String? = value[0].item?.name | |||
override var availableQty: BigDecimal? = zero | |||
override val requiredQty: BigDecimal = value.sumOf { it.qty ?: zero } | |||
}} // itemId - requiredQty | |||
val itemIds = requiredItems.mapNotNull { it.first } | |||
val inventories = inventoryLotLineRepository.findCurrentInventoryByItems(itemIds) | |||
val currentInventoryInfos = requiredItems.map { item -> | |||
val inventory = inventories.find { it.id == item.first } | |||
item.second.let { | |||
it.availableQty = inventory?.availableQty | |||
// return | |||
it | |||
} | |||
} | |||
return ReleasePickOrderInfoResponse( | |||
consoCode = request.consoCode, | |||
items = currentInventoryInfos, | |||
) | |||
} | |||
open fun releaseConsoPickOrderAction(request: ReleaseConsoPickOrderRequest) { | |||
val releasedBy = SecurityUtils.getUser().getOrNull() | |||
val assignTo = request.assignTo?.let { userService.find(it) }?.getOrNull() | |||
println("123") | |||
val pos = pickOrderRepository.findAllByConsoCode(request.consoCode) | |||
println("456") | |||
pos.forEach { | |||
it.apply { | |||
this.releasedBy = releasedBy | |||
@@ -257,10 +281,6 @@ open class PickOrderService( | |||
status = PickOrderStatus.RELEASED | |||
} | |||
} | |||
println(pos[0].releasedBy?.id) | |||
pickOrderRepository.saveAll(pos) | |||
// val suggestedPickLots = suggestedPickLotService.convertRequestsToEntities(request.suggestedPickLots) | |||
// | |||
// suggestedPickLotService.saveAll(suggestedPickLots) | |||
} | |||
} |
@@ -4,10 +4,7 @@ import com.ffii.core.response.RecordsRes | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository | |||
import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderInfo | |||
import com.ffii.fpsms.modules.pickOrder.service.PickOrderService | |||
import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderRequest | |||
import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderResponse | |||
import com.ffii.fpsms.modules.pickOrder.web.models.ReleaseConsoPickOrderRequest | |||
import com.ffii.fpsms.modules.pickOrder.web.models.SearchPickOrderRequest | |||
import com.ffii.fpsms.modules.pickOrder.web.models.* | |||
import jakarta.validation.Valid | |||
import org.springframework.data.domain.Page | |||
import org.springframework.data.domain.PageRequest | |||
@@ -56,8 +53,13 @@ class PickOrderController( | |||
return pickOrderService.consoPickOrderDetail(consoCode); | |||
} | |||
@GetMapping("/releaseConso") | |||
fun releaseConsoPickOrderInfo(@Valid @RequestBody request: ReleaseConsoPickOrderRequest): ReleasePickOrderInfoResponse { | |||
return pickOrderService.releaseConsoPickOrderInfo(request); | |||
} | |||
@PostMapping("/releaseConso") | |||
fun releaseConsoPickOrders(@Valid @RequestBody request: ReleaseConsoPickOrderRequest) { | |||
fun releaseConsoPickOrderAction(@Valid @RequestBody request: ReleaseConsoPickOrderRequest) { | |||
pickOrderService.releaseConsoPickOrderAction(request) | |||
} | |||
} |
@@ -1,20 +1,13 @@ | |||
package com.ffii.fpsms.modules.pickOrder.web.models | |||
import com.ffii.fpsms.modules.stock.entity.projection.CurrentInventoryItemInfo | |||
import java.math.BigDecimal | |||
import java.time.LocalDateTime | |||
// Final Response - Release Conso Pick Order Page | |||
data class ReleasePickOrderInfoResponse( | |||
val consoCode: String, | |||
val inventory: List<ReleasePickOrderInfoInventory> | |||
) | |||
data class ReleasePickOrderInfoInventory( | |||
val id: Long?, | |||
val itemCode: String?, | |||
val itemName: String?, | |||
val availableQty: BigDecimal?, | |||
val requiredQty: BigDecimal?, | |||
val items: List<CurrentInventoryItemInfo> | |||
) | |||
// Final Response - Conso Pick Order Detail | |||
@@ -1,11 +1,27 @@ | |||
package com.ffii.fpsms.modules.stock.entity | |||
import com.ffii.core.support.AbstractRepository | |||
import com.ffii.fpsms.modules.stock.entity.projection.CurrentInventoryItemInfo | |||
import com.ffii.fpsms.modules.stock.entity.projection.InventoryLotLineInfo | |||
import org.springframework.data.jpa.repository.Query | |||
import org.springframework.stereotype.Repository | |||
import java.io.Serializable | |||
@Repository | |||
interface InventoryLotLineRepository : AbstractRepository<InventoryLotLine, Long> { | |||
fun findInventoryLotLineInfoByInventoryLotItemIdIn(ids: List<Serializable>): List<InventoryLotLineInfo> | |||
@Query(""" | |||
select | |||
i.id as id, | |||
i.code as itemCode, | |||
i.name as itemName, | |||
sum(coalesce(ill.inQty, 0) - coalesce(ill.outQty, 0) - coalesce(ill.holdQty, 0)) as availableQty | |||
from InventoryLotLine ill | |||
left join InventoryLot il on ill.inventoryLot = il | |||
left join Items i on il.item = i | |||
where i.id in :items | |||
group by i.id | |||
""") | |||
fun findCurrentInventoryByItems(items: List<Serializable>): List<CurrentInventoryItemInfo> | |||
} |
@@ -20,17 +20,29 @@ interface InventoryLotLineWarehouseInfo { | |||
interface InventoryLotLineInfo { | |||
val id: Long? | |||
@get:Value("#{target.inventoryLot.item}") | |||
val item: InventoryLotLineItemInfo? | |||
val warehouse: InventoryLotLineWarehouseInfo? | |||
var inQty: BigDecimal? | |||
var outQty: BigDecimal? | |||
var holdQty: BigDecimal? | |||
@get:Value("#{target.status.value}") | |||
val status: String? | |||
val remarks: String? | |||
@get:Value("#{target.stockUom.uom.udfudesc}") | |||
val uom: String? | |||
@get:Value("#{target.inventoryLot.expiryDate}") | |||
val expiryDate: LocalDate | |||
} | |||
interface CurrentInventoryItemInfo { | |||
val id: Long? // item id | |||
val code: String? | |||
val name: String? | |||
val availableQty: BigDecimal? | |||
val requiredQty: BigDecimal? | |||
} |
@@ -3,10 +3,7 @@ package com.ffii.fpsms.modules.stock.service | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrder | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLineRepository | |||
import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository | |||
import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository | |||
import com.ffii.fpsms.modules.stock.entity.SuggestPickLotRepository | |||
import com.ffii.fpsms.modules.stock.entity.SuggestedPickLot | |||
import com.ffii.fpsms.modules.stock.entity.* | |||
import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus | |||
import com.ffii.fpsms.modules.stock.entity.projection.InventoryLotLineInfo | |||
import com.ffii.fpsms.modules.stock.enums.SuggestedPickLotType | |||
@@ -27,6 +24,22 @@ open class SuggestedPickLotService( | |||
val pickOrderLineRepository: PickOrderLineRepository, | |||
val inventoryLotLineService: InventoryLotLineService, | |||
) { | |||
// Calculation Available Qty / Remaining Qty | |||
open fun calculateRemainingQtyForInfo(inventoryLotLine: InventoryLotLineInfo?): BigDecimal { | |||
val zero = BigDecimal.ZERO | |||
return (inventoryLotLine?.inQty ?: zero) | |||
.minus(inventoryLotLine?.outQty ?: zero) | |||
.minus((inventoryLotLine?.holdQty ?: zero)) | |||
} | |||
open fun calculateRemainingQty(inventoryLotLine: InventoryLotLine?): BigDecimal { | |||
val zero = BigDecimal.ZERO | |||
return (inventoryLotLine?.inQty ?: zero) | |||
.minus(inventoryLotLine?.outQty ?: zero) | |||
.minus((inventoryLotLine?.holdQty ?: zero)) | |||
} | |||
// Suggestion | |||
open fun suggestionForPickOrders(request: SuggestedPickLotForPoRequest): SuggestedPickLotResponse { | |||
val pos = request.pickOrders | |||
val suggestedList = mutableListOf<SuggestedPickLot>() | |||
@@ -70,11 +83,9 @@ open class SuggestedPickLotService( | |||
lotLines.forEachIndexed { index, lotLine -> | |||
if (remainingQty <= zero) return@forEachIndexed | |||
val availableQty = (lotLine.inQty ?: zero) | |||
.minus(lotLine.outQty ?: zero) | |||
.minus((lotLine.holdQty ?: zero) | |||
.plus(holdQtyMap[lotLine.id] ?: zero) | |||
) | |||
val availableQty = calculateRemainingQtyForInfo(lotLine) | |||
.minus(holdQtyMap[lotLine.id] ?: zero) | |||
if (availableQty <= zero) { | |||
updatedLotLines += lotLine | |||
@@ -109,6 +120,25 @@ open class SuggestedPickLotService( | |||
return SuggestedPickLotResponse(holdQtyMap = holdQtyMap, suggestedList = suggestedList) | |||
} | |||
// Convertion | |||
open fun convertRequestsToEntities(request: List<SaveSuggestedPickLotRequest>): List<SuggestedPickLot> { | |||
// val zero = BigDecimal.ZERO | |||
// val entities = mutableListOf<SuggestedPickLot>() | |||
// val holdQtyCount = mutableMapOf<Long?, BigDecimal?>() | |||
// request.forEach { | |||
// val entity = convertRequestToEntity(it) | |||
// val suggestedLotLine = entity.suggestedLotLine | |||
// val remainQty = calculateRemainingQty(suggestedLotLine) | |||
// holdQtyCount[suggestedLotLine?.id] = (holdQtyCount[suggestedLotLine?.id] ?: zero).plus(suggestedLotLine?.holdQty ?: zero) | |||
// if (remainQty.minus(holdQtyCount[suggestedLotLine?.id] ?: zero) < zero) { | |||
// throw RuntimeException("The suggested pick qty is over. Please re-suggest the pick qty."); | |||
// } | |||
// entities += entity | |||
// } | |||
// return entities | |||
return request.map { convertRequestToEntity(it) } | |||
} | |||
open fun convertRequestToEntity(request: SaveSuggestedPickLotRequest): SuggestedPickLot{ | |||
val suggestedPickLot = | |||
request.id?.let { id -> suggestedPickLotRepository.findById(id).getOrDefault(SuggestedPickLot()) } | |||
@@ -130,6 +160,7 @@ open class SuggestedPickLotService( | |||
return suggestedPickLot | |||
} | |||
// Save | |||
open fun saveSuggestedPickLot(request: SaveSuggestedPickLotRequest): SuggestedPickLot { | |||
val suggestedPickLot = convertRequestToEntity(request) | |||