feat(process): 完善检验委托单功能实现绑定和关联管理
- 实现检验委托单与成品下单的绑定功能,包括新增绑定、解除绑定和变更绑定关系
- 添加检验委托单关联状态查询和未绑定委托单筛选功能
- 实现检验委托单绑定日志记录和报告同步功能
已添加3个文件
已修改10个文件
668 ■■■■■ 文件已修改
cnas-process/src/main/java/com/ruoyi/process/aspect/InspectionOrderSyncAspect.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/controller/InspectionOrderController.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/dto/InspectionOrderDto.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/mapper/InspectionOrderBindLogMapper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/mapper/InspectionOrderMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/pojo/InspectionOrder.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/pojo/InspectionOrderBindLog.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/service/InspectionOrderService.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/service/impl/InspectionOrderServiceImpl.java 393 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/resources/mapper/InspectionOrderMapper.xml 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/resources/static/inspection-order.docx 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/java/com/ruoyi/inspect/dto/InsPlaceOrderDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
inspect-server/src/main/resources/static/report-template.docx 补丁 | 查看 | 原始文档 | blame | 历史
cnas-process/src/main/java/com/ruoyi/process/aspect/InspectionOrderSyncAspect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.ruoyi.process.aspect;
import com.ruoyi.inspect.pojo.InsOrder;
import com.ruoyi.process.service.InspectionOrderService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * æˆå“ä¸‹å•和报告流程完成后,同步检验委托单中的衍生信息。
 *
 * cnas-process ä¾èµ– inspect-server,因此通过切面监听,避免 inspect-server
 * åå‘依赖过程要求模块。
 */
@Aspect
@Component
@Slf4j
public class InspectionOrderSyncAspect {
    @Resource
    private InspectionOrderService inspectionOrderService;
    @AfterReturning(value = "execution(* com.ruoyi.inspect.service.impl.InsOrderServiceImpl.upInsOrderOfState(..)) && args(insOrder)")
    public void syncEntrustCode(InsOrder insOrder) {
        if (insOrder == null || !Integer.valueOf(1).equals(insOrder.getState())) {
            return;
        }
        try {
            inspectionOrderService.syncEntrustCode(insOrder.getId());
        } catch (Exception e) {
            log.error("同步检验委托单委托编号失败,成品下单ID:{}", insOrder.getId(), e);
        }
    }
    @AfterReturning(value = "execution(* com.ruoyi.inspect.service.impl.InsReportServiceImpl.ratifyReport(..)) && args(reportId, isRatify, ratifyTell)")
    public void syncReportFile(Integer reportId, Integer isRatify, String ratifyTell) {
        if (!Integer.valueOf(1).equals(isRatify)) {
            return;
        }
        try {
            inspectionOrderService.syncReportFile(reportId);
        } catch (Exception e) {
            // æŠ¥å‘Šæ‰¹å‡†ä¸èƒ½å› å§”托单附件同步失败而回滚,保留日志供后续重试。
            log.error("同步检验委托单报告失败,报告ID:{}", reportId, e);
        }
    }
}
cnas-process/src/main/java/com/ruoyi/process/controller/InspectionOrderController.java
@@ -3,8 +3,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.common.utils.JackSonUtil;
import com.ruoyi.inspect.pojo.InsOrder;
import com.ruoyi.inspect.dto.InsPlaceOrderDto;
import com.ruoyi.process.dto.InspectionOrderDto;
import com.ruoyi.process.pojo.InspectionOrder;
import com.ruoyi.process.service.InspectionOrderService;
@@ -13,9 +12,9 @@
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.security.access.prepost.PreAuthorize;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
 * <p>
