소스 검색

update report

master
CANCERYS\kw093 3 일 전
부모
커밋
97e358d02f
5개의 변경된 파일470개의 추가작업 그리고 424개의 파일을 삭제
  1. +439
    -413
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
  2. +8
    -4
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt
  3. +4
    -1
      src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt
  4. +14
    -5
      src/main/java/com/ffii/fpsms/modules/report/service/ReportService.kt
  5. +5
    -1
      src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt

+ 439
- 413
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt 파일 보기

@@ -122,198 +122,118 @@ open class DeliveryOrderService(
truckLanceCode: String?
): RecordsRes<DeliveryOrderInfoLiteDto> {

val page = (pageNum ?: 1) - 1
val size = pageSize ?: 10
val statusEnum = status?.let { s -> DeliveryOrderStatus.entries.find { it.value == s } }
val page = (pageNum ?: 1) - 1
val size = pageSize ?: 10
val statusEnum = status?.let { s -> DeliveryOrderStatus.entries.find { it.value == s } }

val etaStart = estimatedArrivalDate
val etaEnd = estimatedArrivalDate?.plusDays(1)
val etaStart = estimatedArrivalDate
val etaEnd = estimatedArrivalDate?.plusDays(1)

val searchTruckLanceCode = truckLanceCode?.ifBlank { null }?.lowercase()
val searchTruckLanceCode = truckLanceCode?.ifBlank { null }?.lowercase()

if (searchTruckLanceCode != null) {
println("DEBUG: Filtering by truckLanceCode: $searchTruckLanceCode")
// ✅ 优化:先从 truck 表找到匹配的 truck,获取 Store_id 和 shopId
val matchingTrucks = truckRepository.findAllByTruckLanceCodeContainingAndDeletedFalse(searchTruckLanceCode)
println("DEBUG: Found ${matchingTrucks.size} matching trucks")
// 收集所有匹配的 Store_id 和 shopId
val matchingStoreIds = matchingTrucks.mapNotNull { it.storeId }.distinct()
val matchingShopIds = matchingTrucks.mapNotNull { it.shop?.id }.distinct()
println("DEBUG: Matching storeIds: $matchingStoreIds")
println("DEBUG: Matching shopIds: ${matchingShopIds.size} shops")
// 根据 Store_id 确定需要过滤的 supplier codes
// Store_id = "2F" → supplier code != "P06B"
// Store_id = "4F" → supplier code = "P06B"
val supplierCodesToInclude = mutableSetOf<String?>()
val supplierCodesToExclude = mutableSetOf<String?>()
if (matchingStoreIds.contains("2F")) {
supplierCodesToExclude.add("P06B") // 2F 排除 P06B
}
if (matchingStoreIds.contains("4F")) {
supplierCodesToInclude.add("P06B") // 4F 只包含 P06B
}
// 查询符合条件的 DeliveryOrder(根据 supplier code 和 shopId 预过滤)
// 注意:这里需要在 Repository 层面添加 supplier code 过滤
// 或者先查询所有,然后在代码层面过滤
val allResult = deliveryOrderRepository.searchDoLitePage(
code = code?.ifBlank { null },
shopName = shopName?.ifBlank { null },
status = statusEnum,
etaStart = etaStart,
etaEnd = etaEnd,
pageable = PageRequest.of(0, 100000)
)
println("DEBUG: Total records from DB before filtering: ${allResult.totalElements}")
// ✅ 优化1: 批量查询所有 DeliveryOrder 实体
val deliveryOrderIds = allResult.content.mapNotNull { it.id }
val deliveryOrdersMap = deliveryOrderRepository.findAllById(deliveryOrderIds)
.associateBy { it.id }
println("DEBUG: Loaded ${deliveryOrdersMap.size} delivery orders in batch")
// ✅ 优化2: 预过滤 - 根据 supplier code 和 shopId 过滤
val preFilteredContent = allResult.content.filter { info ->
val deliveryOrder = deliveryOrdersMap[info.id]
val supplierCode = deliveryOrder?.supplier?.code
// 检查 supplier code 是否匹配
val supplierMatches = when {
supplierCodesToExclude.contains(supplierCode) -> false // 排除
supplierCodesToInclude.isNotEmpty() && !supplierCodesToInclude.contains(supplierCode) -> false // 只包含特定值
else -> true // 没有限制或匹配
}
// 如果提供了 shopId 过滤,也检查 shopId
val shopMatches = if (matchingShopIds.isNotEmpty()) {
deliveryOrder?.shop?.id in matchingShopIds
} else {
true // 如果没有匹配的 shopId,不过滤
}
supplierMatches && shopMatches
}
println("DEBUG: Pre-filtered records: ${preFilteredContent.size} (from ${allResult.content.size})")
// ✅ 优化3: 收集所有需要查询的 shopId 和日期组合(只处理预过滤后的记录)
val shopIdAndDatePairs = preFilteredContent.mapNotNull { info ->
val deliveryOrder = deliveryOrdersMap[info.id]
val shopId = deliveryOrder?.shop?.id
val estimatedArrivalDate = info.estimatedArrivalDate
if (shopId != null && estimatedArrivalDate != null) {
val targetDate = estimatedArrivalDate.toLocalDate()
val dayAbbr = getDayOfWeekAbbr(targetDate)
val supplierCode = deliveryOrder.supplier?.code
val preferredFloor = if (supplierCode == "P06B") "4F" else "2F"
Triple(shopId, preferredFloor, dayAbbr)
} else {
null
if (searchTruckLanceCode != null) {
println("DEBUG: Filtering by truckLanceCode: $searchTruckLanceCode")

// ✅ 优化:先从 truck 表找到匹配的 truck,获取 Store_id 和 shopId
val matchingTrucks = truckRepository.findAllByTruckLanceCodeContainingAndDeletedFalse(searchTruckLanceCode)
println("DEBUG: Found ${matchingTrucks.size} matching trucks")

// 收集所有匹配的 Store_id 和 shopId
val matchingStoreIds = matchingTrucks.mapNotNull { it.storeId }.distinct()
val matchingShopIds = matchingTrucks.mapNotNull { it.shop?.id }.distinct()

println("DEBUG: Matching storeIds: $matchingStoreIds")
println("DEBUG: Matching shopIds: ${matchingShopIds.size} shops")

// 根据 Store_id 确定需要过滤的 supplier codes
// Store_id = "2F" → supplier code != "P06B"
// Store_id = "4F" → supplier code = "P06B"
val supplierCodesToInclude = mutableSetOf<String?>()
val supplierCodesToExclude = mutableSetOf<String?>()

if (matchingStoreIds.contains("2F")) {
// 2F 只关心 P07 / P06D
supplierCodesToInclude.addAll(listOf("P07", "P06D"))
// 同时排除 P06B,避免混在 2F 结果里
supplierCodesToExclude.add("P06B")
}
}.distinct()
println("DEBUG: Unique shopId/floor/day combinations: ${shopIdAndDatePairs.size}")
// ✅ 优化4: 批量查询所有需要的 Truck
val truckCache = mutableMapOf<Triple<Long, String, String>, Truck?>()
shopIdAndDatePairs.forEach { (shopId, preferredFloor, dayAbbr) ->
val trucks = truckRepository.findByShopIdAndStoreIdAndDayOfWeek(shopId, preferredFloor, dayAbbr)
val matchedTruck = if (trucks.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) }
if (matchingStoreIds.contains("4F")) {
// 4F 只关心 P06B
supplierCodesToInclude.add("P06B")
}
truckCache[Triple(shopId, preferredFloor, dayAbbr)] = matchedTruck
}
println("DEBUG: Cached ${truckCache.size} truck lookups")
// 处理预过滤后的记录:计算 truckLanceCode 并过滤
val processedRecords = preFilteredContent.map { info ->
val deliveryOrder = deliveryOrdersMap[info.id]
val supplierCode = deliveryOrder?.supplier?.code
val preferredFloor = if (supplierCode == "P06B") "4F" else "2F"
val shop = deliveryOrder?.shop
val shopId = shop?.id
val estimatedArrivalDate = info.estimatedArrivalDate
val calculatedTruckLanceCode = if (deliveryOrder != null && shopId != null && estimatedArrivalDate != null) {
val targetDate = estimatedArrivalDate.toLocalDate()
val dayAbbr = getDayOfWeekAbbr(targetDate)
// 从缓存中获取 Truck
val matchedTruck = truckCache[Triple(shopId, preferredFloor, dayAbbr)]
matchedTruck?.truckLanceCode
} else {
null
}
DeliveryOrderInfoLiteDto(
id = info.id,
code = info.code,
orderDate = info.orderDate,
estimatedArrivalDate = info.estimatedArrivalDate,
status = info.status,
shopName = info.shopName,
supplierName = info.supplierName,
shopAddress = info.shopAddress,
truckLanceCode = calculatedTruckLanceCode

// 查询符合条件的 DeliveryOrder(根据 supplier code 和 shopId 预过滤)
// 注意:这里需要在 Repository 层面添加 supplier code 过滤
// 或者先查询所有,然后在代码层面过滤

val allResult = deliveryOrderRepository.searchDoLitePage(
code = code?.ifBlank { null },
shopName = shopName?.ifBlank { null },
status = statusEnum,
etaStart = etaStart,
etaEnd = etaEnd,
pageable = PageRequest.of(0, 100000)
)
}.filter { dto ->
val dtoTruckLanceCode = dto.truckLanceCode?.lowercase() ?: ""
dtoTruckLanceCode.contains(searchTruckLanceCode)
}
// 计算准确的总数(过滤后的总数)
val totalCount = processedRecords.size
println("DEBUG: Final filtered records count: $totalCount")
// 对处理后的记录进行分页
val startIndex = page * size
val endIndex = minOf(startIndex + size, processedRecords.size)
val paginatedRecords = if (startIndex < processedRecords.size) {
processedRecords.subList(startIndex, endIndex)
} else {
emptyList()
}
return RecordsRes(paginatedRecords, totalCount)
} else {
// 如果没有提供 truckLanceCode,使用分页查询
val result = deliveryOrderRepository.searchDoLitePage(
code = code?.ifBlank { null },
shopName = shopName?.ifBlank { null },
status = statusEnum,
etaStart = etaStart,
etaEnd = etaEnd,
pageable = PageRequest.of(page.coerceAtLeast(0), size)
)

// 处理当前页的记录
val records = result.content.map { info ->
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(info.id)
val supplierCode = deliveryOrder?.supplier?.code
val preferredFloor = if (supplierCode == "P06B") "4F" else "2F"
val shop = deliveryOrder?.shop
val shopId = shop?.id
val estimatedArrivalDate = info.estimatedArrivalDate
val calculatedTruckLanceCode = if (deliveryOrder != null && shopId != null && estimatedArrivalDate != null) {
val targetDate = estimatedArrivalDate.toLocalDate()
val dayAbbr = getDayOfWeekAbbr(targetDate)
println("DEBUG: Total records from DB before filtering: ${allResult.totalElements}")

// ✅ 优化1: 批量查询所有 DeliveryOrder 实体
val deliveryOrderIds = allResult.content.mapNotNull { it.id }
val deliveryOrdersMap = deliveryOrderRepository.findAllById(deliveryOrderIds)
.associateBy { it.id }

println("DEBUG: Loaded ${deliveryOrdersMap.size} delivery orders in batch")

// ✅ 优化2: 预过滤 - 根据 supplier code 和 shopId 过滤
val preFilteredContent = allResult.content.filter { info ->
val deliveryOrder = deliveryOrdersMap[info.id]
val supplierCode = deliveryOrder?.supplier?.code

// 检查 supplier code 是否匹配
val supplierMatches = when {
supplierCodesToExclude.contains(supplierCode) -> false
supplierCodesToInclude.isNotEmpty() && !supplierCodesToInclude.contains(supplierCode) -> false
else -> true
}

// 如果提供了 shopId 过滤,也检查 shopId
val shopMatches = if (matchingShopIds.isNotEmpty()) {
deliveryOrder?.shop?.id in matchingShopIds
} else {
true // 如果没有匹配的 shopId,不过滤
}

supplierMatches && shopMatches
}

println("DEBUG: Pre-filtered records: ${preFilteredContent.size} (from ${allResult.content.size})")

// ✅ 优化3: 收集所有需要查询的 shopId 和日期组合(只处理预过滤后的记录)
val shopIdAndDatePairs = preFilteredContent.mapNotNull { info ->
val deliveryOrder = deliveryOrdersMap[info.id]
val shopId = deliveryOrder?.shop?.id
val estimatedArrivalDate = info.estimatedArrivalDate
if (shopId != null && estimatedArrivalDate != null) {
val targetDate = estimatedArrivalDate.toLocalDate()
val dayAbbr = getDayOfWeekAbbr(targetDate)
val supplierCode = deliveryOrder.supplier?.code
val preferredFloor = when (supplierCode) {
"P06B" -> "4F"
"P07", "P06D" -> "2F"
else -> "2F" // 或者改成 null / 其他默认值,看你业务需要
}
Triple(shopId, preferredFloor, dayAbbr)
} else {
null
}
}.distinct()

println("DEBUG: Unique shopId/floor/day combinations: ${shopIdAndDatePairs.size}")

// ✅ 优化4: 批量查询所有需要的 Truck
val truckCache = mutableMapOf<Triple<Long, String, String>, Truck?>()
shopIdAndDatePairs.forEach { (shopId, preferredFloor, dayAbbr) ->
val trucks = truckRepository.findByShopIdAndStoreIdAndDayOfWeek(shopId, preferredFloor, dayAbbr)
val matchedTruck = if (trucks.isEmpty()) {
truckRepository.findByShopIdAndDeletedFalse(shopId)
.filter { it.storeId == preferredFloor }
@@ -321,149 +241,255 @@ open class DeliveryOrderService(
} else {
trucks.minByOrNull { it.departureTime ?: LocalTime.of(23, 59, 59) }
}
matchedTruck?.truckLanceCode
truckCache[Triple(shopId, preferredFloor, dayAbbr)] = matchedTruck
}

println("DEBUG: Cached ${truckCache.size} truck lookups")

// 处理预过滤后的记录:计算 truckLanceCode 并过滤
val processedRecords = preFilteredContent.map { info ->
val deliveryOrder = deliveryOrdersMap[info.id]
val supplierCode = deliveryOrder?.supplier?.code
val preferredFloor = when (supplierCode) {
"P06B" -> "4F"
"P07", "P06D" -> "2F"
else -> null
}
val shop = deliveryOrder?.shop
val shopId = shop?.id
val estimatedArrivalDate = info.estimatedArrivalDate

val calculatedTruckLanceCode =
if (deliveryOrder != null && shopId != null && estimatedArrivalDate != null) {
val targetDate = estimatedArrivalDate.toLocalDate()
val dayAbbr = getDayOfWeekAbbr(targetDate)

// 从缓存中获取 Truck
val matchedTruck = truckCache[Triple(shopId, preferredFloor, dayAbbr)]
matchedTruck?.truckLanceCode
} else {
null
}

DeliveryOrderInfoLiteDto(
id = info.id,
code = info.code,
orderDate = info.orderDate,
estimatedArrivalDate = info.estimatedArrivalDate,
status = info.status,
shopName = info.shopName,
supplierName = info.supplierName,
shopAddress = info.shopAddress,
truckLanceCode = calculatedTruckLanceCode
)
}.filter { dto ->
val dtoTruckLanceCode = dto.truckLanceCode?.lowercase() ?: ""
dtoTruckLanceCode.contains(searchTruckLanceCode)
}

// 计算准确的总数(过滤后的总数)
val totalCount = processedRecords.size
println("DEBUG: Final filtered records count: $totalCount")

// 对处理后的记录进行分页
val startIndex = page * size
val endIndex = minOf(startIndex + size, processedRecords.size)

val paginatedRecords = if (startIndex < processedRecords.size) {
processedRecords.subList(startIndex, endIndex)
} else {
null
emptyList()
}
DeliveryOrderInfoLiteDto(
id = info.id,
code = info.code,
orderDate = info.orderDate,
estimatedArrivalDate = info.estimatedArrivalDate,
status = info.status,
shopName = info.shopName,
supplierName = info.supplierName,
shopAddress = info.shopAddress,
truckLanceCode = calculatedTruckLanceCode
return RecordsRes(paginatedRecords, totalCount)
} else {
// 如果没有提供 truckLanceCode,使用分页查询
val result = deliveryOrderRepository.searchDoLitePage(
code = code?.ifBlank { null },
shopName = shopName?.ifBlank { null },
status = statusEnum,
etaStart = etaStart,
etaEnd = etaEnd,
pageable = PageRequest.of(page.coerceAtLeast(0), size)
)
}

return RecordsRes(records, result.totalElements.toInt())
}
}
val allowedSuppliers = setOf("P06B", "P07", "P06D")

// 处理当前页的记录,只保留这三个 supplier
val records = result.content.mapNotNull { info ->
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(info.id)
val supplierCode = deliveryOrder?.supplier?.code
if (supplierCode !in allowedSuppliers) {
null // 过滤掉其他 supplier
} else {
val preferredFloor = when (supplierCode) {
"P06B" -> "4F"
"P07", "P06D" -> "2F"
else -> "2F"
}
val shop = deliveryOrder?.shop
val shopId = shop?.id
val estimatedArrivalDate = info.estimatedArrivalDate

val calculatedTruckLanceCode =
if (deliveryOrder != null && shopId != null && estimatedArrivalDate != null) {
val targetDate = estimatedArrivalDate.toLocalDate()
val dayAbbr = getDayOfWeekAbbr(targetDate)
val trucks = truckRepository.findByShopIdAndStoreIdAndDayOfWeek(shopId, preferredFloor, dayAbbr)

val matchedTruck = if (trucks.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) }
}

matchedTruck?.truckLanceCode
} else {
null
}

DeliveryOrderInfoLiteDto(
id = info.id,
code = info.code,
orderDate = info.orderDate,
estimatedArrivalDate = info.estimatedArrivalDate,
status = info.status,
shopName = info.shopName,
supplierName = info.supplierName,
shopAddress = info.shopAddress,
truckLanceCode = calculatedTruckLanceCode
)
}
}

// 函数自己的返回
return RecordsRes(records, result.totalElements.toInt())
}

open fun findByM18DataLogId(m18DataLogId: Long): DeliveryOrder? {
return deliveryOrderRepository.findTopByM18DataLogIdOrderByModifiedDesc(m18DataLogId)
}

open fun getDoList(): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findDeliveryOrderInfoByDeletedIsFalse();
}

/*
open fun findByM18DataLogId(m18DataLogId: Long): DeliveryOrder? {
return deliveryOrderRepository.findTopByM18DataLogIdOrderByModifiedDesc(m18DataLogId)
}

open fun getDoList(): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findDeliveryOrderInfoByDeletedIsFalse();
}

/*
open fun getDetailedDo(id: Long) : DeliveryOrder? {
return deliveryOrderRepository.findByIdAndDeletedIsFalse(id);
}
*/
open fun getDetailedDo(id: Long): DoDetailResponse? {
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(id) ?: return null
open fun getDetailedDo(id: Long): DoDetailResponse? {
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(id) ?: return null

return DoDetailResponse(
id = deliveryOrder.id!!,
code = deliveryOrder.code ?: "",
supplierCode = deliveryOrder.supplier?.code,
shopCode = deliveryOrder.shop?.code,
shopName = deliveryOrder.shop?.name,
currencyCode = deliveryOrder.currency?.code,
orderDate = deliveryOrder.orderDate,
estimatedArrivalDate = deliveryOrder.estimatedArrivalDate,
completeDate = deliveryOrder.completeDate,
status = deliveryOrder.status?.value,
deliveryOrderLines = deliveryOrder.deliveryOrderLines.map { line ->
DoDetailLineResponse(
id = line.id!!,
itemNo = line.itemNo,
qty = line.qty,
price = line.price,
status = line.status?.value,
itemName = line.item?.name,
uomCode = line.uom?.code,
uom = line.uom?.udfudesc,
shortUom = line.uom?.udfShortDesc
)
}
)
}

return DoDetailResponse(
id = deliveryOrder.id!!,
code = deliveryOrder.code ?: "",
supplierCode = deliveryOrder.supplier?.code,
shopCode = deliveryOrder.shop?.code,
shopName = deliveryOrder.shop?.name,
currencyCode = deliveryOrder.currency?.code,
orderDate = deliveryOrder.orderDate,
estimatedArrivalDate = deliveryOrder.estimatedArrivalDate,
completeDate = deliveryOrder.completeDate,
status = deliveryOrder.status?.value,
deliveryOrderLines = deliveryOrder.deliveryOrderLines.map { line ->
DoDetailLineResponse(
id = line.id!!,
itemNo = line.itemNo,
qty = line.qty,
price = line.price,
status = line.status?.value,
itemName = line.item?.name,
uomCode = line.uom?.code,
uom = line.uom?.udfudesc,
shortUom = line.uom?.udfShortDesc
)
}
)
}
open fun searchByCode(code: String?): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndDeletedIsFalse(code);
}

