From a4ed0f250009167453ca637ce042ef8e0b69f613 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期六, 24 十月 2026 19:30:00 +0800
Subject: [PATCH] feat(aftersales): 增加售后退货流程管理功能

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java |   67 ++++++++++++++++++++++++++-------
 1 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java
index 9bf850d..edc9074 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java
@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.mes.service.wm.returnsales;
 
 import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 
 import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
@@ -9,6 +10,7 @@
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesImportExcelVO;
+import cn.iocoder.yudao.module.mes.api.event.MesReturnSalesProgressEvent;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesImportRespVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesPageReqVO;
 import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.MesWmReturnSalesSaveReqVO;
@@ -27,6 +29,7 @@
 import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
@@ -64,6 +67,8 @@
     private MesMdmItemService mdmItemService;
     @Resource
     private MesWmTransactionService wmTransactionService;
+    @Resource
+    private ApplicationEventPublisher eventPublisher;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -73,6 +78,7 @@
 
         // 2. 鎻掑叆涓昏〃
         MesWmReturnSalesDO returnSales = BeanUtils.toBean(createReqVO, MesWmReturnSalesDO.class);
+        returnSales.setAfterSaleReturnId(createReqVO.getAfterSaleReturnId());
         returnSales.setStatus(MesWmReturnSalesStatusEnum.PREPARE.getStatus());
         returnSalesMapper.insert(returnSales);
         return returnSales.getId();
@@ -82,12 +88,16 @@
     @Transactional(rollbackFor = Exception.class)
     public void updateReturnSales(MesWmReturnSalesSaveReqVO updateReqVO) {
         // 1.1 鏍¢獙瀛樺湪 + 鍑嗗涓姸鎬�
-        validateReturnSalesExistsAndPrepare(updateReqVO.getId());
+        MesWmReturnSalesDO existing = validateReturnSalesExistsAndPrepare(updateReqVO.getId());
+        if (existing.getAfterSaleReturnId() != null) {
+            throw exception(WM_RETURN_SALES_AFTERSALE_LINKED);
+        }
         // 1.2 鏍¢獙鍏宠仈鏁版嵁
         validateSaveData(updateReqVO);
 
         // 2. 鏇存柊涓昏〃
         MesWmReturnSalesDO updateObj = BeanUtils.toBean(updateReqVO, MesWmReturnSalesDO.class);
+        updateObj.setAfterSaleReturnId(null); // 鏉ユ簮鐢宠涓嶅彲閫氳繃缂栬緫鎺ュ彛鏀圭粦
         returnSalesMapper.updateById(updateObj);
     }
 
@@ -95,7 +105,10 @@
     @Transactional(rollbackFor = Exception.class)
     public void deleteReturnSales(Long id) {
         // 1. 鏍¢獙瀛樺湪 + 鍑嗗涓姸鎬�
-        validateReturnSalesExistsAndPrepare(id);
+        MesWmReturnSalesDO returnSales = validateReturnSalesExistsAndPrepare(id);
+        if (returnSales.getAfterSaleReturnId() != null) {
+            throw exception(WM_RETURN_SALES_AFTERSALE_LINKED);
+        }
 
         // 2.1 绾ц仈鍒犻櫎鏄庣粏
         returnSalesDetailService.deleteReturnSalesDetailByReturnId(id);
@@ -133,8 +146,13 @@
         Integer targetStatus = hasPendingQc ? MesWmReturnSalesStatusEnum.CONFIRMED.getStatus()
                 : MesWmReturnSalesStatusEnum.APPROVING.getStatus();
         // 2.2 鎻愪氦锛堣崏绋� -> 寰呮楠�/寰呮墽琛岋級
-        returnSalesMapper.updateById(new MesWmReturnSalesDO()
-                .setId(id).setStatus(targetStatus));
+        if (updateStatusIfCurrent(id, MesWmReturnSalesStatusEnum.PREPARE.getStatus(), targetStatus) != 1) {
+            throw exception(WM_RETURN_SALES_STATUS_NOT_PREPARE);
+        }
+        if (!hasPendingQc && validateReturnSalesExists(id).getAfterSaleReturnId() != null) {
+            eventPublisher.publishEvent(new MesReturnSalesProgressEvent(id,
+                    MesReturnSalesProgressEvent.Stage.QUALITY_FINISHED, "鍏嶆"));
+        }
     }
 
     @Override