@@ -54,6 +53,32 @@
        return Result.success(inspectionOrderService.addInspectionOrder(InspectionOrder));
    }
    @ApiOperation(value = "查询未绑定检验委托单")
    @GetMapping("/pageUnboundInspectionOrder")
    public Result<IPage<InspectionOrder>> pageUnboundInspectionOrder(InspectionOrder inspectionOrder, Page page) {
        return Result.success(inspectionOrderService.pageUnboundInspectionOrder(page, inspectionOrder));
    }
    @ApiOperation(value = "获取成品下单关联的委托单信息")
    @GetMapping("/getInspectionOrderForPlaceOrder")
    public Result<InspectionOrderDto> getInspectionOrderForPlaceOrder(Integer inspectionOrderId) {
        return Result.success(inspectionOrderService.getInspectionOrderForPlaceOrder(inspectionOrderId));
    }
    @ApiOperation(value = "新增成品下单并绑定检验委托单")
    @PreAuthorize("@ss.hasPermi('add:insOrder')")
    @PostMapping("/addInsOrderWithInspectionOrder")
    public Result<Integer> addInsOrderWithInspectionOrder(@RequestBody InsPlaceOrderDto insPlaceOrderDto) {
        return Result.success(inspectionOrderService.addInsOrderWithInspectionOrder(insPlaceOrderDto));
    }
    @ApiOperation(value = "变更检验委托单关联")
    @PreAuthorize("@ss.hasPermi('add:insOrder')")
    @PostMapping("/changeBinding")
    public Result changeBinding(Integer insOrderId, Integer inspectionOrderId, String reason) {
        return Result.success(inspectionOrderService.changeBinding(insOrderId, inspectionOrderId, reason));
    }
    /**
     * å§”托单检验修改
     * @return
@@ -82,26 +107,6 @@
    @GetMapping("/getInspectionOrderOne")
    public Result<InspectionOrderDto> getInspectionOrderOne(Integer inspectionOrderId){
        return Result.success(inspectionOrderService.getInspectionOrderOne(inspectionOrderId));
    }
    /**
     * å§”托单检验查看详情
     * @return
     */
    @ApiOperation(value = "根据成品订单查询委托单详情")
    @GetMapping("/getInspectionOrderByInsOderId")
    public Result<InspectionOrderDto> getInspectionOrderByInsOderId(Integer insOrderId){
        return Result.success(inspectionOrderService.getInspectionOrderByInsOderId(insOrderId));
    }
    /**
     * å§”托单查询成品订单
     * @return
     */
    @ApiOperation(value = "委托单查询成品订单")
    @GetMapping("/getInsOrderOnInspection")
    public Result<IPage<InsOrder>> getInsOrderOnInspection(Page page ,InsOrder insOrder) throws Exception {
        return Result.success(inspectionOrderService.getInsOrderOnInspection(page, insOrder));
    }
    /**
cnas-process/src/main/java/com/ruoyi/process/dto/InspectionOrderDto.java
@@ -16,4 +16,19 @@
    @ApiModelProperty("委托检验单详情")
    private List<InspectionOrderDetail> orderDetailList;
    @ApiModelProperty("关联状态:0未绑定,1已绑定")
    private Integer bindingStatus;
    @ApiModelProperty("成品下单状态")
    private Integer orderState;
    @ApiModelProperty("检验进度")
    private String insProgress;
    @ApiModelProperty("检验结果")
    private Integer insResult;
    @ApiModelProperty("报告状态:0未生成,1待同步,2可下载")
    private Integer reportStatus;
}
cnas-process/src/main/java/com/ruoyi/process/mapper/InspectionOrderBindLogMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,10 @@
package com.ruoyi.process.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.process.pojo.InspectionOrderBindLog;
/**
 * æ£€éªŒå§”托单关联变更日志 Mapper。
 */
public interface InspectionOrderBindLogMapper extends BaseMapper<InspectionOrderBindLog> {
}
cnas-process/src/main/java/com/ruoyi/process/mapper/InspectionOrderMapper.java
@@ -4,7 +4,6 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.inspect.pojo.InsOrder;
import com.ruoyi.process.dto.InspectionOrderDto;
import com.ruoyi.process.pojo.InspectionOrder;
import org.apache.ibatis.annotations.Param;
@@ -31,11 +30,8 @@
    IPage<InspectionOrderDto> pageInspectionOrder(Page page, @Param("ew") QueryWrapper<InspectionOrder> ew);
    /**
     * å§”托单查询成品订单
     * @param page
     * @param insOrderQueryWrapper
     * @return
     * æˆå“ä¸‹å•选择未绑定的检验委托单
     */
    IPage<InsOrder> getInsOrderOnInspection(Page page, @Param("ew") QueryWrapper<InsOrder> insOrderQueryWrapper);
    IPage<InspectionOrder> pageUnboundInspectionOrder(Page page, @Param("ew") QueryWrapper<InspectionOrder> ew);
}
cnas-process/src/main/java/com/ruoyi/process/pojo/InspectionOrder.java
@@ -26,6 +26,9 @@
    @TableId(value = "inspection_order_id", type = IdType.AUTO)
    private Integer inspectionOrderId;
    @ApiModelProperty("委托单号")
    private String inspectionOrderCode;
    @ApiModelProperty("成品订单id")
    private Integer insOrderId;
@@ -50,8 +53,14 @@
    @ApiModelProperty("委托单位")
    private String commissionUnit;
    @ApiModelProperty("委托单位ID")
    private Long commissionUnitId;
    @ApiModelProperty("委托人")
    private String commissionUser;
    @ApiModelProperty("委托人ID")
    private Integer commissionUserId;
    @ApiModelProperty("委托人联系方式")
    private String commissionPhone;
@@ -86,6 +95,9 @@
    @ApiModelProperty("领样人员")
    private String sampleTakerUser;
    @ApiModelProperty("领样人员ID")
    private Integer sampleTakerUserId;
    @ApiModelProperty("领样日期")
    private LocalDate sampleData;
cnas-process/src/main/java/com/ruoyi/process/pojo/InspectionOrderBindLog.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
package com.ruoyi.process.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * æ£€éªŒå§”托单与成品下单的人工变更记录。
 */
