|
|
|
@@ -2086,6 +2086,157 @@ logger.info("Precreated $precreated stock out lines for suggested lots on releas |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
@Transactional(rollbackFor = [java.lang.Exception::class]) |
|
|
|
open fun autoAssignAndReleasePickOrderByStore(userId: Long, storeId: String): MessageResponse { |
|
|
|
try { |
|
|
|
println("=== DEBUG: autoAssignAndReleasePickOrderByStore ===") |
|
|
|
println("userId: $userId, storeId: $storeId") |
|
|
|
|
|
|
|
val zero = BigDecimal.ZERO |
|
|
|
val releasedBy = SecurityUtils.getUser().getOrNull() |
|
|
|
val user = userService.find(userId).orElse(null) |
|
|
|
|
|
|
|
if (user == null) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, name = "User not found", code = "ERROR", type = "pickorder", |
|
|
|
message = "User with ID $userId not found", errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
// Get candidate pick order IDs by store from do_pick_order |
|
|
|
val sql = """ |
|
|
|
SELECT DISTINCT dpo.pick_order_id AS pickOrderId |
|
|
|
FROM do_pick_order dpo |
|
|
|
WHERE dpo.deleted = false |
|
|
|
AND dpo.ticket_status = 'pending' |
|
|
|
AND dpo.store_id = :storeId |
|
|
|
AND dpo.pick_order_id IS NOT NULL |
|
|
|
""".trimIndent() |
|
|
|
val idRows = jdbcDao.queryForList(sql, mapOf("storeId" to storeId)) |
|
|
|
val pickOrderIdsByStore = idRows.mapNotNull { row -> |
|
|
|
when (val id = row["pickOrderId"]) { |
|
|
|
is Number -> id.toLong() |
|
|
|
is String -> id.toLongOrNull() |
|
|
|
else -> null |
|
|
|
} |
|
|
|
}.toSet() |
|
|
|
println("Candidate pickOrderIds by store $storeId: $pickOrderIdsByStore") |
|
|
|
|
|
|
|
if (pickOrderIdsByStore.isEmpty()) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, name = "No pick orders", code = "NO_ORDERS", type = "pickorder", |
|
|
|
message = "No pending pick orders found for store $storeId", errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
// Filter to available pending DO pick orders by ID and earliest target date |
|
|
|
val availablePickOrders = pickOrderRepository |
|
|
|
.findAll() |
|
|
|
.filter { it.status == PickOrderStatus.PENDING } |
|
|
|
.filter { it.deliveryOrder != null } |
|
|
|
.filter { it.id != null && pickOrderIdsByStore.contains(it.id!!) } |
|
|
|
.sortedBy { it.targetDate } |
|
|
|
.take(1) |
|
|
|
|
|
|
|
if (availablePickOrders.isEmpty()) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, name = "No available pick orders", code = "NO_ORDERS", type = "pickorder", |
|
|
|
message = "No pending pick orders available for store $storeId", errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val newConsoCode = assignConsoCode() |
|
|
|
val currUser = SecurityUtils.getUser().orElseThrow() |
|
|
|
|
|
|
|
// Create stock out early |
|
|
|
val stockOut = StockOut().apply { |
|
|
|
this.type = "job" |
|
|
|
this.consoPickOrderCode = newConsoCode |
|
|
|
this.status = StockOutStatus.PENDING.status |
|
|
|
this.handler = currUser.id |
|
|
|
} |
|
|
|
val savedStockOut = stockOutRepository.saveAndFlush(stockOut) |
|
|
|
|
|
|
|
// Assign and release selected pick order |
|
|
|
val selected = availablePickOrders.first() |
|
|
|
selected.apply { |
|
|
|
this.releasedBy = releasedBy |
|
|
|
status = PickOrderStatus.RELEASED |
|
|
|
this.assignTo = user |
|
|
|
this.consoCode = newConsoCode |
|
|
|
} |
|
|
|
|
|
|
|
val suggestions = suggestedPickLotService.suggestionForPickOrders( |
|
|
|
SuggestedPickLotForPoRequest(pickOrders = listOf(selected)) |
|
|
|
) |
|
|
|
val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList) |
|
|
|
pickOrderRepository.saveAndFlush(selected) |
|
|
|
|
|
|
|
// Hold inventory |
|
|
|
val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn( |
|
|
|
saveSuggestedPickLots.mapNotNull { it.suggestedLotLine?.id } |
|
|
|
) |
|
|
|
saveSuggestedPickLots.forEach { lot -> |
|
|
|
val lotLineId = lot.suggestedLotLine?.id |
|
|
|
if (lotLineId != null) { |
|
|
|
val idx = inventoryLotLines.indexOf(lot.suggestedLotLine) |
|
|
|
if (idx >= 0) { |
|
|
|
val currentHold = inventoryLotLines[idx].holdQty ?: zero |
|
|
|
val addHold = lot.qty ?: zero |
|
|
|
inventoryLotLines[idx].holdQty = currentHold.plus(addHold) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
inventoryLotLineRepository.saveAll(inventoryLotLines) |
|
|
|
|
|
|
|
// Pre-create stock out lines |
|
|
|
var precreated = 0 |
|
|
|
saveSuggestedPickLots.forEach { lot -> |
|
|
|
val polId = lot.pickOrderLine?.id |
|
|
|
val illId = lot.suggestedLotLine?.id |
|
|
|
if (polId != null && illId != null) { |
|
|
|
val existingLines = stockOutLIneRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(polId, illId) |
|
|
|
if (existingLines.isEmpty()) { |
|
|
|
val pickOrderLine = pickOrderLineRepository.findById(polId).orElse(null) |
|
|
|
val inventoryLotLine = inventoryLotLineRepository.findById(illId).orElse(null) |
|
|
|
if (pickOrderLine != null && inventoryLotLine != null) { |
|
|
|
val line = com.ffii.fpsms.modules.stock.entity.StockOutLine().apply { |
|
|
|
this.stockOut = savedStockOut |
|
|
|
this.pickOrderLine = pickOrderLine |
|
|
|
this.inventoryLotLine = inventoryLotLine |
|
|
|
this.item = pickOrderLine.item |
|
|
|
this.status = com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus.PENDING.status |
|
|
|
this.qty = 0.0 |
|
|
|
} |
|
|
|
stockOutLIneRepository.save(line) |
|
|
|
precreated++ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
println("Precreated $precreated stock out lines for store $storeId") |
|
|
|
|
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Pick order assigned and released", |
|
|
|
code = "SUCCESS", |
|
|
|
type = "pickorder", |
|
|
|
message = "Assigned to user $userId for store $storeId", |
|
|
|
errorPosition = null, |
|
|
|
entity = mapOf( |
|
|
|
"consoCode" to newConsoCode, |
|
|
|
"pickOrderIds" to listOf(selected.id!!), |
|
|
|
"storeId" to storeId |
|
|
|
) |
|
|
|
) |
|
|
|
} catch (e: Exception) { |
|
|
|
e.printStackTrace() |
|
|
|
return MessageResponse( |
|
|
|
id = null, name = "Failed to auto-assign by store", code = "ERROR", type = "pickorder", |
|
|
|
message = "Failed to auto-assign by store: ${e.message}", errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
open fun getAllPickOrderLotsWithDetailsWithAutoAssign(userId: Long): List<Map<String, Any>> { |
|
|
|
println("=== Debug: getAllPickOrderLotsWithDetailsWithAutoAssign ===") |
|
|
|
println("today: ${LocalDate.now()}") |
|
|
|
|