Bladeren bron

update stockin and suggest

reset-do-picking-order
CANCERYS\kw093 5 dagen geleden
bovenliggende
commit
4e3557f239
3 gewijzigde bestanden met toevoegingen van 70 en 23 verwijderingen
  1. +4
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
  2. +45
    -22
      src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt
  3. +21
    -1
      src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt

+ 4
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt Bestand weergeven

@@ -3729,6 +3729,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A
DATE_FORMAT(il.expiryDate, '%Y-%m-%d') as expiryDate,
w.name as location,
COALESCE(uc.udfudesc, 'N/A') as stockUnit,
il.stockInLineId as stockInLineId,
w.`order` as routerIndex,
w.code as routerRoute,
@@ -3770,6 +3771,7 @@ open fun getAllPickOrderLotsWithDetailsHierarchical(userId: Long): Map<String, A
sol_any.inventoryLotLineId as lotId_any,
il_any.lotNo as lotNo_any,
w_any.name as location_any,
il_any.stockInLineId as stockInLineId_any,
-- 仅当有 lot 时可计算,没 lot 时为 NULL
CASE
WHEN ill_any.id IS NULL THEN NULL
@@ -3857,6 +3859,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto
"stockOutLineId" to lotRow["stockOutLineId"],
"stockOutLineStatus" to lotRow["stockOutLineStatus"],
"stockOutLineQty" to lotRow["stockOutLineQty"],
"stockInLineId" to lotRow["stockInLineId"],
"router" to mapOf(
"id" to null,
"index" to lotRow["routerIndex"],
@@ -3890,6 +3893,7 @@ println("DEBUG sol polIds in linesResults: " + linesResults.mapNotNull { it["sto
"lotNo" to (row["lotNo_any"] ?: ""),
"location" to (row["location_any"] ?: ""),
"availableQty" to row["availableQty_any"],
"stockInLineId" to row["stockInLineId_any"],
"noLot" to noLot
)
}


+ 45
- 22
src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt Bestand weergeven

@@ -40,7 +40,7 @@ import com.ffii.fpsms.modules.bag.service.BagService
import com.ffii.fpsms.modules.common.SecurityUtils
import com.ffii.fpsms.modules.stock.entity.StockLedgerRepository
import com.ffii.fpsms.modules.stock.entity.InventoryRepository
import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository
import java.time.LocalTime
@Service
open class StockOutLineService(
@@ -63,7 +63,8 @@ private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository,
private val inventoryLotLineService: InventoryLotLineService,
private val bagService: BagService,
private val stockLedgerRepository: StockLedgerRepository,
private val inventoryRepository: InventoryRepository
private val inventoryRepository: InventoryRepository,
private val pickExecutionIssueRepository: PickExecutionIssueRepository
): AbstractBaseEntityService<StockOutLine, Long, StockOutLIneRepository>(jdbcDao, stockOutLineRepository) {
@Throws(IOException::class)
@Transactional
@@ -347,29 +348,51 @@ private fun getStockOutIdFromPickOrderLine(pickOrderLineId: Long): Long {
allStockOutLines.forEach { sol ->
println(" StockOutLine ${sol.id}: status=${sol.status}, qty=${sol.qty}")
}

// 计算当前行的需求数量
val pickOrderLine = pickOrderLineRepository.findById(pickOrderLineId).orElse(null)
val requiredQty = pickOrderLine?.qty ?: BigDecimal.ZERO

// 1) 计算所有拣货的累计数量(包括 completed / partially_completed / COMPLETE / PARTIALLY_COMPLETE)
val totalPickedQty = allStockOutLines
.filter { sol ->
val solStatus = sol.status?.trim()?.lowercase()
solStatus == "completed" ||
solStatus == "partially_completed" ||
solStatus == StockOutLineStatus.COMPLETE.status.lowercase() ||
solStatus == StockOutLineStatus.PARTIALLY_COMPLETE.status.lowercase()
}
.fold(BigDecimal.ZERO) { acc, sol ->
val qtyValue = sol.qty ?: 0.0
acc + BigDecimal(qtyValue.toString())
}

// 2) 计算该行所有相关 issue 的数量(miss / bad / expiry 等)
val totalIssueQty = try {
val issues = pickExecutionIssueRepository.findByPickOrderLineIdAndDeletedFalse(pickOrderLineId)
issues.fold(BigDecimal.ZERO) { acc, issue ->
acc + (issue.issueQty ?: BigDecimal.ZERO)
}
} catch (e: Exception) {
println("⚠️ Error fetching issues for pickOrderLineId $pickOrderLineId: ${e.message}")
BigDecimal.ZERO
}

println(" totalPickedQty = $totalPickedQty, totalIssueQty = $totalIssueQty, requiredQty = $requiredQty")

val unfinishedLine = allStockOutLines.filter {
val status = it.status?.trim()?.lowercase()
val isComplete = status == StockOutLineStatus.COMPLETE.status.lowercase()
val isRejected = status == StockOutLineStatus.REJECTED.status.lowercase()
val isPartiallyComplete = status == StockOutLineStatus.PARTIALLY_COMPLETE.status.lowercase()
val rawStatus = it.status?.trim()
val status = rawStatus?.lowercase()
// 兼容多种写法:'COMPLETED'、'completed'、枚举值等
val isComplete = status == "completed" || status == StockOutLineStatus.COMPLETE.status.lowercase()
val isRejected = status == "rejected" || status == StockOutLineStatus.REJECTED.status.lowercase()
val isPartiallyComplete =
status == "partially_completed" || status == StockOutLineStatus.PARTIALLY_COMPLETE.status.lowercase()
// Check if partially_completed should be considered as finished
// (if total picked qty meets required qty)
// 如果「拣货数量 + issue 数量」已经覆盖需求,就把 partially_completed 视为已完成
val shouldConsiderPartiallyCompleteAsFinished = if (isPartiallyComplete) {
// ✅ 修复:从 repository 获取 pickOrderLine,避免懒加载问题
val pickOrderLine = pickOrderLineRepository.findById(pickOrderLineId).orElse(null)
if (pickOrderLine != null && pickOrderLine.qty != null) {
val totalPickedQty = allStockOutLines
.filter { sol ->
val solStatus = sol.status?.trim()?.lowercase()
solStatus == "completed" || solStatus == "partially_completed"
}
.fold(BigDecimal.ZERO) { acc, sol ->
val qtyValue = sol.qty ?: 0.0
acc + BigDecimal(qtyValue.toString())
}
totalPickedQty >= pickOrderLine.qty
if (requiredQty > BigDecimal.ZERO) {
(totalPickedQty + totalIssueQty) >= requiredQty
} else {
false
}


+ 21
- 1
src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt Bestand weergeven

@@ -118,7 +118,20 @@ open class SuggestedPickLotService(
val salesUnit = line.item?.id?.let { itemUomService.findSalesUnitByItemId(it) }
val lotLines = availableInventoryLotLines[line.item?.id].orEmpty()
val ratio = one // (salesUnit?.ratioN ?: one).divide(salesUnit?.ratioD ?: one, 10, RoundingMode.HALF_UP)
val pickOrder = line.pickOrder
val isDoPickOrder = pickOrder?.type?.value == "do" || pickOrder?.type?.value == "delivery_order"
val doPreferredFloor: String? = if (isDoPickOrder) {
val supplierCode = pickOrder?.deliveryOrder?.supplier?.code
when (supplierCode) {
"P06B" -> "4F"
"P07", "P06D" -> "2F"
else -> null // 其他供应商不限定 2F/4F
}
} else {
null
}
// FIX: Calculate remaining quantity needed (not the full required quantity)
val stockOutLines = stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(line.id!!)
val totalPickedQty = stockOutLines
@@ -153,6 +166,13 @@ open class SuggestedPickLotService(
if (warehouseStoreId == "3F" && isDeliveryOrderPick) {
return@forEachIndexed
}
if (doPreferredFloor != null &&
warehouseStoreId != "1F" &&
warehouseStoreId != doPreferredFloor
) {
// 例:首选 2F,但是 lot 在 4F -> 跳过
return@forEachIndexed
}
// 修复:计算可用数量,转换为销售单位
val availableQtyInBaseUnits = calculateRemainingQtyForInfo(lotLine)
val holdQtyInBaseUnits = holdQtyMap[lotLine.id] ?: zero


Laden…
Annuleren
Opslaan