瀏覽代碼

update

master
CANCERYS\kw093 1 月之前
父節點
當前提交
ee2ee33189
共有 6 個檔案被更改,包括 1661 行新增1246 行删除
  1. +75
    -45
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt
  2. +3
    -1
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt
  3. +107
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt
  4. +1459
    -1195
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
  5. +5
    -5
      src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt
  6. +12
    -0
      src/main/resources/db/changelog/changes/20251023_01_enson/01_alter_table.sql

+ 75
- 45
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt 查看文件

@@ -18,6 +18,7 @@ import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRepository
import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderRepository
import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRepository
import com.ffii.fpsms.modules.pickOrder.service.PickExecutionIssueService
data class BatchReleaseJobStatus(
val jobId: String,
val total: Int,
@@ -34,7 +35,8 @@ class DoReleaseCoordinatorService(
private val jdbcDao: JdbcDao,
private val doPickOrderLineRepository: DoPickOrderLineRepository,
private val deliveryOrderRepository: DeliveryOrderRepository,
private val doPickOrderRepository: DoPickOrderRepository
private val doPickOrderRepository: DoPickOrderRepository,
private val pickExecutionIssueService: PickExecutionIssueService,
) {
private val poolSize = Runtime.getRuntime().availableProcessors()
private val executor = Executors.newFixedThreadPool(min(poolSize, 4))
@@ -362,28 +364,32 @@ class DoReleaseCoordinatorService(
}
fun startBatchReleaseAsync(ids: List<Long>, userId: Long): MessageResponse {
if (ids.isEmpty()) {
return MessageResponse(id = null, code = "NO_IDS", name = null, type = null,
message = "No IDs provided", errorPosition = null, entity = null)
return MessageResponse(
id = null, code = "NO_IDS", name = null, type = null,
message = "No IDs provided", errorPosition = null, entity = null
)
}
val jobId = UUID.randomUUID().toString()
val status = BatchReleaseJobStatus(jobId = jobId, total = ids.size)
jobs[jobId] = status
executor.submit {
try {
println("📦 Starting batch release for ${ids.size} orders")
val sortedIds = getOrderedDeliveryOrderIds(ids)
println("🔍 DEBUG: Got ${sortedIds.size} sorted orders")
val releaseResults = mutableListOf<ReleaseDoResult>()
// 第一步:发布所有 DO(创建 pick orders,但不创建 DoPickOrder)
// 第一步:发布所有 DO(创建 pick orders,但不创建 DoPickOrder)
sortedIds.forEach { id ->
try {
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(id)
if (deliveryOrder?.status == DeliveryOrderStatus.COMPLETED ||
deliveryOrder?.status == DeliveryOrderStatus.RECEIVING) {
if (deliveryOrder?.status == DeliveryOrderStatus.COMPLETED ||
deliveryOrder?.status == DeliveryOrderStatus.RECEIVING
) {
println("⏭️ DO $id is already ${deliveryOrder.status?.value}, skipping")
return@forEach
}
@@ -398,27 +404,51 @@ class DoReleaseCoordinatorService(
status.failed.add(id to (e.message ?: "Exception"))
}
println("❌ DO $id skipped: ${e.message}")

// ✅ 调用 PickExecutionIssueService 创建 issue 记录
try {
val issueCategory = when {
e.message?.contains("Unable to find") == true &&
e.message?.contains("Warehouse") == true ->
com.ffii.fpsms.modules.pickOrder.entity.IssueCategory.warehouse_issue

e.message?.contains("No matching truck") == true ->
com.ffii.fpsms.modules.pickOrder.entity.IssueCategory.truck_issue

else ->
com.ffii.fpsms.modules.pickOrder.entity.IssueCategory.match_issue
}

pickExecutionIssueService.createBatchReleaseIssue(
deliveryOrderId = id,
errorMessage = e.message ?: "Unknown error",
issueCategory = issueCategory
)
} catch (issueException: Exception) {
println("⚠️ Failed to create issue for DO $id: ${issueException.message}")
}
}
}
// 第二步:按日期、楼层、店铺分组(与 SQL 逻辑一致)
val sortedResults = releaseResults.sortedWith(compareBy(
{ it.estimatedArrivalDate },
{ it.preferredFloor },
{ it.truckDepartureTime },
{ it.truckLanceCode },
{ it.loadingSequence },
{ it.shopId }
))
} // ✅ forEach 循环在这里结束

// ✅ 然后按正确的顺序分组(保持排序后的顺序)
val grouped = sortedResults.groupBy {
Triple(it.estimatedArrivalDate, it.preferredFloor, it.shopId)
}
// ✅ 第二步:按日期、楼层、店铺分组(在 forEach 之后)
val sortedResults = releaseResults.sortedWith(
compareBy(
{ it.estimatedArrivalDate },
{ it.preferredFloor },
{ it.truckDepartureTime },
{ it.truckLanceCode },
{ it.loadingSequence },
{ it.shopId }
)
)

// ✅ 然后按正确的顺序分组(保持排序后的顺序)
val grouped = sortedResults.groupBy {
Triple(it.estimatedArrivalDate, it.preferredFloor, it.shopId)
}

println("🔍 DEBUG: Grouped into ${grouped.size} DoPickOrders")
// 第三步:为每组创建一个 DoPickOrder 和多条 DoPickOrderLine
grouped.forEach { (key, group) ->
try {
@@ -429,31 +459,31 @@ class DoReleaseCoordinatorService(
e.printStackTrace()
}
}
// 第四步:更新 ticket numbers
if (status.success.get() > 0) {
println("🎫 Updating ticket numbers...")
updateBatchTicketNumbers()
}
println("✅ Batch completed: ${status.success.get()} success, ${status.failed.size} failed")
} catch (e: Exception) {
println("❌ Batch release exception: ${e.javaClass.simpleName} - ${e.message}")
e.printStackTrace()
} finally {
status.running = false
status.finishedAt = Instant.now().toEpochMilli()
}
}
return MessageResponse(
id = null, code = "STARTED", name = null, type = null,
message = "Batch release started", errorPosition = null,
entity = mapOf("jobId" to jobId, "total" to ids.size)
)
}
} catch (e: Exception) {
println("❌ Batch release exception: ${e.javaClass.simpleName} - ${e.message}")
e.printStackTrace()
} finally {
status.running = false
status.finishedAt = Instant.now().toEpochMilli()
}
}
return MessageResponse(
id = null, code = "STARTED", name = null, type = null,
message = "Batch release started", errorPosition = null,
entity = mapOf("jobId" to jobId, "total" to ids.size)
)
}
private fun createMergedDoPickOrder(results: List<ReleaseDoResult>) {
val first = results.first()


+ 3
- 1
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt 查看文件

@@ -144,5 +144,7 @@ enum class HandleStatus {
enum class IssueCategory {
lot_issue, // 正常 Issue Button 提交
resuggest_issue, // Resuggest 失败
match_issue // Matching 问题
match_issue ,
warehouse_issue,
truck_issue // Matching 问题
}

+ 107
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt 查看文件

@@ -674,4 +674,111 @@ private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty
println("=== End Debug ===")
return result
}
/**
* 为 batch release 失败的 delivery order 创建 issue 记录
*/
@Transactional(rollbackFor = [Exception::class])
open fun createBatchReleaseIssue(
deliveryOrderId: Long,
errorMessage: String,
issueCategory: IssueCategory = IssueCategory.match_issue
): Int {
try {
println("=== Creating batch release issue ===")
println("Delivery Order ID: $deliveryOrderId")
println("Error Message: $errorMessage")
println("Issue Category: $issueCategory")
// 查询 delivery order
val deliveryOrderSql = """
SELECT do.id, do.code, do.estimatedArrivalDate
FROM fpsmsdb.delivery_order do
WHERE do.id = :deliveryOrderId
AND do.deleted = 0
""".trimIndent()
val deliveryOrder = jdbcDao.queryForMap(
deliveryOrderSql,
mapOf("deliveryOrderId" to deliveryOrderId)
).orElse(null)
if (deliveryOrder == null) {
println("❌ Delivery Order not found: $deliveryOrderId")
return 0
}
// 查询 delivery order lines
val linesSql = """
SELECT dol.id, dol.itemId, i.code as itemCode, i.name as itemName, dol.qty
FROM fpsmsdb.delivery_order_line dol
INNER JOIN fpsmsdb.item i ON i.id = dol.itemId
WHERE dol.doId = :deliveryOrderId
AND dol.deleted = 0
""".trimIndent()
val lines = jdbcDao.queryForList(linesSql, mapOf("deliveryOrderId" to deliveryOrderId))
if (lines.isEmpty()) {
println("⚠️ No delivery order lines found for DO: $deliveryOrderId")
return 0
}
// 生成 issue number
val issueNo = generateIssueNo()
var createdCount = 0
// 为每个 line 创建 issue 记录
lines.forEach { line ->
val itemId = (line["itemId"] as? Number)?.toLong() ?: 0L
val itemCode = line["itemCode"] as? String
val itemName = line["itemName"] as? String
val qty = (line["qty"] as? Number)?.let { BigDecimal(it.toString()) } ?: BigDecimal.ZERO
val issue = PickExecutionIssue(
id = null,
pickOrderId = 0L, // batch release 失败时可能还没有 pick order
pickOrderCode = deliveryOrder["code"] as? String ?: "",
pickOrderCreateDate = LocalDate.now(),
pickExecutionDate = LocalDate.now(),
pickOrderLineId = 0L, // batch release 失败时可能还没有 pick order line
issueNo = issueNo,
joPickOrderId = null,
doPickOrderId = null,
issueCategory = issueCategory,
itemId = itemId,
itemCode = itemCode,
itemDescription = itemName,
lotId = null,
lotNo = null,
storeLocation = null,
requiredQty = qty,
actualPickQty = BigDecimal.ZERO,
missQty = qty,
badItemQty = BigDecimal.ZERO,
issueRemark = "Batch release failed: $errorMessage",
pickerName = null,
handleStatus = HandleStatus.pending,
handleDate = null,
handledBy = null,
created = LocalDateTime.now(),
createdBy = "SYSTEM",
version = 0,
modified = LocalDateTime.now(),
modifiedBy = "SYSTEM",
deleted = false
)
pickExecutionIssueRepository.save(issue)
createdCount++
}
println("✅ Created $createdCount ${issueCategory.name} issues for DO $deliveryOrderId")
return createdCount
} catch (e: Exception) {
println("❌ Failed to create batch release issue: ${e.message}")
e.printStackTrace()
return 0
}
}
}