open fun searchByCode(code: String?): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndDeletedIsFalse(code);
}
open fun searchByShopName(shopName: String): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByShopNameContainsAndDeletedIsFalse(shopName);
}

open fun searchByShopName(shopName: String): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByShopNameContainsAndDeletedIsFalse(shopName);
}
open fun searchByStatus(status: DeliveryOrderStatus): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByStatusAndDeletedIsFalse(status);
}

open fun searchByStatus(status: DeliveryOrderStatus): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByStatusAndDeletedIsFalse(status);
}
open fun searchBetweenOrderDate(start: LocalDateTime?, end: LocalDateTime?): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findByOrderDateBetweenAndDeletedIsFalse(start, end);
}

open fun searchBetweenOrderDate(start: LocalDateTime?, end: LocalDateTime?): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findByOrderDateBetweenAndDeletedIsFalse(start, end);
}

open fun getFullList(): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllBy();
}

open fun getFullList(): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllBy();
}
open fun searchAll(
code: String?,
shopName: String?,
status: DeliveryOrderStatus?,
orderStartDate: LocalDateTime?,
orderEndDate: LocalDateTime?,
estArrStartDate: LocalDateTime?,
estArrEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndOrderDateBetweenAndEstimatedArrivalDateBetweenAndDeletedIsFalse(
code,
shopName,
status,
orderStartDate,
orderEndDate,
estArrStartDate,
estArrEndDate
);
}

