yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/service/ticket/AfterSaleTicketServiceImpl.java
@@ -15,6 +15,7 @@
import cn.iocoder.yudao.module.aftersales.enums.permission.AfterSalePermissionLevelEnum;
import cn.iocoder.yudao.module.aftersales.service.permission.AfterSalePermissionService;
import cn.iocoder.yudao.module.aftersales.service.permission.bo.AfterSalePermissionCreateReqBO;
import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -47,6 +48,9 @@
    @Resource
    private AfterSalePermissionService permissionService;
    @Resource
    private StorageAttachmentApi storageAttachmentApi;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createTicket(AfterSaleTicketSaveReqVO createReqVO, Long userId) {
@@ -63,16 +67,21 @@
                .setOwnerUserId(userId);
        ticketMapper.insert(ticket);
        // 3. 插入明细行
        // 3. 插入明细行(每条生成独立售后单号:工单号-序号)
        if (CollUtil.isNotEmpty(createReqVO.getItems())) {
            createReqVO.getItems().forEach(item -> {
                AfterSaleTicketItemDO itemDO = BeanUtils.toBean(item, AfterSaleTicketItemDO.class);
            for (int i = 0; i < createReqVO.getItems().size(); i++) {
                AfterSaleTicketItemDO itemDO = BeanUtils.toBean(createReqVO.getItems().get(i), AfterSaleTicketItemDO.class);
                itemDO.setTicketId(ticket.getId());
                itemDO.setItemNo(buildItemNo(no, i + 1));
                ticketItemMapper.insert(itemDO);
            });
            }
        }
        // 4. 创建数据权限(负责人)
        // 4. 绑定附件
        storageAttachmentApi.bindAttachments("file", "aftersales_after_sale_ticket",
                ticket.getId(), createReqVO.getBlobIds());
        // 5. 创建数据权限(负责人)
        AfterSalePermissionCreateReqBO permBO = new AfterSalePermissionCreateReqBO();
        permBO.setBizType(AfterSaleBizTypeEnum.AFTER_SALE_TICKET.getType());
        permBO.setBizId(ticket.getId());
@@ -94,15 +103,19 @@
        AfterSaleTicketDO updateObj = BeanUtils.toBean(updateReqVO, AfterSaleTicketDO.class);
        ticketMapper.updateById(updateObj);
        // 3. 更新明细行(先删后增)
        // 3. 更新明细行(先删后增,每条生成独立售后单号:工单号-序号)
        ticketItemMapper.deleteByTicketId(ticket.getId());
        if (CollUtil.isNotEmpty(updateReqVO.getItems())) {
            updateReqVO.getItems().forEach(item -> {
                AfterSaleTicketItemDO itemDO = BeanUtils.toBean(item, AfterSaleTicketItemDO.class);
            for (int i = 0; i < updateReqVO.getItems().size(); i++) {
                AfterSaleTicketItemDO itemDO = BeanUtils.toBean(updateReqVO.getItems().get(i), AfterSaleTicketItemDO.class);
                itemDO.setTicketId(ticket.getId());
                itemDO.setItemNo(buildItemNo(ticket.getNo(), i + 1));
                ticketItemMapper.insert(itemDO);
            });
            }
        }
        // 4. 更新附件
        storageAttachmentApi.updateAttachments("file", "aftersales_after_sale_ticket", updateReqVO.getId(), updateReqVO.getBlobIds());
    }
    @Override
@@ -113,6 +126,7 @@
        // 软删除
        ticketMapper.deleteById(id);
        ticketItemMapper.deleteByTicketId(id);
        storageAttachmentApi.deleteAttachmentsByRecord("aftersales_after_sale_ticket", id);
        permissionService.deletePermission(AfterSaleBizTypeEnum.AFTER_SALE_TICKET.getType(), id);
    }
@@ -192,6 +206,11 @@
    // ========== 内部方法 ==========
    /** 生成明细售后单号:工单号-两位序号 */
    private String buildItemNo(String ticketNo, int index) {
        return ticketNo + "-" + String.format("%02d", index);
    }
    private AfterSaleTicketDO validateTicketExists(Long id) {
        AfterSaleTicketDO ticket = ticketMapper.selectById(id);
        if (ticket == null) {