@@ -151,8 +169,10 @@
             throw exception(WM_RETURN_SALES_NO_LINE);
         }
         // 2. 鎵ц閫�璐э紙寰呮墽琛� -> 寰呬笂鏋讹級
-        returnSalesMapper.updateById(new MesWmReturnSalesDO()
-                .setId(id).setStatus(MesWmReturnSalesStatusEnum.APPROVED.getStatus()));
+        if (updateStatusIfCurrent(id, MesWmReturnSalesStatusEnum.APPROVING.getStatus(),
+                MesWmReturnSalesStatusEnum.APPROVED.getStatus()) != 1) {
+            throw exception(WM_RETURN_SALES_STATUS_NOT_APPROVING);
+        }
     }
 
     @Override
@@ -184,12 +204,16 @@
             }
         }
 
-        // 2. 閬嶅巻鎵�鏈夋槑缁嗭紝鍒涘缓搴撳瓨浜嬪姟锛堝鍔犲簱瀛� + 璁板綍娴佹按锛�
+        // 鎶㈠崰鐘舵�佸悗鍐嶈搴撳瓨娴佹按锛岄伩鍏嶄袱涓苟鍙戜笂鏋惰姹傞噸澶嶅叆搴擄紱浜嬪姟澶辫触浼氬洖婊氱姸鎬併��
+        if (updateStatusIfCurrent(id, MesWmReturnSalesStatusEnum.APPROVED.getStatus(),
+                MesWmReturnSalesStatusEnum.FINISHED.getStatus()) != 1) {
+            throw exception(WM_RETURN_SALES_STATUS_NOT_APPROVED);
+        }
         createTransactionList(returnSales);
-
-        // 3. 鏇存柊閫�璐у崟鐘舵��
-        returnSalesMapper.updateById(new MesWmReturnSalesDO()
-                .setId(id).setStatus(MesWmReturnSalesStatusEnum.FINISHED.getStatus()));
+        if (returnSales.getAfterSaleReturnId() != null) {
+            eventPublisher.publishEvent(new MesReturnSalesProgressEvent(id,
+                    MesReturnSalesProgressEvent.Stage.INBOUND_FINISHED, null));
+        }
     }
 
     private void createTransactionList(MesWmReturnSalesDO returnSales) {
@@ -216,8 +240,13 @@
         }
 
         // 鍙栨秷
-        returnSalesMapper.updateById(new MesWmReturnSalesDO()
-                .setId(id).setStatus(MesWmReturnSalesStatusEnum.CANCELED.getStatus()));
+        if (updateStatusIfCurrent(id, returnSales.getStatus(), MesWmReturnSalesStatusEnum.CANCELED.getStatus()) != 1) {
+            throw exception(WM_RETURN_SALES_CANCEL_NOT_ALLOWED);
+        }
+        if (returnSales.getAfterSaleReturnId() != null) {
+            eventPublisher.publishEvent(new MesReturnSalesProgressEvent(id,
+                    MesReturnSalesProgressEvent.Stage.CANCELED, null));
+        }
     }
 
     @Override
@@ -257,8 +286,16 @@
 
     @Override
     public void updateReturnSalesStatus(Long id, Integer status) {
-        validateReturnSalesExists(id);
-        returnSalesMapper.updateById(new MesWmReturnSalesDO().setId(id).setStatus(status));
+        if (updateStatusIfCurrent(id, MesWmReturnSalesStatusEnum.CONFIRMED.getStatus(), status) != 1) {
+            throw exception(WM_RETURN_SALES_RQC_SOURCE_INVALID);
+        }
+    }
+
+    private int updateStatusIfCurrent(Long id, Integer currentStatus, Integer targetStatus) {
+        return returnSalesMapper.update(null, new LambdaUpdateWrapper<MesWmReturnSalesDO>()
+                .eq(MesWmReturnSalesDO::getId, id)
+                .eq(MesWmReturnSalesDO::getStatus, currentStatus)
+                .set(MesWmReturnSalesDO::getStatus, targetStatus));
     }
 
     /**

--
Gitblit v1.9.3