open fun searchAll(
code: String?,
shopName: String?,
status: DeliveryOrderStatus?,
orderStartDate: LocalDateTime?,
orderEndDate: LocalDateTime?,
estArrStartDate: LocalDateTime?,
estArrEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndOrderDateBetweenAndEstimatedArrivalDateBetweenAndDeletedIsFalse(
code,
shopName,
status,
orderStartDate,
orderEndDate,
estArrStartDate,
estArrEndDate
);
}
open fun searchWithoutStatus(
code: String?,
shopName: String?,
orderStartDate: LocalDateTime?,
orderEndDate: LocalDateTime?,
estArrStartDate: LocalDateTime?,
estArrEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndOrderDateBetweenAndEstimatedArrivalDateBetweenAndDeletedIsFalse(
code,
shopName,
orderStartDate,
orderEndDate,
estArrStartDate,
estArrEndDate
);
}

open fun searchWithoutStatus(
code: String?,
shopName: String?,
orderStartDate: LocalDateTime?,
orderEndDate: LocalDateTime?,
estArrStartDate: LocalDateTime?,
estArrEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndOrderDateBetweenAndEstimatedArrivalDateBetweenAndDeletedIsFalse(
code,
shopName,
orderStartDate,
orderEndDate,
estArrStartDate,
estArrEndDate
);
}
open fun searchWithoutEstArrDate(
code: String?,
shopName: String?,
status: DeliveryOrderStatus?,
orderStartDate: LocalDateTime?,
orderEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndOrderDateBetweenAndDeletedIsFalse(
code,
shopName,
status,
orderStartDate,
orderEndDate
);
}

