|
@@ -490,6 +490,289 @@ open class PickOrderService( |
|
|
) |
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO: |
|
|
|
|
|
open fun getPickOrdersInfo(ids: List<Long>): GetPickOrderInfoResponse { |
|
|
|
|
|
val today = LocalDate.now() |
|
|
|
|
|
val zero = BigDecimal.ZERO |
|
|
|
|
|
val one = BigDecimal.ONE |
|
|
|
|
|
val pos = pickOrderRepository.findAllByIdIn(ids) |
|
|
|
|
|
println(pos) |
|
|
|
|
|
// Get Inventory Data |
|
|
|
|
|
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 val uomDesc: String? = value[0].uom?.udfudesc |
|
|
|
|
|
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 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 } |
|
|
|
|
|
|
|
|
|
|
|
val suggestions = |
|
|
|
|
|
suggestedPickLotService.suggestionForPickOrders(SuggestedPickLotForPoRequest(pickOrders = pos)) |
|
|
|
|
|
// Pick Orders |
|
|
|
|
|
val releasePickOrderInfos = pos |
|
|
|
|
|
.map { po -> |
|
|
|
|
|
val releasePickOrderLineInfos = po.pickOrderLines.map { pol -> |
|
|
|
|
|
// if (pol.item?.id != null && pol.item!!.id!! > 0) { |
|
|
|
|
|
val inventory = pol.item?.id?.let { inventories[it] } |
|
|
|
|
|
val itemUom = pol.item?.id?.let { itemUomService.findSalesUnitByItemId(it) } |
|
|
|
|
|
// val inventory = inventories.find { it.itemId == pol.item?.id } |
|
|
|
|
|
|
|
|
|
|
|
// Return |
|
|
|
|
|
GetPickOrderLineInfo( |
|
|
|
|
|
id = pol.id, |
|
|
|
|
|
itemId = pol.item?.id, |
|
|
|
|
|
itemCode = pol.item?.code, |
|
|
|
|
|
itemName = pol.item?.name, |
|
|
|
|
|
// availableQty = inventory?.availableQty, |
|
|
|
|
|
availableQty = inventory?.sumOf { i -> (i.availableQty ?: zero) }, |
|
|
|
|
|
// availableQty = inventory?.sumOf { i -> (i.availableQty ?: zero) * (itemUom?.ratioN ?: one) * (itemUom?.ratioD ?: one) }, |
|
|
|
|
|
requiredQty = pol.qty, |
|
|
|
|
|
uomCode = pol.uom?.code, |
|
|
|
|
|
uomDesc = pol.uom?.udfudesc, |
|
|
|
|
|
suggestedList = suggestions.suggestedList.filter { it.pickOrderLine?.id == pol.id } |
|
|
|
|
|
) |
|
|
|
|
|
// } |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Return |
|
|
|
|
|
GetPickOrderInfo( |
|
|
|
|
|
id = po.id, |
|
|
|
|
|
code = po.code, |
|
|
|
|
|
targetDate = po.targetDate, |
|
|
|
|
|
type = po.type?.value, |
|
|
|
|
|
status = po.status?.value, |
|
|
|
|
|
pickOrderLines = releasePickOrderLineInfos |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Items |
|
|
|
|
|
val currentInventoryInfos = requiredItems.map { item -> |
|
|
|
|
|
// val inventory = inventories |
|
|
|
|
|
// .find { it.itemId == item.first } |
|
|
|
|
|
|
|
|
|
|
|
val inventory = item.first?.let { inventories[it] } |
|
|
|
|
|
val itemUom = item.first?.let { itemUomService.findSalesUnitByItemId(it) } |
|
|
|
|
|
|
|
|
|
|
|
item.second.let { |
|
|
|
|
|
// it.availableQty = inventory?.availableQty |
|
|
|
|
|
|
|
|
|
|
|
it.availableQty = inventory?.sumOf { i -> i.availableQty ?: zero } |
|
|
|
|
|
// it.availableQty = inventory?.sumOf { i -> (i.availableQty ?: zero) * (itemUom?.ratioN ?: one) * (itemUom?.ratioD ?: one) } |
|
|
|
|
|
|
|
|
|
|
|
// return |
|
|
|
|
|
it |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return GetPickOrderInfoResponse( |
|
|
|
|
|
// consoCode = consoCode, |
|
|
|
|
|
pickOrders = releasePickOrderInfos, |
|
|
|
|
|
items = currentInventoryInfos, |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
open fun getAllPickOrdersInfo(): GetPickOrderInfoResponse { |
|
|
|
|
|
// 使用现有的查询方法获取所有 Pick Orders,然后在内存中过滤 |
|
|
|
|
|
val allPickOrders = pickOrderRepository.findAll() |
|
|
|
|
|
val releasedPickOrderIds = allPickOrders |
|
|
|
|
|
.filter { it.status == PickOrderStatus.RELEASED } |
|
|
|
|
|
.map { it.id!! } |
|
|
|
|
|
|
|
|
|
|
|
println("All released pick order IDs: $releasedPickOrderIds") |
|
|
|
|
|
|
|
|
|
|
|
// 如果没有任何已发布的 Pick Orders,返回空结果 |
|
|
|
|
|
if (releasedPickOrderIds.isEmpty()) { |
|
|
|
|
|
return GetPickOrderInfoResponse( |
|
|
|
|
|
pickOrders = emptyList(), |
|
|
|
|
|
items = emptyList() |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 重用现有的 getPickOrdersInfo 方法 |
|
|
|
|
|
return getPickOrdersInfo(releasedPickOrderIds) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
open fun getPickOrderLineLotDetails(pickOrderLineId: Long): List<Map<String, Any>> { |
|
|
|
|
|
val today = LocalDate.now() |
|
|
|
|
|
|
|
|
|
|
|
println("=== Debug: getPickOrderLineLotDetails ===") |
|
|
|
|
|
println("pickOrderLineId: $pickOrderLineId") |
|
|
|
|
|
println("today: $today") |
|
|
|
|
|
|
|
|
|
|
|
// 检查具体的数量字段值 |
|
|
|
|
|
val quantityCheckSql = """ |
|
|
|
|
|
SELECT |
|
|
|
|
|
spl.id as suggestedPickLotId, |
|
|
|
|
|
ill.id as lotLineId, |
|
|
|
|
|
ill.inQty, |
|
|
|
|
|
ill.outQty, |
|
|
|
|
|
ill.holdQty, |
|
|
|
|
|
COALESCE(ill.inQty, 0) as inQtyCoalesced, |
|
|
|
|
|
COALESCE(ill.outQty, 0) as outQtyCoalesced, |
|
|
|
|
|
COALESCE(ill.holdQty, 0) as holdQtyCoalesced, |
|
|
|
|
|
(COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as availableQtyCalculated |
|
|
|
|
|
FROM fpsmsdb.suggested_pick_lot spl |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId |
|
|
|
|
|
WHERE spl.pickOrderLineId = :pickOrderLineId |
|
|
|
|
|
AND ill.status = 'available' |
|
|
|
|
|
""".trimIndent() |
|
|
|
|
|
|
|
|
|
|
|
val quantityCheckResult = jdbcDao.queryForList(quantityCheckSql, mapOf("pickOrderLineId" to pickOrderLineId)) |
|
|
|
|
|
println("Quantity check result:") |
|
|
|
|
|
quantityCheckResult.forEach { row -> |
|
|
|
|
|
println("Row: $row") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查日期条件 |
|
|
|
|
|
val dateCheckSql = """ |
|
|
|
|
|
SELECT |
|
|
|
|
|
spl.id as suggestedPickLotId, |
|
|
|
|
|
ill.id as lotLineId, |
|
|
|
|
|
il.lotNo, |
|
|
|
|
|
il.expiryDate, |
|
|
|
|
|
:today as today, |
|
|
|
|
|
il.expiryDate >= :today as isNotExpired, |
|
|
|
|
|
il.expiryDate IS NULL as isNullExpiry |
|
|
|
|
|
FROM fpsmsdb.suggested_pick_lot spl |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId |
|
|
|
|
|
WHERE spl.pickOrderLineId = :pickOrderLineId |
|
|
|
|
|
AND ill.status = 'available' |
|
|
|
|
|
AND (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) > 0 |
|
|
|
|
|
""".trimIndent() |
|
|
|
|
|
|
|
|
|
|
|
val dateCheckResult = jdbcDao.queryForList(dateCheckSql, mapOf("pickOrderLineId" to pickOrderLineId, "today" to today)) |
|
|
|
|
|
println("Date check result:") |
|
|
|
|
|
dateCheckResult.forEach { row -> |
|
|
|
|
|
println("Row: $row") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查 warehouse JOIN |
|
|
|
|
|
val warehouseCheckSql = """ |
|
|
|
|
|
SELECT |
|
|
|
|
|
spl.id as suggestedPickLotId, |
|
|
|
|
|
ill.id as lotLineId, |
|
|
|
|
|
ill.warehouseId, |
|
|
|
|
|
w.id as warehouseId, |
|
|
|
|
|
w.name as warehouseName |
|
|
|
|
|
FROM fpsmsdb.suggested_pick_lot spl |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId |
|
|
|
|
|
JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId |
|
|
|
|
|
WHERE spl.pickOrderLineId = :pickOrderLineId |
|
|
|
|
|
AND ill.status = 'available' |
|
|
|
|
|
AND (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) > 0 |
|
|
|
|
|
AND (il.expiryDate IS NULL OR il.expiryDate >= :today) |
|
|
|
|
|
""".trimIndent() |
|
|
|
|
|
|
|
|
|
|
|
val warehouseCheckResult = jdbcDao.queryForList(warehouseCheckSql, mapOf("pickOrderLineId" to pickOrderLineId, "today" to today)) |
|
|
|
|
|
println("Warehouse check result count: ${warehouseCheckResult.size}") |
|
|
|
|
|
warehouseCheckResult.forEach { row -> |
|
|
|
|
|
println("Warehouse Row: $row") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 检查 uom_conversion JOIN - 使用 LEFT JOIN 并检查 stockItemUomId |
|
|
|
|
|
val uomCheckSql = """ |
|
|
|
|
|
SELECT |
|
|
|
|
|
spl.id as suggestedPickLotId, |
|
|
|
|
|
ill.id as lotLineId, |
|
|
|
|
|
ill.stockItemUomId, |
|
|
|
|
|
uc.id as uomId, |
|
|
|
|
|
uc.code as uomCode |
|
|
|
|
|
FROM fpsmsdb.suggested_pick_lot spl |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId |
|
|
|
|
|
JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId |
|
|
|
|
|
LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = ill.stockItemUomId |
|
|
|
|
|
WHERE spl.pickOrderLineId = :pickOrderLineId |
|
|
|
|
|
AND ill.status = 'available' |
|
|
|
|
|
AND (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) > 0 |
|
|
|
|
|
AND (il.expiryDate IS NULL OR il.expiryDate >= :today) |
|
|
|
|
|
""".trimIndent() |
|
|
|
|
|
|
|
|
|
|
|
val uomCheckResult = jdbcDao.queryForList(uomCheckSql, mapOf("pickOrderLineId" to pickOrderLineId, "today" to today)) |
|
|
|
|
|
println("UOM check result count: ${uomCheckResult.size}") |
|
|
|
|
|
uomCheckResult.forEach { row -> |
|
|
|
|
|
println("UOM Row: $row") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 修改查询,通过 item_uom 表获取 UOM 信息 |
|
|
|
|
|
val sql = """ |
|
|
|
|
|
SELECT |
|
|
|
|
|
ill.id as lotId, |
|
|
|
|
|
il.lotNo, |
|
|
|
|
|
il.expiryDate, |
|
|
|
|
|
w.name as location, |
|
|
|
|
|
COALESCE(uc.code, 'N/A') as stockUnit, |
|
|
|
|
|
(COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as availableQty, |
|
|
|
|
|
spl.qty as requiredQty, |
|
|
|
|
|
COALESCE(sol.qty, 0) as actualPickQty, |
|
|
|
|
|
spl.id as suggestedPickLotId, |
|
|
|
|
|
ill.status as lotStatus, |
|
|
|
|
|
CASE |
|
|
|
|
|
WHEN ill.status != 'available' THEN 'status_unavailable' |
|
|
|
|
|
WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < :today) THEN 'expired' |
|
|
|
|
|
WHEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) < spl.qty THEN 'insufficient_stock' |
|
|
|
|
|
ELSE 'available' |
|
|
|
|
|
END as lotAvailability |
|
|
|
|
|
FROM fpsmsdb.suggested_pick_lot spl |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot_line ill ON ill.id = spl.suggestedLotLineId |
|
|
|
|
|
JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId |
|
|
|
|
|
JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId |
|
|
|
|
|
LEFT JOIN fpsmsdb.item_uom iu ON iu.id = ill.stockItemUomId |
|
|
|
|
|
LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = iu.uomId |
|
|
|
|
|
LEFT JOIN fpsmsdb.stock_out_line sol ON sol.inventoryLotLineId = ill.id |
|
|
|
|
|
AND sol.pickOrderLineId = spl.pickOrderLineId |
|
|
|
|
|
WHERE spl.pickOrderLineId = :pickOrderLineId |
|
|
|
|
|
ORDER BY |
|
|
|
|
|
CASE lotAvailability |
|
|
|
|
|
WHEN 'available' THEN 1 |
|
|
|
|
|
WHEN 'insufficient_stock' THEN 2 |
|
|
|
|
|
WHEN 'expired' THEN 3 |
|
|
|
|
|
WHEN 'status_unavailable' THEN 4 |
|
|
|
|
|
END, |
|
|
|
|
|
il.expiryDate ASC |
|
|
|
|
|
""".trimIndent() |
|
|
|
|
|
|
|
|
|
|
|
val params = mapOf( |
|
|
|
|
|
"pickOrderLineId" to pickOrderLineId, |
|
|
|
|
|
"today" to today |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
val result = jdbcDao.queryForList(sql, params) |
|
|
|
|
|
println("Final result count: ${result.size}") |
|
|
|
|
|
result.forEach { row -> |
|
|
|
|
|
println("Final Row: $row") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Transactional(rollbackFor = [java.lang.Exception::class]) |
|
|
@Transactional(rollbackFor = [java.lang.Exception::class]) |
|
|
open fun releaseConsoPickOrderAction(request: ReleaseConsoPickOrderRequest): ReleasePickOrderInfoResponse { |
|
|
open fun releaseConsoPickOrderAction(request: ReleaseConsoPickOrderRequest): ReleasePickOrderInfoResponse { |
|
|
val zero = BigDecimal.ZERO |
|
|
val zero = BigDecimal.ZERO |
|
|