Explorar el Código

dosearch not allow input withour date.

if 4/F truck is not match that day count as truck X
truck x tab have warn mesage
doTruckUpdate
CANCERYS\kw093 hace 4 semanas
padre
commit
a99979d377
Se han modificado 3 ficheros con 38 adiciones y 116 borrados
  1. +35
    -116
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
  2. +1
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt
  3. +2
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/ReleaseDoRequest.kt

+ 35
- 116
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt Ver fichero

@@ -350,9 +350,10 @@ open class DeliveryOrderService(
truckLanceCode: String?,
floor: String? = null,
isExtra: Boolean? = null,
excludeUnassignedTruck: Boolean = false,
): RecordsRes<DeliveryOrderInfoLiteDto> {
val mode = TruckLaneSearchSpec.parse(truckLanceCode)
if (mode is TruckLaneSearchSpec.Mode.NoFilter) {
if (mode is TruckLaneSearchSpec.Mode.NoFilter && !excludeUnassignedTruck) {
return searchDoLiteByPage(
code,
shopName,
@@ -371,7 +372,10 @@ open class DeliveryOrderService(
val etaStart = estimatedArrivalDate
val etaEnd = estimatedArrivalDate?.plusDays(1)

val lanePredicate: (String?) -> Boolean = { lane -> TruckLaneSearchSpec.matches(mode, lane) }
val lanePredicate: (String?) -> Boolean = { lane ->
TruckLaneSearchSpec.matches(mode, lane) &&
(!excludeUnassignedTruck || !TruckLaneSearchSpec.isUnassignedResolvedLane(lane))
}
val matched = scanDoLiteSupplierFilteredWithLanePredicate(
code = code?.ifBlank { null },
shopName = shopName?.ifBlank { null },
@@ -2231,62 +2235,16 @@ val inventoryLotLine = illId?.let { inventoryLotLineMap[it] }
println(" - Preferred floor: $preferredFloor")

val truck = deliveryOrder.shop?.id?.let { shopId ->
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
val preferredStoreId = when (preferredFloor) {
"2F" -> "2F"
"4F" -> "4F"
"3F" -> "3F"
else -> "2F"
}

val matchedTrucks = trucks.filter { it.storeId == preferredStoreId }

if (matchedTrucks.isEmpty()) {
val eta = deliveryOrder.estimatedArrivalDate?.toLocalDate()
if (preferredFloor == "4F" && eta == null) {
null
} else {
if (preferredStoreId == "4F" && matchedTrucks.size > 1) {
deliveryOrder.estimatedArrivalDate?.let { estimatedArrivalDate ->
val targetDate = estimatedArrivalDate.toLocalDate()
val dayOfWeek = targetDate.dayOfWeek

val dayAbbr = when (dayOfWeek) {
java.time.DayOfWeek.MONDAY -> "Mon"
java.time.DayOfWeek.TUESDAY -> "Tue"
java.time.DayOfWeek.WEDNESDAY -> "Wed"
java.time.DayOfWeek.THURSDAY -> "Thu"
java.time.DayOfWeek.FRIDAY -> "Fri"
java.time.DayOfWeek.SATURDAY -> "Sat"
java.time.DayOfWeek.SUNDAY -> "Sun"
}

println(" DEBUG: DO ${deliveryOrder.id} - Target date: $targetDate ($dayAbbr), Shop: $shopId")
println(" DEBUG: Found ${matchedTrucks.size} matched 4F trucks")

val dayMatchedTrucks = matchedTrucks.filter {
it.truckLanceCode?.contains(dayAbbr, ignoreCase = true) == true
}

println(" DEBUG: Found ${dayMatchedTrucks.size} trucks matching $dayAbbr")
dayMatchedTrucks.forEach { t ->
println(" - Truck ID=${t.id}, Code=${t.truckLanceCode}, Time=${t.departureTime}")
}

if (dayMatchedTrucks.isNotEmpty()) {
val selected = dayMatchedTrucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
println("✅ DEBUG: Selected truck matching $dayAbbr - ID=${selected?.id}, Code=${selected?.truckLanceCode}")
selected
} else {
println("⚠️ WARNING: No truck matching $dayAbbr, using first available truck")
matchedTrucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
} ?: run {
matchedTrucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
} else {
matchedTrucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
resolveTruckForShopFloorAndDay(
shopId,
preferredFloor,
getDayOfWeekAbbr(eta ?: LocalDate.now()),
)
}

}
val defaultTruckId = 5577L
val effectiveTruck = truck ?: truckRepository.findById(defaultTruckId).orElse(null)
@@ -2396,46 +2354,15 @@ val inventoryLotLine = illId?.let { inventoryLotLineMap[it] }
val preferredFloor = preferredStoreFloorForSupplier(supplierCode, floorSuppliers2F, floorSuppliers4F)

val truck = deliveryOrder.shop?.id?.let { shopId ->
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
val preferredStoreId = when (preferredFloor) {
"2F" -> "2F"
"4F" -> "4F"
"3F" -> "3F"
else -> "2F"
}

val matchedTrucks = trucks.filter { it.storeId == preferredStoreId }
if (matchedTrucks.isEmpty()) {
val eta = deliveryOrder.estimatedArrivalDate?.toLocalDate()
if (preferredFloor == "4F" && eta == null) {
null
} else {
if (preferredStoreId == "4F" && matchedTrucks.size > 1) {
deliveryOrder.estimatedArrivalDate?.let { estimatedArrivalDate ->
val targetDate2 = estimatedArrivalDate.toLocalDate()
val dayAbbr = when (targetDate2.dayOfWeek) {
java.time.DayOfWeek.MONDAY -> "Mon"
java.time.DayOfWeek.TUESDAY -> "Tue"
java.time.DayOfWeek.WEDNESDAY -> "Wed"
java.time.DayOfWeek.THURSDAY -> "Thu"
java.time.DayOfWeek.FRIDAY -> "Fri"
java.time.DayOfWeek.SATURDAY -> "Sat"
java.time.DayOfWeek.SUNDAY -> "Sun"
}

val dayMatchedTrucks = matchedTrucks.filter {
it.truckLanceCode?.contains(dayAbbr, ignoreCase = true) == true
}

if (dayMatchedTrucks.isNotEmpty()) {
dayMatchedTrucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
} else {
matchedTrucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
} ?: run {
matchedTrucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
} else {
matchedTrucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
resolveTruckForShopFloorAndDay(
shopId,
preferredFloor,
getDayOfWeekAbbr(eta ?: LocalDate.now()),
)
}
}

@@ -2563,7 +2490,7 @@ val inventoryLotLine = illId?.let { inventoryLotLineMap[it] }
/**
* 依店鋪 + 揀貨樓層解析當日應顯示之車線。
* - **2F**(P07/P06D/P06Y):`TruckLanceCode` 多為 `車線-…` 且不含星期縮寫,不依 `LIKE '%Mon%'` 篩選;取該店該樓層未刪除車輛中出發時間最早者。
* - **4F**(P06B):維持以星期縮寫篩選 [TruckRepository.findByShopIdAndStoreIdAndDayOfWeek];無命中時再退回同樓層最早出發。
* - **4F**(P06B):只取車線代碼含當天星期的車。沒有對到當天車時回傳 null,搜尋顯示為車線-X,不退回其他日子的車。
*/
private fun resolveTruckForShopFloorAndDay(
shopId: Long,
@@ -2575,13 +2502,16 @@ val inventoryLotLine = illId?.let { inventoryLotLineMap[it] }
.filter { it.storeId == preferredFloor }
.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
val trucks = truckRepository.findByShopIdAndStoreIdAndDayOfWeek(shopId, preferredFloor, dayAbbr)
return if (trucks.isEmpty()) {
val dayMatched = truckRepository.findByShopIdAndStoreIdAndDayOfWeek(shopId, preferredFloor, dayAbbr)
if (preferredFloor == "4F") {
return dayMatched.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
return if (dayMatched.isEmpty()) {
truckRepository.findByShopIdAndDeletedFalse(shopId)
.filter { it.storeId == preferredFloor }
.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
} else {
trucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
dayMatched.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
}

@@ -2598,31 +2528,20 @@ val inventoryLotLine = illId?.let { inventoryLotLineMap[it] }

open fun check4FTruckAvailabilityForDoList(doIds: List<Long>): Check4FTruckBatchResponse {
val problems = mutableListOf<ProblemDoDto>()
val (floorSuppliers2F, floorSuppliers4F) = loadDoFloorSupplierLists()

doIds.forEach { doId ->
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(doId) ?: return@forEach
val shopId = deliveryOrder.shop?.id ?: return@forEach
val eta = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: return@forEach

// 1) Check if this DO is a 4F order (your “all items on 4F, no 2F” rule)
val sql = """
SELECT
COUNT(DISTINCT CASE WHEN i.store_id = '4F' THEN dol.itemId END) AS count_4f,
COUNT(DISTINCT CASE WHEN i.store_id = '2F' THEN dol.itemId END) AS count_2f,
COUNT(DISTINCT dol.itemId) AS total_items
FROM fpsmsdb.delivery_order_line dol
INNER JOIN fpsmsdb.items i ON i.id = dol.itemId AND i.deleted = 0
WHERE dol.deliveryOrderId = :doId AND dol.deleted = 0
""".trimIndent()

val res = jdbcDao.queryForList(sql, mapOf("doId" to doId)).firstOrNull() ?: return@forEach
val count4F = (res["count_4f"] as? Number)?.toInt() ?: 0
val count2F = (res["count_2f"] as? Number)?.toInt() ?: 0
val totalItems = (res["total_items"] as? Number)?.toInt() ?: 0

val is4FOrder = (totalItems > 0 && count4F == totalItems && count2F == 0)
if (!is4FOrder) {
// Not a 4F order → no problem, skip
// Same floor rule as release: supplier code (P06B → 4F), not item store_id.
val preferredFloor = preferredStoreFloorForSupplier(
deliveryOrder.supplier?.code,
floorSuppliers2F,
floorSuppliers4F,
)
if (preferredFloor != "4F") {
return@forEach
}



+ 1
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DeliveryOrderController.kt Ver fichero

@@ -113,6 +113,7 @@ class DeliveryOrderController(
truckLanceCode = request.truckLanceCode,
floor = request.floor,
isExtra = request.isExtra,
excludeUnassignedTruck = request.excludeUnassignedTruck == true,
)
}



+ 2
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/ReleaseDoRequest.kt Ver fichero

@@ -36,4 +36,6 @@ data class SearchDeliveryOrderInfoRequest(
val floor: String? = null,
/** null:不篩 isExtra;true/false:只顯示加單或非加單 DO */
val isExtra: Boolean? = null,
/** true:排除推算車線為空白或「車線-X」的送貨單(2/F、4/F 分頁)。 */
val excludeUnassignedTruck: Boolean? = null,
)

Cargando…
Cancelar
Guardar