open fun searchWithoutEstArrDate(
code: String?,
shopName: String?,
status: DeliveryOrderStatus?,
orderStartDate: LocalDateTime?,
orderEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndOrderDateBetweenAndDeletedIsFalse(
code,
shopName,
status,
orderStartDate,
orderEndDate
);
}
/*
/*
open fun searchDoForList(
code: String?,
shopName: String?,
@@ -500,73 +526,73 @@ open class DeliveryOrderService(
}
}
*/
open fun searchWithoutEstArrDateAndStatus(
code: String?,
shopName: String?,
orderStartDate: LocalDateTime?,
orderEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndOrderDateBetweenAndDeletedIsFalse(
code,
shopName,
orderStartDate,
orderEndDate
);
}
open fun searchWithoutEstArrDateAndStatus(
code: String?,
shopName: String?,
orderStartDate: LocalDateTime?,
orderEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndOrderDateBetweenAndDeletedIsFalse(
code,
shopName,
orderStartDate,
orderEndDate
);
}

open fun searchWithoutOrderDate(
code: String?,
shopName: String?,
status: DeliveryOrderStatus?,
estArrStartDate: LocalDateTime?,
estArrEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndEstimatedArrivalDateBetweenAndDeletedIsFalse(
code,
shopName,
status,
estArrStartDate,
estArrEndDate
);
}
open fun searchWithoutOrderDate(
code: String?,
shopName: String?,
status: DeliveryOrderStatus?,
estArrStartDate: LocalDateTime?,
estArrEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndEstimatedArrivalDateBetweenAndDeletedIsFalse(
code,
shopName,
status,
estArrStartDate,
estArrEndDate
);
}

