@@ -9,7 +9,7 @@ import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus | |||
import com.ffii.fpsms.modules.pickOrder.web.models.* | |||
import com.ffii.fpsms.modules.stock.service.StockOutLineService | |||
import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService | |||
import com.ffii.fpsms.modules.stock.web.model.SuggestInventoryLotLineResponse | |||
import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotForPoRequest | |||
import org.springframework.context.annotation.Lazy | |||
import org.springframework.data.domain.PageRequest | |||
import org.springframework.stereotype.Service | |||
@@ -25,7 +25,7 @@ open class PickOrderService( | |||
val stockOutLineService: StockOutLineService, | |||
val suggestedPickLotService: SuggestedPickLotService, | |||
) { | |||
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 { | |||
val formatter = DateTimeFormatter.ofPattern(pattern!!) | |||
return LocalDateTime.parse(dateTime, formatter) | |||
@@ -43,8 +43,8 @@ open class PickOrderService( | |||
val response = pickOrderRepository.findPickOrderInfoByConditionsAndPageable( | |||
code = request.code ?: "all", | |||
targetDateFrom = LocalDateTimeParse(request.targetDateFrom), | |||
targetDateTo = LocalDateTimeParse(request.targetDateTo), | |||
targetDateFrom = localDateTimeParse(request.targetDateFrom), | |||
targetDateTo = localDateTimeParse(request.targetDateTo), | |||
type = request.type ?: "all", | |||
status = request.status ?: "all", | |||
itemName = request.itemName ?: "all", | |||
@@ -106,21 +106,23 @@ open class PickOrderService( | |||
return updatedPickOrderInfos | |||
} | |||
// TODO: Add actual pick lots | |||
open fun consoPickOrderDetail(consoCode: String): ConsoPickOrderResponse { | |||
// Conso code | |||
// Pick orders with items | |||
// Items | |||
val zero = BigDecimal.ZERO | |||
// pick orders | |||
// Mapping: PickOrder -> PickOrderInConso | |||
val pos = pickOrderRepository.findAllByConsoCode(consoCode) | |||
// Suggestions for Pick Order | |||
val suggestions = suggestedPickLotService.suggestionForPickOrders(SuggestedPickLotForPoRequest(pickOrders = pos)) | |||
val suggestedList = suggestions.suggestedList | |||
// Mapping: PickOrder -> PickOrderInConso | |||
val finalPos = pos.map { po -> | |||
val pols = po.pickOrderLines | |||
// Suggestions for Pick Order Line | |||
val suggestions = suggestedPickLotService.suggestionForPickOrderLines(pols) | |||
// val suggestions = suggestedPickLotService.suggestionForPickOrderLines(pols) | |||
// Pick Order Lines | |||
// Mapping: PickOrderLine -> PickOrderLineInConso | |||
@@ -131,7 +133,7 @@ open class PickOrderService( | |||
// Check If already have suggestion | |||
var suggestion = pol.suggestedPickLots | |||
if (suggestion.isEmpty()) { | |||
suggestion = suggestions.filter { it.pickOrderLine?.id == pol.id }.toMutableList() | |||
suggestion = suggestedList.filter { it.pickOrderLine?.id == pol.id }.toMutableList() | |||
} | |||
// Mapping: SuggestedPickLot -> SuggestPickLotInConso | |||
@@ -217,8 +219,7 @@ open class PickOrderService( | |||
code = _line.first().item.code, | |||
name = _line.first().item.name, | |||
qty = _line.fold(zero) { sum, item -> sum + (item.qty ?: zero)}, | |||
suggestPickLots = _line | |||
.flatMap { it.suggestPickLots }, | |||
suggestPickLots = itemSuggestions, | |||
actualPickLots = mutableListOf() | |||
) | |||
} | |||
@@ -231,4 +232,8 @@ open class PickOrderService( | |||
return response | |||
} | |||
open fun releaseConsoPickOrder(request: ReleaseConsoPickOrderRequest) { | |||
val pos = pickOrderRepository.findAllByConsoCode(request.consoCode) | |||
} | |||
} |
@@ -1,5 +1,14 @@ | |||
package com.ffii.fpsms.modules.pickOrder.web.models | |||
import com.ffii.fpsms.modules.stock.web.model.SaveSuggestedPickLotRequest | |||
// Consolidated / De-consolidated | |||
data class ConsoPickOrderRequest ( | |||
val ids: List<Long> | |||
) | |||
// Release Consolidated Pick Order | |||
data class ReleaseConsoPickOrderRequest ( | |||
val consoCode: String, | |||
val suggestedPickLots: List<SaveSuggestedPickLotRequest> | |||
) |
@@ -1,5 +1,6 @@ | |||
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 | |||
@@ -10,7 +11,9 @@ 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 | |||
import com.ffii.fpsms.modules.stock.web.model.SaveSuggestedPickLotRequest | |||
import com.ffii.fpsms.modules.stock.web.model.SuggestInventoryLotLineResponse | |||
import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotForPoRequest | |||
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 kotlin.jvm.optionals.getOrDefault | |||
@@ -24,12 +27,31 @@ open class SuggestedPickLotService( | |||
val pickOrderLineRepository: PickOrderLineRepository, | |||
val inventoryLotLineService: InventoryLotLineService, | |||
) { | |||
open fun suggestionForPickOrders(request: SuggestedPickLotForPoRequest): SuggestedPickLotResponse { | |||
val pos = request.pickOrders | |||
val suggestedList = mutableListOf<SuggestedPickLot>() | |||
var holdQtyMap = request.holdQtyMap | |||
open fun suggestionForPickOrderLines(pickOrderlines: List<PickOrderLine>): List<SuggestedPickLot> { | |||
val itemIds = pickOrderlines.mapNotNull { it.item?.id } | |||
pos.forEach { | |||
val response = suggestionForPickOrderLines(SuggestedPickLotForPolRequest( | |||
holdQtyMap = holdQtyMap, | |||
pickOrderLines = it.pickOrderLines | |||
)) | |||
holdQtyMap = response.holdQtyMap | |||
suggestedList += response.suggestedList | |||
} | |||
return SuggestedPickLotResponse(holdQtyMap = holdQtyMap, suggestedList = suggestedList) | |||
} | |||
open fun suggestionForPickOrderLines(request: SuggestedPickLotForPolRequest): SuggestedPickLotResponse { | |||
val pols = request.pickOrderLines | |||
val itemIds = pols.mapNotNull { it.item?.id } | |||
val zero = BigDecimal.ZERO | |||
val suggestionList: MutableList<SuggestedPickLot> = mutableListOf() | |||
val suggestedList: MutableList<SuggestedPickLot> = mutableListOf() | |||
val holdQtyMap: MutableMap<Long?, BigDecimal?> = request.holdQtyMap | |||
// get current inventory lot line qty & grouped by item Id | |||
val availableInventoryLotLines = inventoryLotLineService | |||
@@ -40,7 +62,7 @@ open class SuggestedPickLotService( | |||
.groupBy { it.item?.id } | |||
// loop for suggest pick lot line | |||
pickOrderlines.forEach { line -> | |||
pols.forEach { line -> | |||
val lotLines = availableInventoryLotLines[line.item?.id].orEmpty() | |||
var remainingQty = line.qty ?: zero | |||
val updatedLotLines = mutableListOf<InventoryLotLineInfo>() | |||
@@ -50,58 +72,44 @@ open class SuggestedPickLotService( | |||
val availableQty = (lotLine.inQty ?: zero) | |||
.minus(lotLine.outQty ?: zero) | |||
.minus(lotLine.holdQty ?: zero) | |||
.minus((lotLine.holdQty ?: zero) | |||
.plus(holdQtyMap[lotLine.id] ?: zero) | |||
) | |||
if (availableQty <= zero) { | |||
updatedLotLines += lotLine | |||
return@forEachIndexed | |||
} | |||
val inventoryLotLine = lotLine.id?.let { inventoryLotLineService.findById(it).getOrNull() } | |||
// println("1:${inventoryLotLine?.id}: ${inventoryLotLine?.holdQty}") | |||
val originalHoldQty = inventoryLotLine?.holdQty | |||
// Update Qty | |||
val assignQty = minOf(availableQty, remainingQty) | |||
remainingQty = remainingQty.minus(assignQty) | |||
lotLine.holdQty = lotLine.holdQty?.plus(assignQty) | |||
// println("2:${inventoryLotLine?.id}: ${inventoryLotLine?.holdQty}") | |||
// println("3:${inventoryLotLine?.id}: ${originalHoldQty}") | |||
suggestionList += SuggestedPickLot().apply { | |||
holdQtyMap[lotLine.id] = (holdQtyMap[lotLine.id] ?: zero).plus(assignQty) | |||
// lotLine.holdQty = lotLine.holdQty?.plus(assignQty) | |||
suggestedList += SuggestedPickLot().apply { | |||
type = SuggestedPickLotType.PICK_ORDER | |||
suggestedLotLine = inventoryLotLine?.apply { | |||
holdQty = originalHoldQty | |||
} | |||
suggestedLotLine = inventoryLotLine | |||
pickOrderLine = line | |||
qty = assignQty | |||
} | |||
// suggestionList += SuggestInventoryLotLineResponse( | |||
// type = SuggestedPickLotType.PICK_ORDER.value, | |||
// suggestedLotLine = inventoryLotLine, | |||
// pickOrderLine = line, | |||
// qty = assignQty | |||
// ) | |||
} | |||
// if still have remainingQty | |||
if (remainingQty > zero) { | |||
suggestionList += SuggestedPickLot().apply { | |||
suggestedList += SuggestedPickLot().apply { | |||
type = SuggestedPickLotType.PICK_ORDER | |||
suggestedLotLine = null | |||
pickOrderLine = line | |||
qty = null | |||
qty = remainingQty | |||
} | |||
// suggestionList += SuggestInventoryLotLineResponse( | |||
// type = SuggestedPickLotType.PICK_ORDER.value, | |||
// suggestedLotLine = null, | |||
// pickOrderLine = line, | |||
// qty = null | |||
// ) | |||
} | |||
} | |||
return suggestionList | |||
return SuggestedPickLotResponse(holdQtyMap = holdQtyMap, suggestedList = suggestedList) | |||
} | |||
open fun saveSuggestedPickLot(request: SaveSuggestedPickLotRequest): SuggestedPickLot { | |||
open fun convertRequestToEntity(request: SaveSuggestedPickLotRequest): SuggestedPickLot{ | |||
val suggestedPickLot = | |||
request.id?.let { id -> suggestedPickLotRepository.findById(id).getOrDefault(SuggestedPickLot()) } | |||
?: SuggestedPickLot() | |||
@@ -119,6 +127,16 @@ open class SuggestedPickLotService( | |||
qty = request.qty | |||
} | |||
return suggestedPickLot | |||
} | |||
open fun saveSuggestedPickLot(request: SaveSuggestedPickLotRequest): SuggestedPickLot { | |||
val suggestedPickLot = convertRequestToEntity(request) | |||
return suggestedPickLotRepository.save(suggestedPickLot) | |||
} | |||
open fun saveAll(request: List<SuggestedPickLot>): List<SuggestedPickLot> { | |||
return suggestedPickLotRepository.saveAll(request) | |||
} | |||
} |
@@ -7,6 +7,7 @@ import com.ffii.fpsms.modules.purchaseOrder.service.PurchaseOrderLineService | |||
import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService | |||
import org.springframework.web.bind.annotation.GetMapping | |||
import org.springframework.web.bind.annotation.PathVariable | |||
import org.springframework.web.bind.annotation.PostMapping | |||
import org.springframework.web.bind.annotation.RequestMapping | |||
import org.springframework.web.bind.annotation.RestController | |||
@@ -1,13 +0,0 @@ | |||
package com.ffii.fpsms.modules.stock.web.model | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine | |||
import com.ffii.fpsms.modules.stock.entity.InventoryLotLine | |||
import com.ffii.fpsms.modules.stock.enums.SuggestedPickLotType | |||
import java.math.BigDecimal | |||
data class SuggestInventoryLotLineResponse( | |||
val type: String?, | |||
val suggestedLotLine: InventoryLotLine?, | |||
val pickOrderLine: PickOrderLine?, | |||
val qty: BigDecimal? | |||
) |
@@ -0,0 +1,17 @@ | |||
package com.ffii.fpsms.modules.stock.web.model | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrder | |||
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine | |||
import java.math.BigDecimal | |||
data class SuggestedPickLotForPoRequest( | |||
val holdQtyMap: MutableMap<Long?, BigDecimal?> = mutableMapOf(), | |||
val pickOrders: List<PickOrder> | |||
) | |||
data class SuggestedPickLotForPolRequest( | |||
val holdQtyMap: MutableMap<Long?, BigDecimal?> = mutableMapOf(), | |||
val pickOrderLines: List<PickOrderLine> | |||
) | |||
@@ -0,0 +1,16 @@ | |||
package com.ffii.fpsms.modules.stock.web.model | |||
import com.ffii.fpsms.modules.stock.entity.SuggestedPickLot | |||
import java.math.BigDecimal | |||
//data class SuggestInventoryLotLine( | |||
// val type: String?, | |||
// val suggestedLotLine: InventoryLotLine?, | |||
// val pickOrderLine: PickOrderLine?, | |||
// val qty: BigDecimal? | |||
//) | |||
data class SuggestedPickLotResponse( | |||
val holdQtyMap: MutableMap<Long?, BigDecimal?>, | |||
val suggestedList: List<SuggestedPickLot> | |||
) |