+ 1459
- 1195
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
文件差異過大導致無法顯示
查看文件


+ 5
- 5
src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt 查看文件

@@ -161,7 +161,10 @@ class PickOrderController(
fun getPickOrderLineLotDetails(@PathVariable pickOrderLineId: Long): List<Map<String, Any>> {
return pickOrderService.getPickOrderLineLotDetails(pickOrderLineId);
}

@GetMapping("/lot-details-by-do-pick-order-record/{doPickOrderRecordId}")
fun getLotDetailsByDoPickOrderRecordId(@PathVariable doPickOrderRecordId: Long): Map<String, Any?> {
return pickOrderService.getLotDetailsByDoPickOrderRecordId(doPickOrderRecordId)
}

@PostMapping("/groups")
fun createGroup(@RequestBody request: Map<String, Any>): ResponseEntity<Map<String, Any>> {
@@ -297,9 +300,6 @@ fun getCompletedDoPickOrders(
): List<Map<String, Any?>> {
return pickOrderService.getCompletedDoPickOrders(userId, pickOrderCode, shopName, deliveryNo, ticketNo)
}
@GetMapping("/lot-details-by-pick-order/{pickOrderId}")
fun getLotDetailsByPickOrderId(@PathVariable pickOrderId: Long): List<Map<String, Any>> {
return pickOrderService.getLotDetailsByPickOrderId(pickOrderId);
}


}

+ 12
- 0
src/main/resources/db/changelog/changes/20251023_01_enson/01_alter_table.sql 查看文件

@@ -0,0 +1,12 @@
-- liquibase formatted sql
-- changeset enson:alter_pick_execution_issue_category_20251023

ALTER TABLE pick_execution_issue
MODIFY COLUMN issue_category ENUM(
'lot_issue',
'resuggest_issue',
'match_issue',
'warehouse_issue',
'truck_issue'
) NOT NULL;


Loading…
取消
儲存