open fun searchWithoutOrderDateAndStatus(
code: String?,
shopName: String?,
estArrStartDate: LocalDateTime?,
estArrEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndEstimatedArrivalDateBetweenAndDeletedIsFalse(
code,
shopName,
estArrStartDate,
estArrEndDate
);
}
open fun searchWithoutOrderDateAndStatus(
code: String?,
shopName: String?,
estArrStartDate: LocalDateTime?,
estArrEndDate: LocalDateTime?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndEstimatedArrivalDateBetweenAndDeletedIsFalse(
code,
shopName,
estArrStartDate,
estArrEndDate
);
}

open fun searchWithoutDate(
code: String?,
shopName: String?,
status: DeliveryOrderStatus?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndDeletedIsFalse(
code,
shopName,
status
);
}
open fun searchWithoutDate(
code: String?,
shopName: String?,
status: DeliveryOrderStatus?
): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndStatusAndDeletedIsFalse(
code,
shopName,
status
);
}

open fun searchCodeAndShopName(code: String?, shopName: String?): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndDeletedIsFalse(code, shopName);
}
open fun searchCodeAndShopName(code: String?, shopName: String?): List<DeliveryOrderInfo> {
return deliveryOrderRepository.findAllByCodeContainsAndShopNameContainsAndDeletedIsFalse(code, shopName);
}