@Data
@TableName("cnas_inspection_order_bind_log")
@ApiModel(value = "InspectionOrderBindLog对象", description = "检验委托单关联变更日志")
public class InspectionOrderBindLog {
    @ApiModelProperty("主键")
    @TableId(type = IdType.AUTO)
    private Long id;
    @ApiModelProperty("成品下单ID")
    private Integer insOrderId;
    @ApiModelProperty("原检验委托单ID")
    private Integer oldInspectionOrderId;
    @ApiModelProperty("新检验委托单ID")
    private Integer newInspectionOrderId;
    @ApiModelProperty("变更原因")
    private String changeReason;
    @ApiModelProperty("操作人ID")
    private Integer createUser;
    @ApiModelProperty("操作时间")
    private LocalDateTime createTime;
}
cnas-process/src/main/java/com/ruoyi/process/service/InspectionOrderService.java
@@ -3,7 +3,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.inspect.pojo.InsOrder;
import com.ruoyi.inspect.dto.InsPlaceOrderDto;
import com.ruoyi.process.dto.InspectionOrderDto;
import com.ruoyi.process.pojo.InspectionOrder;
import org.springframework.web.multipart.MultipartFile;
@@ -33,7 +33,7 @@
     * @param InspectionOrder
     * @return
     */
    boolean addInspectionOrder(InspectionOrderDto InspectionOrder);
    InspectionOrderDto addInspectionOrder(InspectionOrderDto inspectionOrder);
    /**
     * æ£€éªŒå§”托单修改
@@ -57,17 +57,34 @@
    InspectionOrderDto getInspectionOrderOne(Integer inspectionOrderId);
    /**
     * æ ¹æ®æˆå“è®¢å•id查询委托单信息
     * @param insOrderId
     * @return
     * æŸ¥è¯¢æœªç»‘定的检验委托单,供成品下单选择。
     */
    InspectionOrderDto getInspectionOrderByInsOderId(Integer insOrderId);
    IPage<InspectionOrder> pageUnboundInspectionOrder(Page page, InspectionOrder inspectionOrder);
    /**
     * å§”托单查询成品订单
     * @return
     * èŽ·å–æˆå“ä¸‹å•åˆå§‹åŒ–æ‰€éœ€çš„å§”æ‰˜å•ä¿¡æ¯ã€‚
     */
    IPage<InsOrder> getInsOrderOnInspection(Page page, InsOrder insOrder);
    InspectionOrderDto getInspectionOrderForPlaceOrder(Integer inspectionOrderId);
    /**
     * æ–°å¢žæˆå“ä¸‹å•并与委托单绑定。
     */
    Integer addInsOrderWithInspectionOrder(InsPlaceOrderDto insPlaceOrderDto);
    /**
     * ä¸‹å•生成委托编号后回写检验委托单。
     */
    void syncEntrustCode(Integer insOrderId);
    /**
     * æ­£å¼æŠ¥å‘Šæ‰¹å‡†åŽå¤åˆ¶æŠ¥å‘Šå¹¶å›žå†™å§”托单文件地址。
     */
    void syncReportFile(Integer insReportId);
    /**
     * æ›´æ­£ä¸‹å•与委托单的绑定关系。
     */
    boolean changeBinding(Integer insOrderId, Integer inspectionOrderId, String reason);
    /**
     * å§”托单成品报告上传
cnas-process/src/main/java/com/ruoyi/process/service/impl/InspectionOrderServiceImpl.java
@@ -10,24 +10,34 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.ruoyi.common.numgen.NumberGenerator;
import com.ruoyi.common.core.domain.entity.Custom;
import com.ruoyi.common.core.domain.entity.User;
import com.ruoyi.common.utils.QueryWrappers;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.exception.ErrorException;
import com.ruoyi.inspect.dto.InsOrderDeviceRecordDto;
import com.ruoyi.inspect.dto.InsPlaceOrderDto;
import com.ruoyi.inspect.mapper.InsProductResultMapper;
import com.ruoyi.inspect.mapper.InsSampleMapper;
import com.ruoyi.inspect.pojo.*;
import com.ruoyi.inspect.pojo.InsOrder;
import com.ruoyi.inspect.pojo.InsProductResult;
import com.ruoyi.inspect.pojo.InsReport;
import com.ruoyi.inspect.service.InsOrderService;
import com.ruoyi.inspect.service.InsReportService;
import com.ruoyi.inspect.util.HackLoopTableRenderPolicy;
import com.ruoyi.process.dto.InspectionOrderDto;
import com.ruoyi.process.dto.InspectionOrderExportDto;
import com.ruoyi.process.mapper.InspectionOrderBindLogMapper;
import com.ruoyi.process.mapper.InspectionOrderMapper;
import com.ruoyi.process.mapper.ProcessOrderDeviceMapper;
import com.ruoyi.process.mapper.ProcessSampleMapper;
import com.ruoyi.process.pojo.*;
import com.ruoyi.process.pojo.InspectionOrder;
import com.ruoyi.process.pojo.InspectionOrderBindLog;
import com.ruoyi.process.pojo.InspectionOrderDetail;
import com.ruoyi.process.pojo.ProcessOrderDevice;
import com.ruoyi.process.service.*;
import com.ruoyi.system.mapper.UserMapper;
import com.ruoyi.system.mapper.CustomMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@@ -44,10 +54,12 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -61,6 +73,8 @@
@Service
@Transactional(rollbackFor = Exception.class)
public class InspectionOrderServiceImpl extends ServiceImpl<InspectionOrderMapper, InspectionOrder> implements InspectionOrderService {
    @Resource
    private InspectionOrderBindLogMapper inspectionOrderBindLogMapper;
    @Resource
    private InspectionOrderDetailService inspectionOrderDetailService;
    @Resource
@@ -82,15 +96,20 @@
    @Resource
    private UserMapper userMapper;
    @Resource
    private CustomMapper customMapper;
    @Resource
    private ProcessSampleService processSampleService;
    @Resource
    private ProcessSampleMapper processSampleMapper;
    @Resource
    private ProcessDealService processDealService;
    @Resource
    private NumberGenerator<InspectionOrder> numberGenerator;
    /**
     * æ£€éªŒå§”托单分页查询
     *
     * @param page
     * @param InspectionOrder
     * @return
@@ -102,39 +121,23 @@
    /**
     * æ£€éªŒå§”托单新增
     *
     * @param inspectionOrder
     * @return
     */
    @Override
    public boolean addInspectionOrder(InspectionOrderDto inspectionOrder) {
        if (inspectionOrder.getInsOrderId() == null) {
            throw new ErrorException("缺少订单id");
    public InspectionOrderDto addInspectionOrder(InspectionOrderDto inspectionOrder) {
        if (inspectionOrder.getInsOrderId() != null) {
            throw new ErrorException("新增检验委托单不允许直接绑定成品下单,请在成品下单页面选择委托单");
        }
        normalizeCommissionParty(inspectionOrder);
        // å¤åˆ¶æŠ¥å‘Š
        // æŸ¥è¯¢è®¢å•报告
        InsReport insReport = insReportService.getOne(Wrappers.<InsReport>lambdaQuery()
                .eq(InsReport::getInsOrderId, inspectionOrder.getInsOrderId()));
        String path = wordUrl + insReport.getUrl().replaceFirst("/word", "");
        String fileName =LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss")) + "_" + "委托单报告.docx";
        // æºæ–‡ä»¶è·¯å¾„
        Path sourcePath = Paths.get(path);
        // ç›®æ ‡æ–‡ä»¶è·¯å¾„
        Path targetPath = Paths.get(wordUrl + "/" + fileName);
        try {
            // å¤åˆ¶æ–‡ä»¶ï¼Œå¦‚果目标文件已存在,则覆盖
            Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
            // æ·»åŠ æ–‡ä»¶åœ°å€
            inspectionOrder.setFileUrl("/word/" + fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        inspectionOrder.setInspectionOrderCode(numberGenerator.generateNumberWithPrefix(4,
                "WTD" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")),
                InspectionOrder::getInspectionOrderCode));
        // å§”托编号由成品下单流程生成,委托单新增阶段不得手工填写。
        inspectionOrder.setEntrustCode(null);
        inspectionOrder.setFileUrl(null);
        baseMapper.insert(inspectionOrder);
        // æ–°å¢žè¯¦æƒ…
        if (CollectionUtils.isNotEmpty(inspectionOrder.getOrderDetailList())) {
@@ -143,50 +146,10 @@
            }
            inspectionOrderDetailService.saveBatch(inspectionOrder.getOrderDetailList());
        }
        /*新增7.8报告结果*/
        ProcessReport processReport = new ProcessReport();
        processReport.setInspectionOrderId(inspectionOrder.getInsOrderId());
        processReport.setInsReportCode(inspectionOrder.getEntrustCode());//报告编号=委托编号
        //页数
        try {
            com.aspose.words.Document doc = new com.aspose.words.Document(path);
            processReport.setPages(doc.getPageCount()+"");
        } catch (Exception e) {
        }
        processReport.setNumber("1");//发送份数默认1
        processReport.setSend(inspectionOrder.getCommissionUnit());//发往何处=委托单位
        processReport.setMethod(inspectionOrder.getSend()==1?"自取":"其他");//发送方式
        processReport.setSendTime(insReport.getRatifyTime().toLocalDate());//发送日期
        processReport.setSendUser(64);//发送人固定
        processReport.setSignatory(inspectionOrder.getCommissionUser());//签收人=委托人
        processReportService.save(processReport);
        /*新增7.1委托单对应的设备使用记录*/
        addDeviceRecord(inspectionOrder,insReport.getWriteUserId());
        /*新增7.4样品接收*/
        List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
                .eq(InsSample::getInsOrderId, inspectionOrder.getInsOrderId()));
        if (insSamples.size()>0){
            List<ProcessSample> processSamples = new ArrayList<>();
            for (InsSample insSample : insSamples) {
                ProcessSample processSample = new ProcessSample();
                processSample.setReceiveDate(inspectionOrder.getSampleData());//收样日期=领样日期
                processSample.setSampleCode(insSample.getSampleCode());//样品编号
                processSample.setSampleName(insSample.getSample());//样品名称
                processSample.setNum(1);//样品数量=1
                processSample.setSampleSupplier(inspectionOrder.getCommissionUnit());//来样单位
                LocalDate plusMonths = inspectionOrder.getSampleData() == null ? null : inspectionOrder.getSampleData().plusMonths(1);
                processSample.setLeaveDate(plusMonths);//留样日期=收样日期往后延一个月
                processSample.setSampleState(inspectionOrder.getSampleStatus());//样品状态
                processSample.setDealTime(plusMonths);//退样日期=留样日期
                processSample.setInspectionOrderId(inspectionOrder.getInspectionOrderId());//委托单id
                processSamples.add(processSample);
            }
            processSampleService.saveBatch(processSamples);
        }
        return true;
        return inspectionOrder;
    }
    private synchronized void addDeviceRecord(InspectionOrder inspectionOrder,Integer userId) {
    private synchronized void addDeviceRecord(InspectionOrder inspectionOrder, Integer userId) {
        // æŸ¥è¯¢è®¾å¤‡ä½¿ç”¨è®°å½•查询该订单的使用记录
        Set<String> recordCodeset = processOrderDeviceMapper.selectDeviceNumber(inspectionOrder.getInspectionOrderId());
        // èŽ·å–è®¢å•è®¾å¤‡ç¼–å·
@@ -229,11 +192,24 @@
    /**
     * æ£€éªŒå§”托单修改
     *
     * @param InspectionOrder
     * @return
     */
    @Override
    public boolean updateInspectionOrder(InspectionOrderDto InspectionOrder) {
        InspectionOrder oldInspectionOrder = baseMapper.selectById(InspectionOrder.getInspectionOrderId());
        if (oldInspectionOrder == null) {
            throw new ErrorException("检验委托单不存在");
        }
        normalizeCommissionParty(InspectionOrder);
        // ç¼–号、关联关系、正式委托编号和报告地址只能由专用流程维护。
        InspectionOrder.setInspectionOrderCode(null);
        InspectionOrder.setInsOrderId(null);
        InspectionOrder.setEntrustCode(null);
        InspectionOrder.setFileUrl(null);
        InspectionOrder.setSampleTakerUserId(null);
        InspectionOrder.setSampleTakerUser(null);
        baseMapper.updateById(InspectionOrder);
        // åˆ é™¤ä¹‹å‰çš„详情
@@ -241,51 +217,41 @@
                .eq(InspectionOrderDetail::getInspectionOrderId, InspectionOrder.getInspectionOrderId()));
        // æ–°å¢žè¯¦æƒ…
        for (InspectionOrderDetail InspectionOrderDetail : InspectionOrder.getOrderDetailList()) {
            InspectionOrderDetail.setInspectionOrderId(InspectionOrder.getInspectionOrderId());
        if (CollectionUtils.isNotEmpty(InspectionOrder.getOrderDetailList())) {
            for (InspectionOrderDetail InspectionOrderDetail : InspectionOrder.getOrderDetailList()) {
                InspectionOrderDetail.setInspectionOrderId(InspectionOrder.getInspectionOrderId());
            }
            inspectionOrderDetailService.saveBatch(InspectionOrder.getOrderDetailList());
        }
        inspectionOrderDetailService.saveBatch(InspectionOrder.getOrderDetailList());
        //修改7.9报告结果
        ProcessReport processReport = processReportService.getOne(Wrappers.<ProcessReport>lambdaQuery().eq(ProcessReport::getInspectionOrderId, InspectionOrder.getInspectionOrderId()));
        processReport.setInsReportCode(InspectionOrder.getEntrustCode());//报告编号=委托编号
        processReportService.updateById(processReport);
        return true;
    }
    /**
     * æ£€éªŒå§”托单删除
     *
     * @param inspectionOrderId
     * @return
     */
    @Override
    public boolean delInspectionOrder(Integer inspectionOrderId) {
        InspectionOrder inspectionOrder = baseMapper.selectById(inspectionOrderId);
        if (inspectionOrder == null) {
            throw new ErrorException("检验委托单不存在");
        }
        if (inspectionOrder.getInsOrderId() != null) {
            throw new ErrorException("已绑定成品下单的检验委托单不允许删除");
        }
        inspectionOrderDetailService.remove(Wrappers.<InspectionOrderDetail>lambdaQuery()
                .eq(InspectionOrderDetail::getInspectionOrderId, inspectionOrderId));
        baseMapper.deleteById(inspectionOrderId);
        //删除7.8报告
        processReportService.remove(Wrappers.<ProcessReport>lambdaQuery()
                .eq(ProcessReport::getInspectionOrderId, inspectionOrderId));
        //删除对应的设备使用记录
        processOrderDeviceService.remove(Wrappers.<ProcessOrderDevice>lambdaQuery()
                .eq(ProcessOrderDevice::getInspectionOrderId, inspectionOrderId));
        //删除对应的7.4的样品申请
        List<ProcessSample> processSamples = processSampleMapper.selectList(Wrappers.<ProcessSample>lambdaQuery()
                .eq(ProcessSample::getInspectionOrderId, inspectionOrderId));
        if (processSamples.size()>0){
            List<Integer> list = processSamples.stream().map(ProcessSample::getId).collect(Collectors.toList());
            processDealService.remove(Wrappers.<ProcessDeal>lambdaQuery()
                    .in(ProcessDeal::getProcessSampleId,list));
        }
        //删除对应7.4的样品接收
        processSampleService.remove(Wrappers.<ProcessSample>lambdaQuery()
                .eq(ProcessSample::getInspectionOrderId,inspectionOrderId));
        return true;
    }
    /**
     * æ£€éªŒå§”托单查看详情
     *
     * @param inspectionOrderId
     * @return
     */
@@ -301,43 +267,197 @@
        return inspectionOrderDto;
    }
    /**
     * æ ¹æ®æˆå“è®¢å•id查询委托单详情
     * @param insOrderId
     * @return
     */
    @Override
    public InspectionOrderDto getInspectionOrderByInsOderId(Integer insOrderId) {
        InsOrder order = insOrderService.getById(insOrderId);
        InspectionOrderDto inspectionOrderDto = new InspectionOrderDto();
        inspectionOrderDto.setInsOrderId(order.getId());//成品订单id
        inspectionOrderDto.setEntrustCode(order.getEntrustCode());//委托编号
        inspectionOrderDto.setSampleName(order.getSample());//试样名称
        inspectionOrderDto.setProduction(order.getProduction());//生产单位
        inspectionOrderDto.setCommissionUnit(order.getCompany());//委托单位
        inspectionOrderDto.setCommissionUser(order.getPrepareUser());//委托人
        inspectionOrderDto.setSampleStatus("完好");//样品状态
        inspectionOrderDto.setIsLeave(order.getIsLeave());//是否留样
        inspectionOrderDto.setProcessing(order.getProcessing());//样品处理方式
        inspectionOrderDto.setAppointed(order.getAppointed());//约定时间
        inspectionOrderDto.setSend(order.getSend());//报告发送方式
        inspectionOrderDto.setCommissionPhone(order.getPhone());//报告发送方式
        return inspectionOrderDto;
    public IPage<InspectionOrder> pageUnboundInspectionOrder(Page page, InspectionOrder inspectionOrder) {
        return baseMapper.pageUnboundInspectionOrder(page, QueryWrappers.queryWrappers(inspectionOrder));
    }
    /**
     * å§”托单查询成品订单
     * @return
     */
    @Override
    public IPage<InsOrder> getInsOrderOnInspection(Page page, InsOrder insOrder) {
        return baseMapper.getInsOrderOnInspection(page, QueryWrappers.queryWrappers(insOrder));
    public InspectionOrderDto getInspectionOrderForPlaceOrder(Integer inspectionOrderId) {
        InspectionOrder inspectionOrder = baseMapper.selectById(inspectionOrderId);
        if (inspectionOrder == null) {
            throw new ErrorException("检验委托单不存在");
        }
        if (inspectionOrder.getInsOrderId() != null) {
            throw new ErrorException("该检验委托单已绑定成品下单,不能重复选择");
        }
        return getInspectionOrderOne(inspectionOrderId);
    }
    @Override
    public Integer addInsOrderWithInspectionOrder(InsPlaceOrderDto insPlaceOrderDto) {
        if (insPlaceOrderDto == null || insPlaceOrderDto.getInspectionOrderId() == null) {
            throw new ErrorException("请选择检验委托单");
        }
        if (insPlaceOrderDto.getInsOrder() == null) {
            throw new ErrorException("缺少成品下单信息");
        }
        InspectionOrder inspectionOrder = baseMapper.selectById(insPlaceOrderDto.getInspectionOrderId());
        if (inspectionOrder == null) {
            throw new ErrorException("检验委托单不存在");
        }
        if (inspectionOrder.getInsOrderId() != null) {
            throw new ErrorException("该检验委托单已绑定成品下单,不能重复提交");
        }
        if (inspectionOrder.getCommissionUnitId() == null) {
            throw new ErrorException("请先完善委托单位");
        }
        if (inspectionOrder.getCommissionUserId() == null) {
            throw new ErrorException("请先完善委托人");
        }
        fillInsOrderFromInspectionOrder(inspectionOrder, insPlaceOrderDto.getInsOrder());
        Integer insOrderId = insOrderService.addInsOrder(insPlaceOrderDto.getSampleList(), insPlaceOrderDto.getInsOrder());
        Long sampleTakerUserId = SecurityUtils.getUserId();
        User sampleTaker = sampleTakerUserId == null ? null : userMapper.selectById(sampleTakerUserId);
        int updated = baseMapper.update(null, Wrappers.<InspectionOrder>lambdaUpdate()
                .eq(InspectionOrder::getInspectionOrderId, inspectionOrder.getInspectionOrderId())
                .isNull(InspectionOrder::getInsOrderId)
                .set(InspectionOrder::getInsOrderId, insOrderId)
                .set(InspectionOrder::getSampleTakerUserId, sampleTakerUserId == null ? null : sampleTakerUserId.intValue())
                .set(InspectionOrder::getSampleTakerUser, sampleTaker == null ? null : sampleTaker.getName()));
        if (updated != 1) {
            throw new ErrorException("检验委托单已被其他下单绑定,请刷新后重试");
        }
        return insOrderId;
    }
    private void fillInsOrderFromInspectionOrder(InspectionOrder inspectionOrder, InsOrder insOrder) {
        insOrder.setEntrustCode(null);
        insOrder.setSample(inspectionOrder.getSampleName());
        insOrder.setCompany(inspectionOrder.getCommissionUnit());
        insOrder.setCompanyId(inspectionOrder.getCommissionUnitId());
        insOrder.setProduction(inspectionOrder.getProduction());
        insOrder.setPrepareUser(inspectionOrder.getCommissionUser());
        insOrder.setPhone(inspectionOrder.getCommissionPhone());
        insOrder.setSampleStatus(inspectionOrder.getSampleStatus());
        insOrder.setIsLeave(inspectionOrder.getIsLeave());
        insOrder.setProcessing(inspectionOrder.getProcessing());
        insOrder.setAppointed(inspectionOrder.getAppointed());
        insOrder.setSend(inspectionOrder.getSend());
    }
    /** ä»…信任客户和人员主数据,名称与电话均以主数据快照为准。 */
    private void normalizeCommissionParty(InspectionOrder inspectionOrder) {
        if (inspectionOrder.getCommissionUnitId() == null) {
            throw new ErrorException("请选择委托单位");
        }
        Custom custom = customMapper.selectById(inspectionOrder.getCommissionUnitId());
        if (custom == null) {
            throw new ErrorException("委托单位不存在或已停用");
        }
        inspectionOrder.setCommissionUnit(custom.getCompany());
        if (inspectionOrder.getCommissionUserId() == null) {
            throw new ErrorException("请选择委托人");
        }
        User commissionUser = userMapper.selectById(inspectionOrder.getCommissionUserId());
        if (commissionUser == null) {
            throw new ErrorException("委托人不存在或已停用");
        }
        inspectionOrder.setCommissionUser(commissionUser.getName());
        inspectionOrder.setCommissionPhone(commissionUser.getPhone());
    }
    @Override
    public void syncEntrustCode(Integer insOrderId) {
        if (insOrderId == null) {
            return;
        }
        InsOrder insOrder = insOrderService.getById(insOrderId);
        if (insOrder == null || StrUtil.isBlank(insOrder.getEntrustCode())) {
            return;
        }
        baseMapper.update(null, Wrappers.<InspectionOrder>lambdaUpdate()
                .eq(InspectionOrder::getInsOrderId, insOrderId)
                .set(InspectionOrder::getEntrustCode, insOrder.getEntrustCode()));
    }
    @Override
    public void syncReportFile(Integer insReportId) {
        if (insReportId == null) {
            return;
        }
        InsReport insReport = insReportService.getById(insReportId);
        if (insReport == null || !Integer.valueOf(1).equals(insReport.getIsRatify())) {
            return;
        }
        InspectionOrder inspectionOrder = baseMapper.selectOne(Wrappers.<InspectionOrder>lambdaQuery()
                .eq(InspectionOrder::getInsOrderId, insReport.getInsOrderId())
                .last("limit 1"));
        if (inspectionOrder == null) {
            return;
        }
        String sourceUrl = StrUtil.isBlank(insReport.getUrlS()) ? insReport.getUrl() : insReport.getUrlS();
        if (StrUtil.isBlank(sourceUrl)) {
            throw new ErrorException("正式报告文件不存在,无法同步到检验委托单");
        }
        String sourceFileName = sourceUrl.substring(sourceUrl.lastIndexOf('/') + 1);
        String extension = sourceFileName.lastIndexOf('.') >= 0
                ? sourceFileName.substring(sourceFileName.lastIndexOf('.')) : ".docx";
        String fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmss"))
                + "_" + inspectionOrder.getInspectionOrderCode() + "_委托单报告" + extension;
        Path sourcePath = Paths.get(wordUrl + sourceUrl.replaceFirst("/word", ""));
        Path targetPath = Paths.get(wordUrl, fileName);
        try {
            if (!Files.exists(sourcePath)) {
                throw new ErrorException("正式报告文件不存在,无法同步到检验委托单");
            }
            Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
            baseMapper.update(null, Wrappers.<InspectionOrder>lambdaUpdate()
                    .eq(InspectionOrder::getInspectionOrderId, inspectionOrder.getInspectionOrderId())
                    .set(InspectionOrder::getFileUrl, "/word/" + fileName));
        } catch (ErrorException e) {
            throw e;
        } catch (Exception e) {
            throw new ErrorException("报告同步失败");
        }
    }
    @Override
    public boolean changeBinding(Integer insOrderId, Integer inspectionOrderId, String reason) {
        if (insOrderId == null || inspectionOrderId == null || StrUtil.isBlank(reason)) {
            throw new ErrorException("缺少变更关联所需参数");
        }
        InsOrder insOrder = insOrderService.getById(insOrderId);
        if (insOrder == null) {
            throw new ErrorException("成品下单不存在");
        }
        if (!(Integer.valueOf(0).equals(insOrder.getState()) || Integer.valueOf(2).equals(insOrder.getState()))
                || StrUtil.isNotBlank(insOrder.getEntrustCode())) {
            throw new ErrorException("当前下单已进入检验流程或已生成委托编号,不允许变更关联");
        }
        InspectionOrder target = baseMapper.selectById(inspectionOrderId);
        if (target == null || target.getInsOrderId() != null) {
            throw new ErrorException("目标检验委托单不存在或已被绑定");
        }
        InspectionOrder oldInspectionOrder = baseMapper.selectOne(Wrappers.<InspectionOrder>lambdaQuery()
                .eq(InspectionOrder::getInsOrderId, insOrderId));
        baseMapper.update(null, Wrappers.<InspectionOrder>lambdaUpdate()
                .eq(InspectionOrder::getInsOrderId, insOrderId)
                .set(InspectionOrder::getInsOrderId, null));
        int updated = baseMapper.update(null, Wrappers.<InspectionOrder>lambdaUpdate()
                .eq(InspectionOrder::getInspectionOrderId, inspectionOrderId)
                .isNull(InspectionOrder::getInsOrderId)
                .set(InspectionOrder::getInsOrderId, insOrderId));
        if (updated != 1) {
            throw new ErrorException("目标检验委托单已被其他下单绑定,请刷新后重试");
        }
        InspectionOrderBindLog bindLog = new InspectionOrderBindLog();
        bindLog.setInsOrderId(insOrderId);
        bindLog.setOldInspectionOrderId(oldInspectionOrder == null ? null : oldInspectionOrder.getInspectionOrderId());
        bindLog.setNewInspectionOrderId(inspectionOrderId);
        bindLog.setChangeReason(reason.trim());
        bindLog.setCreateUser(SecurityUtils.getUserId().intValue());
        bindLog.setCreateTime(LocalDateTime.now());
        inspectionOrderBindLogMapper.insert(bindLog);
        return true;
    }
    /**
     * å§”托单成品报告上传
     *
     * @param file
     * @param inspectionOrderId
     * @return
@@ -359,7 +479,6 @@
            baseMapper.update(null, Wrappers.<InspectionOrder>lambdaUpdate()
                    .eq(InspectionOrder::getInspectionOrderId, inspectionOrderId)
                    .set(InspectionOrder::getFileUrl, "/word/" + pathName));
        } catch (Exception e) {
@@ -426,14 +545,14 @@
            inspectionOrderExportDto.setAppointedString(inspectionOrder.getAppointed().format(formatter));
        }
        inspectionOrderExportDto.setIsLeave1(inspectionOrder.getIsLeave() != null && inspectionOrder.getIsLeave() == 1? "☑" : "□");
        inspectionOrderExportDto.setIsLeave2(inspectionOrder.getIsLeave() != null && inspectionOrder.getIsLeave() == 0? "☑" : "□");
        inspectionOrderExportDto.setSend0(inspectionOrder.getSend() != null && inspectionOrder.getSend() == 1? "☑" : "□");
        inspectionOrderExportDto.setSend1(inspectionOrder.getSend() != null && inspectionOrder.getSend() == 0? "☑" : "□");
        inspectionOrderExportDto.setProcessing0(inspectionOrder.getProcessing() != null && inspectionOrder.getProcessing() == 0? "☑" : "□");
        inspectionOrderExportDto.setProcessing1(inspectionOrder.getProcessing() != null && inspectionOrder.getProcessing() == 1? "☑" : "□");
        inspectionOrderExportDto.setCriterionRule0(inspectionOrder.getCriterionRule() != null && inspectionOrder.getCriterionRule() == 0? "☑" : "□");
        inspectionOrderExportDto.setCriterionRule1(inspectionOrder.getCriterionRule() != null && inspectionOrder.getCriterionRule() == 1? "☑" : "□");
        inspectionOrderExportDto.setIsLeave1(inspectionOrder.getIsLeave() != null && inspectionOrder.getIsLeave() == 1 ? "☑" : "□");
        inspectionOrderExportDto.setIsLeave2(inspectionOrder.getIsLeave() != null && inspectionOrder.getIsLeave() == 0 ? "☑" : "□");
        inspectionOrderExportDto.setSend0(inspectionOrder.getSend() != null && inspectionOrder.getSend() == 1 ? "☑" : "□");
        inspectionOrderExportDto.setSend1(inspectionOrder.getSend() != null && inspectionOrder.getSend() == 0 ? "☑" : "□");
        inspectionOrderExportDto.setProcessing0(inspectionOrder.getProcessing() != null && inspectionOrder.getProcessing() == 0 ? "☑" : "□");
        inspectionOrderExportDto.setProcessing1(inspectionOrder.getProcessing() != null && inspectionOrder.getProcessing() == 1 ? "☑" : "□");
        inspectionOrderExportDto.setCriterionRule0(inspectionOrder.getCriterionRule() != null && inspectionOrder.getCriterionRule() == 0 ? "☑" : "□");
        inspectionOrderExportDto.setCriterionRule1(inspectionOrder.getCriterionRule() != null && inspectionOrder.getCriterionRule() == 1 ? "☑" : "□");
        return inspectionOrderExportDto;
    }
}
cnas-process/src/main/resources/mapper/InspectionOrderMapper.xml
@@ -5,21 +5,53 @@
    <!--检验委托单分页查询-->
    <select id="pageInspectionOrder" resultType="com.ruoyi.process.dto.InspectionOrderDto">
        select *
        from (select *
        from cnas_inspection_order
        order by create_time desc) a
        from (
            select cio.*,
                   case when cio.ins_order_id is null then 0 else 1 end as binding_status,
                   io.state as order_state,
                   io.ins_result as ins_result,
                   case
                       when cio.ins_order_id is null then null
                       when total_product_counts.total_count is null or total_product_counts.total_count = 0 then '0%'
                       else concat(round(ifnull(approved_product_counts.approved_count, 0) / total_product_counts.total_count * 100, 2), '%')
                   end as ins_progress,
                   case
                       when cio.file_url is not null and trim(cio.file_url) != '' then 2
                       when approved_report.id is not null then 1
                       else 0
                   end as report_status
            from cnas_inspection_order cio
                     left join ins_order io on cio.ins_order_id = io.id
                     left join (select max(id) as id, ins_order_id
                                from ins_report
                                where is_ratify = 1
                                group by ins_order_id) approved_report on approved_report.ins_order_id = io.id
                     left join (select ins_sample.ins_order_id, count(*) as total_count
                                from ins_product
                                         join ins_sample on ins_product.ins_sample_id = ins_sample.id
                                where ins_product.state = 1
                                group by ins_sample.ins_order_id) total_product_counts on total_product_counts.ins_order_id = io.id
                     left join (select ins_sample.ins_order_id, count(*) as approved_count
                                from ins_product
                                         join ins_sample on ins_product.ins_sample_id = ins_sample.id
                                where ins_product.state = 1 and ins_product.ins_result is not null
                                group by ins_sample.ins_order_id) approved_product_counts on approved_product_counts.ins_order_id = io.id
            order by cio.create_time desc
        ) a
        <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
            ${ew.customSqlSegment}
        </if>
    </select>
    <!--委托单查询成品订单-->
    <select id="getInsOrderOnInspection" resultType="com.ruoyi.inspect.pojo.InsOrder">
    <!--成品下单选择尚未绑定的检验委托单-->
    <select id="pageUnboundInspectionOrder" resultType="com.ruoyi.process.pojo.InspectionOrder">
        select *
        from (select *
        from ins_order
        where state = 4 and ifs_inventory_id is null
        order by entrust_code desc) a
        from (
            select *
            from cnas_inspection_order
            where ins_order_id is null
            order by create_time desc
        ) a
        <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
            ${ew.customSqlSegment}
        </if>
cnas-process/src/main/resources/static/inspection-order.docx
Binary files differ
inspect-server/src/main/java/com/ruoyi/inspect/dto/InsPlaceOrderDto.java
@@ -15,6 +15,9 @@
@Data
public class InsPlaceOrderDto{
    @ApiModelProperty("关联的检验委托单ID")
    private Integer inspectionOrderId;
    @ApiModelProperty("样品")
    private List<SampleProductDto> sampleList;
inspect-server/src/main/resources/static/report-template.docx
Binary files differ