From e11f32dd9ab0d51ecae21c327ddef0903344dde6 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Fri, 10 Oct 2025 16:34:59 +0800 Subject: [PATCH] update --- .../jobOrder/service/JoPickOrderService.kt | 132 +++++++++++++---- .../jobOrder/web/JobOrderController.kt | 36 +++-- .../web/model/SecondScanIssueRequest.kt | 7 +- .../pickOrder/entity/PickExecutionIssue.kt | 16 +- .../entity/PickExecutionIssueRepository.kt | 12 +- .../service/PickExecutionIssueService.kt | 27 ++++ .../pickOrder/service/PickOrderService.kt | 137 +++++++++++------- .../web/models/PickExecutionIssueRequest.kt | 2 + .../20251009_02_enson/02_altertable_enson.sql | 15 ++ 9 files changed, 280 insertions(+), 104 deletions(-) create mode 100644 src/main/resources/db/changelog/changes/20251009_02_enson/02_altertable_enson.sql diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt index fd23b04..aad660f 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt @@ -1032,73 +1032,125 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse ) } - // ✅ Get pick order line details with item information - val pickOrderLineResults = jdbcDao.queryForList( + // ✅ Get pick order and pick order line details with item and lot information + val pickOrderDetails = jdbcDao.queryForList( """ SELECT + po.code as pickOrderCode, + DATE_FORMAT(po.created, '%Y-%m-%d') as pickOrderCreateDate, pol.id as pickOrderLineId, i.code as itemCode, i.name as itemName, - pol.qty as requiredQty - FROM fpsmsdb.pick_order_line pol + pol.qty as requiredQty, + u.name as pickerName + FROM fpsmsdb.pick_order po + JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id JOIN fpsmsdb.items i ON i.id = pol.itemId - WHERE pol.poId = :pickOrderId AND pol.itemId = :itemId AND pol.deleted = false + LEFT JOIN fpsmsdb.user u ON u.id = :createdBy + WHERE po.id = :pickOrderId + AND pol.itemId = :itemId + AND pol.deleted = false + AND po.deleted = false """, mapOf( "pickOrderId" to request.pickOrderId, - "itemId" to request.itemId + "itemId" to request.itemId, + "createdBy" to request.createdBy ) ) - if (pickOrderLineResults.isEmpty()) { + // ✅ 修复:使用正确的变量名 pickOrderDetails + if (pickOrderDetails.isEmpty()) { return MessageResponse( id = null, name = null, code = "ERROR", type = "NOT_FOUND", - message = "Pick order line not found for pickOrderId: ${request.pickOrderId}, itemId: ${request.itemId}", + message = "Pick order not found for pickOrderId: ${request.pickOrderId}, itemId: ${request.itemId}", errorPosition = null ) } - val lineData = pickOrderLineResults.first() - val pickOrderLineId = (lineData["pickOrderLineId"] as Number).toLong() - val itemCode = lineData["itemCode"] as String? - val itemName = lineData["itemName"] as String? - val requiredQty = lineData["requiredQty"]?.let { + // ✅ 修复:使用正确的变量名 pickOrderDetails + val orderData = pickOrderDetails.first() + val pickOrderCode = orderData["pickOrderCode"] as String? + val pickOrderCreateDate = orderData["pickOrderCreateDate"]?.let { + LocalDate.parse(it.toString()) + } + val pickOrderLineId = (orderData["pickOrderLineId"] as Number).toLong() + val itemCode = orderData["itemCode"] as String? + val itemName = orderData["itemName"] as String? + val pickerName = orderData["pickerName"] as String? + val requiredQty = orderData["requiredQty"]?.let { BigDecimal(it.toString()) } + // ✅ 获取 suggested lot 信息(用于 lot_id, lot_no, store_location) + val lotResults = jdbcDao.queryForList( + """ + SELECT + ill.id as lotId, + il.lotNo as lotNo, + w.name as storeLocation + FROM fpsmsdb.suggested_pick_lot spl + JOIN fpsmsdb.inventory_lot_line ill ON spl.suggestedLotLineId = ill.id + JOIN fpsmsdb.inventory_lot il ON ill.inventoryLotId = il.id + LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId + WHERE spl.pickOrderLineId = :pickOrderLineId + AND spl.deleted = false + AND ill.deleted = false + LIMIT 1 + """, + mapOf("pickOrderLineId" to pickOrderLineId) + ) + + val lotId = if (lotResults.isNotEmpty()) { + (lotResults.first()["lotId"] as Number?)?.toLong() + } else null + + val lotNo = if (lotResults.isNotEmpty()) { + lotResults.first()["lotNo"] as String? + } else null + + val storeLocation = if (lotResults.isNotEmpty()) { + lotResults.first()["storeLocation"] as String? + } else null val joPickOrderEntity = joPickOrder.get() joPickOrderEntity.matchStatus = JoPickOrderStatus.completed joPickOrderEntity.matchQty = request.qty.toInt() - // ✅ 添加:如果 ticketCompleteTime 还没设置,现在设置 if (joPickOrderEntity.ticketCompleteTime == null) { joPickOrderEntity.ticketCompleteTime = LocalDateTime.now() } joPickOrderRepository.save(joPickOrderEntity) + // ✅ 生成 issueNo + val issueNo = generateIssueNoForJo() + // ✅ Create pick execution issue with complete data val pickExecutionIssue = PickExecutionIssue( + issueNo = issueNo, + type = request.type ?: "match", pickOrderId = request.pickOrderId, - pickOrderCode = "JO-${request.pickOrderId}", + pickOrderCode = pickOrderCode ?: "P-${request.pickOrderId}", + pickOrderCreateDate = pickOrderCreateDate, // ✅ 现在已经定义了 + pickExecutionDate = LocalDate.now(), pickOrderLineId = pickOrderLineId, itemId = request.itemId, - itemCode = itemCode, // ✅ Include item code - itemDescription = itemName, // ✅ Include item name - lotId = null, - lotNo = null, - storeLocation = null, - requiredQty = requiredQty, // ✅ Include required quantity - actualPickQty = request.qty.toBigDecimal(), // ✅ Include actual pick quantity - missQty = if (request.isMissing) request.qty.toBigDecimal() else BigDecimal.ZERO, - badItemQty = if (request.isBad) request.qty.toBigDecimal() else BigDecimal.ZERO, + itemCode = itemCode, + itemDescription = itemName, + lotId = lotId, + lotNo = lotNo, + storeLocation = storeLocation, + requiredQty = requiredQty, + actualPickQty = request.qty.toBigDecimal(), + missQty = request.missQty.toBigDecimal(), // ✅ 使用实际的 missQty + badItemQty = request.badItemQty.toBigDecimal(), // ✅ 使用实际的 badItemQty issueRemark = request.reason, - pickerName = null, - handleStatus = HandleStatus.jopending, + pickerName = pickerName, + handleStatus = HandleStatus.pending, handleDate = null, handledBy = null, created = LocalDateTime.now(), @@ -1118,19 +1170,41 @@ open fun recordSecondScanIssue(request: SecondScanIssueRequest): MessageResponse message = "Second scan issue recorded successfully", errorPosition = null ) - } catch (e: Exception) { - println("❌ Error recording second scan issue: ${e.message}") + println("=== ERROR in recordSecondScanIssue ===") + e.printStackTrace() return MessageResponse( id = null, name = null, code = "ERROR", type = "EXCEPTION", - message = "Error recording second scan issue: ${e.message}", + message = "Error: ${e.message}", errorPosition = null ) } } +private fun generateIssueNoForJo(): String { + val now = LocalDateTime.now() + val yearMonth = now.format(java.time.format.DateTimeFormatter.ofPattern("yyMM")) + + // 查询当月最新的 issueNo + val latestIssueNo = pickExecutionIssueRepository.findLatestIssueNoByYearMonth(yearMonth) + + // 计算下一个序列号 + val nextSequence = if (latestIssueNo != null) { + val parts = latestIssueNo.split("-") + if (parts.size == 3) { + val currentSequence = parts[2].toIntOrNull() ?: 0 + currentSequence + 1 + } else { + 1 + } + } else { + 1 + } + + return "SKO-${yearMonth}-${nextSequence.toString().padStart(3, '0')}" +} open fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(userId: Long): List> { println("=== getCompletedJobOrderPickOrdersWithCompletedSecondScan ===") println("userId: $userId") diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt index a3e3757..18f0b2a 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt @@ -144,22 +144,26 @@ class JobOrderController( } @PostMapping("/second-scan-issue/{pickOrderId}/{itemId}") - fun recordSecondScanIssue( - @PathVariable pickOrderId: Long, - @PathVariable itemId: Long, - @RequestBody data: Map - ): MessageResponse { - val request = SecondScanIssueRequest( - pickOrderId = pickOrderId, // ✅ Use path variable - itemId = itemId, // ✅ Use path variable - qty = (data["qty"] as Number).toDouble(), - isMissing = data["isMissing"] as Boolean, - isBad = data["isBad"] as Boolean, - reason = data["reason"] as String, - createdBy = (data["createdBy"] as Number).toLong() - ) - return joPickOrderService.recordSecondScanIssue(request) - } +fun recordSecondScanIssue( + @PathVariable pickOrderId: Long, + @PathVariable itemId: Long, + @RequestBody data: Map +): MessageResponse { + val request = SecondScanIssueRequest( + pickOrderId = pickOrderId, // ✅ path 变量 + itemId = itemId, // ✅ path 变量 + qty = (data["qty"] as Number).toDouble(), + // ✅ 新增:安全读取 missQty/badItemQty/type,默认 0/"match" + missQty = (data["missQty"] as? Number)?.toDouble() ?: 0.0, + badItemQty = (data["badItemQty"] as? Number)?.toDouble() ?: 0.0, + isMissing = data["isMissing"] as? Boolean ?: false, + isBad = data["isBad"] as? Boolean ?: false, + reason = data["reason"] as? String ?: "", + createdBy = (data["createdBy"] as Number).toLong(), + type = (data["type"] as? String) ?: "match" + ) + return joPickOrderService.recordSecondScanIssue(request) +} @GetMapping("/completed-job-order-pick-orders-with-completed-second-scan/{userId}") fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(@PathVariable userId: Long): List> { return joPickOrderService.getCompletedJobOrderPickOrdersWithCompletedSecondScan(userId) diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanIssueRequest.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanIssueRequest.kt index 08159f5..936bd5d 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanIssueRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/SecondScanIssueRequest.kt @@ -3,9 +3,12 @@ package com.ffii.fpsms.modules.jobOrder.web.model data class SecondScanIssueRequest( val pickOrderId: Long, val itemId: Long, - val qty: Double, + val qty: Double, // 这是 actual pick qty (verified qty) + val missQty: Double = 0.0, // ✅ 添加:单独的 miss qty + val badItemQty: Double = 0.0, // ✅ 添加:单独的 bad item qty val isMissing: Boolean, val isBad: Boolean, val reason: String, - val createdBy: Long + val createdBy: Long, + val type: String? = "match" ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt index e06ca81..a71b4f4 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssue.kt @@ -27,7 +27,12 @@ class PickExecutionIssue( @Column(name = "pick_order_line_id", nullable = false) val pickOrderLineId: Long, + @Column(name = "issue_no", length = 50) + val issueNo: String? = null, + // ✅ 新增字段:type + @Column(name = "type", length = 50) + val type: String? = null, @Column(name = "item_id", nullable = false) val itemId: Long, @@ -104,6 +109,8 @@ class PickExecutionIssue( itemCode = null, itemDescription = null, lotId = null, + issueNo = null, + type = null, lotNo = null, storeLocation = null, requiredQty = null, @@ -125,10 +132,7 @@ class PickExecutionIssue( } enum class HandleStatus { - pending, // ✅ Change to lowercase to match database - handled, // ✅ Change to lowercase to match database - resolved, - jopending, - johandled, - joresolved // ✅ Change to lowercase to match database + pending, + sort_and_repair, + dispose } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssueRepository.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssueRepository.kt index 3d53c19..69840c1 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssueRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickExecutionIssueRepository.kt @@ -3,7 +3,8 @@ package com.ffii.fpsms.modules.pickOrder.entity import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository - +import org.springframework.data.jpa.repository.Query +import org.springframework.data.repository.query.Param @Repository interface PickExecutionIssueRepository : JpaRepository { fun findByPickOrderIdAndDeletedFalse(pickOrderId: Long): List @@ -13,4 +14,13 @@ interface PickExecutionIssueRepository : JpaRepository pickOrderLineId: Long, lotId: Long ): List + @Query(""" + SELECT p.issueNo + FROM PickExecutionIssue p + WHERE p.issueNo LIKE CONCAT('SKO-', :yearMonth, '-%') + AND p.deleted = false + ORDER BY p.issueNo DESC + LIMIT 1 +""") +fun findLatestIssueNoByYearMonth(@Param("yearMonth") yearMonth: String): String? } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt index 7598619..85ecaf6 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt @@ -50,6 +50,8 @@ open class PickExecutionIssueService( // 2. 创建 pick execution issue 记录 val pickExecutionIssue = PickExecutionIssue( + issueNo = generateIssueNo(), + type = request.type, pickOrderId = request.pickOrderId, pickOrderCode = request.pickOrderCode, pickOrderCreateDate = request.pickOrderCreateDate, @@ -146,6 +148,31 @@ open class PickExecutionIssueService( ) } } + private fun generateIssueNo(): String { + val now = LocalDateTime.now() + val yearMonth = now.format(java.time.format.DateTimeFormatter.ofPattern("yyMM")) + + // 查询当月最新的 issueNo + val latestIssueNo = pickExecutionIssueRepository.findLatestIssueNoByYearMonth(yearMonth) + + // 计算下一个序列号 + val nextSequence = if (latestIssueNo != null) { + // 从最新的 issueNo 中提取序列号 + // 例如: SKO-2510-001 -> 001 + val parts = latestIssueNo.split("-") + if (parts.size == 3) { + val currentSequence = parts[2].toIntOrNull() ?: 0 + currentSequence + 1 + } else { + 1 + } + } else { + 1 + } + + // 格式化为 SKO-YYMM-001 + return "SKO-${yearMonth}-${nextSequence.toString().padStart(3, '0')}" + } // FPSMS-backend/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt // ✅ 修复:处理有部分拣货但有 miss item 的情况 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class]) diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt index 2b91dd8..da0c4ee 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt @@ -1843,57 +1843,93 @@ open fun autoAssignAndReleasePickOrderByStoreAndTicket(storeId: String, ticketNo val pickOrderIdsStr = pickOrderIds.joinToString(",") val sql = """ - SELECT - -- Pick Order Information - po.id as pickOrderId, - po.code as pickOrderCode, - po.consoCode as pickOrderConsoCode, -- ✅ 添加 consoCode - po.targetDate as pickOrderTargetDate, - po.type as pickOrderType, - po.status as pickOrderStatus, - po.assignTo as pickOrderAssignTo, - - -- Pick Order Line Information - pol.id as pickOrderLineId, - pol.qty as pickOrderLineRequiredQty, - - -- Item Information - i.id as itemId, - i.code as itemCode, - i.name as itemName, - uc.code as uomCode, - uc.udfudesc as uomDesc, - - -- ✅ Calculate total picked quantity from stock_out_line table - COALESCE(( - SELECT SUM(sol_picked.qty) - FROM fpsmsdb.stock_out_line sol_picked - WHERE sol_picked.pickOrderLineId = pol.id - AND sol_picked.deleted = false - AND sol_picked.status IN ('completed', 'COMPLETE', 'partially_completed','rejected') - ), 0) as totalPickedQty, - - -- ✅ Calculate available quantity from inventory - COALESCE(( - SELECT inv.onHandQty - inv.onHoldQty - inv.unavailableQty - FROM fpsmsdb.inventory inv - WHERE inv.itemId = i.id - AND inv.deleted = false - ), 0) as availableQty - - FROM fpsmsdb.pick_order po - JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id - JOIN fpsmsdb.items i ON i.id = pol.itemId - LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = pol.uomId - WHERE po.deleted = false - AND po.id IN ($pickOrderIdsStr) - AND pol.deleted = false - AND po.status = 'RELEASED' + SELECT + -- Pick Order Information + po.id as pickOrderId, + po.code as pickOrderCode, + po.consoCode as pickOrderConsoCode, + po.targetDate as pickOrderTargetDate, + po.type as pickOrderType, + po.status as pickOrderStatus, + po.assignTo as pickOrderAssignTo, - ORDER BY - po.code ASC, - i.code ASC - """.trimIndent() + -- Pick Order Line Information + pol.id as pickOrderLineId, + pol.qty as pickOrderLineRequiredQty, + pol.status as pickOrderLineStatus, + + -- Item Information + i.id as itemId, + i.code as itemCode, + i.name as itemName, + uc.code as uomCode, + uc.udfudesc as uomDesc, + + -- ✅ Calculate total picked quantity from stock_out_line table + COALESCE(( + SELECT SUM(sol_picked.qty) + FROM fpsmsdb.stock_out_line sol_picked + WHERE sol_picked.pickOrderLineId = pol.id + AND sol_picked.deleted = false + AND sol_picked.status IN ('completed', 'COMPLETE', 'partially_completed','rejected') + ), 0) as totalPickedQty, + + -- ✅ Calculate available quantity from inventory + COALESCE(( + SELECT inv.onHandQty - inv.onHoldQty - inv.unavailableQty + FROM fpsmsdb.inventory inv + WHERE inv.itemId = i.id + AND inv.deleted = false + ), 0) as availableQty, + + -- ✅ Check if all stock out lines for this pick order line are completed + CASE + WHEN EXISTS ( + SELECT 1 + FROM fpsmsdb.stock_out_line sol_check + WHERE sol_check.pickOrderLineId = pol.id + AND sol_check.deleted = false + AND sol_check.status NOT IN ('completed', 'COMPLETE') + ) THEN false + WHEN EXISTS ( + SELECT 1 + FROM fpsmsdb.stock_out_line sol_check + WHERE sol_check.pickOrderLineId = pol.id + AND sol_check.deleted = false + ) THEN true + ELSE false + END as allLotsCompleted + + FROM fpsmsdb.pick_order po + JOIN fpsmsdb.pick_order_line pol ON pol.poId = po.id + JOIN fpsmsdb.items i ON i.id = pol.itemId + LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = pol.uomId + WHERE po.deleted = false + AND po.id IN ($pickOrderIdsStr) + AND pol.deleted = false + AND po.status = 'RELEASED' + AND po.type NOT IN ('do', 'job') -- ✅ 排除 do 和 job 类型 + -- ✅ Only include lines that have incomplete stock out lines + AND ( + NOT EXISTS ( + SELECT 1 + FROM fpsmsdb.stock_out_line sol_all_complete + WHERE sol_all_complete.pickOrderLineId = pol.id + AND sol_all_complete.deleted = false + ) + OR EXISTS ( + SELECT 1 + FROM fpsmsdb.stock_out_line sol_incomplete + WHERE sol_incomplete.pickOrderLineId = pol.id + AND sol_incomplete.deleted = false + AND sol_incomplete.status NOT IN ('completed', 'COMPLETE') + ) + ) + + ORDER BY + po.code ASC, + i.code ASC + """.trimIndent() println("🔍 Executing optimized SQL: $sql") @@ -1966,6 +2002,7 @@ open fun autoAssignAndReleasePickOrderByStoreAndTicket(storeId: String, ticketNo val releasedPickOrderIds = allPickOrders .filter { it.status == PickOrderStatus.RELEASED } .filter { it.assignTo?.id == userId } + .filter { it.type?.value != "do" && it.type?.value != "jo" } // ✅ 排除 do 和 job 类型 .map { it.id!! } if (releasedPickOrderIds.isEmpty()) { diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/PickExecutionIssueRequest.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/PickExecutionIssueRequest.kt index 24dc673..c5927ff 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/PickExecutionIssueRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/PickExecutionIssueRequest.kt @@ -15,6 +15,8 @@ data class PickExecutionIssueRequest( val itemDescription: String? = null, val lotId: Long? = null, val lotNo: String? = null, + val issueNo: String? = null, + val type: String? = null, val storeLocation: String? = null, val requiredQty: BigDecimal? = null, val actualPickQty: BigDecimal? = null, diff --git a/src/main/resources/db/changelog/changes/20251009_02_enson/02_altertable_enson.sql b/src/main/resources/db/changelog/changes/20251009_02_enson/02_altertable_enson.sql new file mode 100644 index 0000000..22f775b --- /dev/null +++ b/src/main/resources/db/changelog/changes/20251009_02_enson/02_altertable_enson.sql @@ -0,0 +1,15 @@ +--liquibase formatted sql + +--changeset [enson]:update_pick_execution_issue_add_columns_and_modify_status + +-- 1. 添加新列 issueNo +ALTER TABLE pick_execution_issue +ADD COLUMN issue_no VARCHAR(50) NULL AFTER id; + +-- 2. 添加新列 Type +ALTER TABLE pick_execution_issue +ADD COLUMN type VARCHAR(50) NULL AFTER issue_no; + +-- 3. 修改 handle_status 枚举值 +ALTER TABLE pick_execution_issue +MODIFY COLUMN handle_status ENUM('pending', 'Sort and Repair', 'Dispose') NULL DEFAULT 'pending'; \ No newline at end of file