open fun getWarehouseOrderByItemId(itemId: Long): Int? {
val inventoryLots = inventoryLotService.findByItemId(itemId)
if (inventoryLots.isNotEmpty()) {
val inventoryLotId = inventoryLots.first().id?.toInt()
return inventoryLotId?.let { lotId ->
// 查询 warehouse 的 order 字段
val sql = """
open fun getWarehouseOrderByItemId(itemId: Long): Int? {
val inventoryLots = inventoryLotService.findByItemId(itemId)
if (inventoryLots.isNotEmpty()) {
val inventoryLotId = inventoryLots.first().id?.toInt()
return inventoryLotId?.let { lotId ->
// 查询 warehouse 的 order 字段
val sql = """
SELECT w.`order` as warehouseOrder
FROM fpsmsdb.inventory_lot_line ill
JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId
@@ -575,47 +601,47 @@ open class DeliveryOrderService(
ORDER BY w.`order` ASC
LIMIT 1
""".trimIndent()
val result = jdbcDao.queryForList(sql, mapOf("lotId" to lotId))
if (result.isNotEmpty()) {
val orderString = result.first()["warehouseOrder"] as? String
// Extract the last 3 digits from format like "2F-001"
orderString?.let { order ->
// Try to extract numeric part after the last "-"
val parts = order.split("-")
if (parts.isNotEmpty()) {
val lastPart = parts.last().trim()
// Take last 3 characters if they are all digits
if (lastPart.length >= 3) {
val lastThreeDigits = lastPart.takeLast(3)
if (lastThreeDigits.all { it.isDigit() }) {
return lastThreeDigits.toIntOrNull()
val result = jdbcDao.queryForList(sql, mapOf("lotId" to lotId))
if (result.isNotEmpty()) {
val orderString = result.first()["warehouseOrder"] as? String
// Extract the last 3 digits from format like "2F-001"
orderString?.let { order ->
// Try to extract numeric part after the last "-"
val parts = order.split("-")
if (parts.isNotEmpty()) {
val lastPart = parts.last().trim()
// Take last 3 characters if they are all digits
if (lastPart.length >= 3) {
val lastThreeDigits = lastPart.takeLast(3)
if (lastThreeDigits.all { it.isDigit() }) {
return lastThreeDigits.toIntOrNull()
}
}
}
// Fallback: try to parse the last part as Int
lastPart.toIntOrNull()
} else {
// Fallback: try to extract any 3-digit sequence from the end
val lastThreeDigits = order.takeLast(3)
if (lastThreeDigits.all { it.isDigit() }) {
lastThreeDigits.toIntOrNull()
// Fallback: try to parse the last part as Int
lastPart.toIntOrNull()
} else {
null
// Fallback: try to extract any 3-digit sequence from the end
val lastThreeDigits = order.takeLast(3)
if (lastThreeDigits.all { it.isDigit() }) {
lastThreeDigits.toIntOrNull()
} else {
null
}
}
}
}
} else null
} else null
}
}
return null
}
return null
}

// 新增方法2:获取 warehouse 的 code 字段(用于显示路由)
open fun getWarehouseCodeByItemId(itemId: Long): String? {
val inventoryLots = inventoryLotService.findByItemId(itemId)
if (inventoryLots.isNotEmpty()) {
val inventoryLotId = inventoryLots.first().id?.toInt()
return inventoryLotId?.let { lotId ->
val sql = """
// 新增方法2:获取 warehouse 的 code 字段(用于显示路由)
open fun getWarehouseCodeByItemId(itemId: Long): String? {
val inventoryLots = inventoryLotService.findByItemId(itemId)
if (inventoryLots.isNotEmpty()) {
val inventoryLotId = inventoryLots.first().id?.toInt()
return inventoryLotId?.let { lotId ->
val sql = """
SELECT w.code as warehouseCode
FROM fpsmsdb.inventory_lot_line ill
JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId
@@ -624,14 +650,14 @@ open class DeliveryOrderService(
ORDER BY w.`order` ASC
LIMIT 1
""".trimIndent()
val result = jdbcDao.queryForList(sql, mapOf("lotId" to lotId))
if (result.isNotEmpty()) {
result.first()["warehouseCode"] as String?
} else null
val result = jdbcDao.queryForList(sql, mapOf("lotId" to lotId))
if (result.isNotEmpty()) {
result.first()["warehouseCode"] as String?
} else null
}
}
return null
}
return null
}

open fun updateDeliveryOrderStatus(request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse {
val deliveryOrder = checkNotNull(
@@ -832,10 +858,10 @@ open class DeliveryOrderService(
// 新逻辑:根据 supplier code 决定楼层
// 如果 supplier code 是 "P06B",使用 4F,否则使用 2F
val supplierCode = deliveryOrder.supplier?.code
val preferredFloor = if (supplierCode == "P06B") {
"4F"
} else {
"2F"
val preferredFloor = when (supplierCode) {
"P06B" -> "4F"
"P07", "P06D" -> "2F"
else -> "2F" // 或者改成 null / 其他默认值,看你业务需要
}

println(" DEBUG: Supplier code: $supplierCode, Preferred floor: $preferredFloor")
@@ -1510,10 +1536,10 @@ open class DeliveryOrderService(
// 如果 supplier code 是 "P06B",使用 4F,否则使用 2F
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val supplierCode = deliveryOrder.supplier?.code
val preferredFloor = if (supplierCode == "P06B") {
"4F"
} else {
"2F"
val preferredFloor = when (supplierCode) {
"P06B" -> "4F"
"P07", "P06D" -> "2F"
else -> "2F" // 或者改成 null / 其他默认值,看你业务需要
}

println(" DEBUG: Floor calculation for DO ${deliveryOrder.id}")


+ 8
- 4
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt 파일 보기

@@ -82,11 +82,13 @@ class DoReleaseCoordinatorService(
do.id AS deliveryOrderId,
CASE
WHEN s.code = 'P06B' THEN '4F'
ELSE '2F'
WHEN s.code = 'P07' OR s.code = 'P06D' THEN '2F'
ELSE NULL
END AS preferred_floor,
CASE
WHEN s.code = 'P06B' THEN 4
ELSE 2
WHEN s.code = 'P07' OR s.code = 'P06D' THEN 2
ELSE NULL
END AS preferred_store_id
FROM fpsmsdb.delivery_order do
LEFT JOIN fpsmsdb.shop s ON s.id = do.supplierId AND s.deleted = 0
@@ -244,11 +246,13 @@ class DoReleaseCoordinatorService(
do.id AS deliveryOrderId,
CASE
WHEN s.code = 'P06B' THEN '4F'
ELSE '2F'
WHEN s.code = 'P07' OR s.code = 'P06D' THEN '2F'
ELSE NULL
END AS preferred_floor,
CASE
WHEN s.code = 'P06B' THEN 4
ELSE 2
WHEN s.code = 'P07' OR s.code = 'P06D' THEN 2
ELSE NULL
END AS preferred_store_id
FROM fpsmsdb.delivery_order do
LEFT JOIN fpsmsdb.shop s ON s.id = do.supplierId AND s.deleted = 0


+ 4
- 1
src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt 파일 보기

@@ -1433,7 +1433,10 @@ open class ProductProcessService(
// 过滤掉已完成上架的 job order
val jobOrder = jobOrderRepository.findById(response.jobOrderId ?: 0L).orElse(null)
val stockInLineStatus = jobOrder?.stockInLines?.firstOrNull()?.status
stockInLineStatus != "completed" && jobOrder?.status != JobOrderStatus.PLANNING
stockInLineStatus != "completed"
&& stockInLineStatus != "escalated"
&& stockInLineStatus != "rejected"
&& jobOrder?.status != JobOrderStatus.PLANNING
}
}



+ 14
- 5
src/main/java/com/ffii/fpsms/modules/report/service/ReportService.kt 파일 보기

@@ -137,11 +137,16 @@ FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty,
WHERE t2.shopId = do.shopId
AND t2.deleted = 0
AND t2.Store_id = CASE
WHEN supplier.code = 'P06B' THEN '4F'
ELSE '2F'
END
WHEN supplier.code = 'P06B' THEN '4F'
WHEN supplier.code IN ('P07', 'P06D') THEN '2F'
ELSE NULL
END
AND (
(CASE WHEN supplier.code = 'P06B' THEN '4F' ELSE '2F' END = '4F'
(CASE
WHEN supplier.code = 'P06B' THEN '4F'
WHEN supplier.code IN ('P07', 'P06D') THEN '2F'
ELSE NULL
END
AND (SELECT COUNT(*) FROM truck t3
WHERE t3.shopId = do.shopId AND t3.deleted = 0
AND t3.Store_id = '4F') > 1
@@ -158,7 +163,11 @@ FORMAT(ROUND(IFNULL(IFNULL(sol.qty, dol.qty), 0), 0), 0) AS qty,
ELSE ''
END, '%'))
OR
t2.Store_id = CASE WHEN supplier.code = 'P06B' THEN '4F' ELSE '2F' END
t2.Store_id = CASE
WHEN supplier.code = 'P06B' THEN '4F'
WHEN supplier.code IN ('P07', 'P06D') THEN '2F'
ELSE NULL
END
)
ORDER BY t2.DepartureTime ASC
LIMIT 1),


+ 5
- 1
src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt 파일 보기

@@ -272,7 +272,11 @@ open class SuggestedPickLotService(
val doPreferredFloor: String? = if (isDoPickOrder) {
val supplierCode = pickOrder?.deliveryOrder?.supplier?.code
if (supplierCode == "P06B") "4F" else "2F"
when (supplierCode) {
"P06B" -> "4F"
"P07", "P06D" -> "2F"
else -> null // 其他供应商不限定 2F/4F
}
} else {
null
}


불러오는 중...
취소
저장