liu
2 天以前 3b4dc22224ba1db1ba7a3ececa36b9c4f67cc15b
feat(aftersales): 售后工单/退货销售订单号必填并反显订单物料

- 工单/退货 SaveReqVO 销售订单字段加必填校验
- 退货 RespVO 新增 saleOrderNo,详情/分页从关联工单拼装反显
- 创建退货强校验工单必须已关联销售订单,订单以工单为准
- 新增错误码 1022002005(工单未关联销售订单)

Co-Authored-By: Claude <noreply@anthropic.com>
已修改6个文件
31 ■■■■ 文件已修改
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/returnobj/AfterSaleReturnController.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/returnobj/vo/AfterSaleReturnRespVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/returnobj/vo/AfterSaleReturnSaveReqVO.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/vo/ticket/AfterSaleTicketSaveReqVO.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/enums/ErrorCodeConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/service/returnobj/AfterSaleReturnServiceImpl.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/returnobj/AfterSaleReturnController.java
@@ -9,7 +9,9 @@
import cn.iocoder.yudao.module.aftersales.controller.admin.returnobj.vo.AfterSaleReturnSaveReqVO;
import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnDO;
import cn.iocoder.yudao.module.aftersales.dal.dataobject.returnobj.AfterSaleReturnItemDO;
import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO;
import cn.iocoder.yudao.module.aftersales.service.returnobj.AfterSaleReturnService;
import cn.iocoder.yudao.module.aftersales.service.ticket.AfterSaleTicketService;
import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
import io.swagger.v3.oas.annotations.Operation;
@@ -24,6 +26,7 @@
import java.util.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -35,6 +38,9 @@
    @Resource
    private AfterSaleReturnService returnService;
    @Resource
    private AfterSaleTicketService ticketService;
    @Resource
    private CrmCustomerApi customerApi;
@@ -85,10 +91,15 @@
        // 批量加载客户名称
        Set<Long> customerIds = convertSet(returnList, AfterSaleReturnDO::getCustomerId);
        Map<Long, CrmCustomerRespDTO> customerMap = customerApi.getCustomerMap(customerIds);
        // 批量加载关联工单的销售订单号(反显订单信息)
        Set<Long> ticketIds = convertSet(returnList, AfterSaleReturnDO::getTicketId);
        Map<Long, AfterSaleTicketDO> ticketMap = convertMap(ticketService.getTicketList(ticketIds), AfterSaleTicketDO::getId);
        // 拼装名称字段
        return BeanUtils.toBean(returnList, AfterSaleReturnRespVO.class, vo -> {
            CrmCustomerRespDTO customer = customerMap.get(vo.getCustomerId());
            if (customer != null) vo.setCustomerName(customer.getName());
            AfterSaleTicketDO ticket = ticketMap.get(vo.getTicketId());
            if (ticket != null) vo.setSaleOrderNo(ticket.getSaleOrderNo());
        });
    }
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/returnobj/vo/AfterSaleReturnRespVO.java
@@ -32,6 +32,9 @@
    @Schema(description = "关联销售订单编号", example = "1")
    private Long saleOrderId;
    @Schema(description = "关联销售订单号", example = "SO202401010001")
    private String saleOrderNo;
    @Schema(description = "退货类型: 1-退款退货 2-换货 3-仅退款", example = "1")
    private Integer returnType;
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/returnobj/vo/AfterSaleReturnSaveReqVO.java
@@ -26,7 +26,8 @@
    @NotNull(message = "客户不能为空")
    private Long customerId;
    @Schema(description = "关联销售订单编号", example = "1")
    @Schema(description = "关联销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    @NotNull(message = "销售订单号不能为空")
    private Long saleOrderId;
    @Schema(description = "退货类型: 1-退款退货 2-换货 3-仅退款", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/vo/ticket/AfterSaleTicketSaveReqVO.java
@@ -29,10 +29,12 @@
    @Schema(description = "联系人编号", example = "1")
    private Long contactId;
    @Schema(description = "销售订单编号", example = "1")
    @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    @NotNull(message = "销售订单号不能为空")
    private Long saleOrderId;
    @Schema(description = "销售订单号", example = "SO202401010001")
    @Schema(description = "销售订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SO202401010001")
    @NotEmpty(message = "销售订单号不能为空")
    private String saleOrderNo;
    @Schema(description = "合同编号", example = "1")
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/enums/ErrorCodeConstants.java
@@ -30,6 +30,7 @@
    ErrorCode RETURN_APPROVE_FAIL = new ErrorCode(1_022_002_002, "审核退货申请失败,原因:不是待审核状态");
    ErrorCode RETURN_ITEM_EMPTY = new ErrorCode(1_022_002_003, "退货明细行不能为空");
    ErrorCode RETURN_DELETE_FAIL_NOT_DRAFT = new ErrorCode(1_022_002_004, "退货申请不是草稿状态,无法删除");
    ErrorCode RETURN_TICKET_SALE_ORDER_REQUIRED = new ErrorCode(1_022_002_005, "创建退货申请失败,原因:售后工单未关联销售订单");
    // ========== 维修记录 1-022-003-000 ==========
    ErrorCode REPAIR_NOT_EXISTS = new ErrorCode(1_022_003_000, "维修记录不存在");
yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/service/returnobj/AfterSaleReturnServiceImpl.java
@@ -62,11 +62,16 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createReturn(AfterSaleReturnSaveReqVO createReqVO, Long userId) {
        // 1. 校验工单存在
        // 1. 校验工单存在,且必须关联销售订单(退货的订单与物料数据由工单反显带入)
        AfterSaleTicketDO ticket = ticketMapper.selectById(createReqVO.getTicketId());
        if (ticket == null) {
            throw exception(TICKET_NOT_EXISTS);
        }
        if (ticket.getSaleOrderId() == null) {
            throw exception(RETURN_TICKET_SALE_ORDER_REQUIRED);
        }
        // 销售订单以工单为准,保证退货单与工单关联同一订单
        createReqVO.setSaleOrderId(ticket.getSaleOrderId());
        // 2. 生成单号
        String no = noRedisDAO.generate(AfterSaleNoRedisDAO.RETURN_NO_PREFIX);