From 3728fa293e1faf4bf4f9bf41105b84ddb43dc82e Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期一, 02 十一月 2026 16:53:02 +0800
Subject: [PATCH] feat(order-rates): 新增筛选条件下全部订单费用汇总接口

---
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java |  381 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 343 insertions(+), 38 deletions(-)

diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
index f8e1376..b7cfbbc 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsReportServiceImpl.java
@@ -35,6 +35,7 @@
 import com.ruoyi.common.constant.InsOrderTypeConstants;
 import com.ruoyi.common.constant.MenuJumpPathConstants;
 import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.core.domain.entity.User;
 import com.ruoyi.common.core.domain.entity.SysMenu;
 import com.ruoyi.common.core.domain.entity.InformationNotification;
 import com.ruoyi.common.utils.DateImageUtil;
@@ -50,6 +51,7 @@
 import com.ruoyi.inspect.service.InsOrderService;
 import com.ruoyi.inspect.service.InsReportService;
 import com.ruoyi.inspect.service.RawMaterialOrderService;
+import com.ruoyi.inspect.service.SealUsageLedgerService;
 import com.ruoyi.inspect.util.PreserveReportPicturePlaceholderHandler;
 import com.ruoyi.inspect.util.ReportSealLayoutUtil;
 import com.ruoyi.inspect.util.ReportSignaturePictureUtils;
@@ -102,11 +104,20 @@
 
     private static final int DETECTION_REPORT = 0;
     private static final int INSPECTION_REPORT = 1;
+    private static final String RETURN_TO_INSPECTION_TASK = "INSPECTION_TASK";
+    private static final String RETURN_TO_REPORT_REVIEW = "REPORT_REVIEW";
+    private static final int RETURNED_STATUS = 2;
 
     @Resource
     private UserMapper userMapper;
     @Resource
     private InsReportMapper insReportMapper;
+    @Resource
+    private InsReportEditSessionMapper insReportEditSessionMapper;
+    @Resource
+    private InsReportReturnRecordMapper insReportReturnRecordMapper;
+    @Resource
+    private SealUsageLedgerService sealUsageLedgerService;
     @Resource
     private InsOrderStateMapper insOrderStateMapper;
     @Resource
@@ -231,8 +242,6 @@
         info.setViewStatus(false);
         info.setJumpPath(MenuJumpPathConstants.REPORT_PREPARATION);
         informationNotificationService.addInformationNotification(info);
-        String primaryReportUrl = getPrimaryReportUrl(insReport);
-
         // 鍒ゆ柇鏄惁鏄師鏉愭枡  闇�瑕佹浛鎹�****鎴愪緵搴斿晢
         IfsInventoryQuantity one = ifsInventoryQuantityMapper.selectOne(new LambdaQueryWrapper<IfsInventoryQuantity>()
                 .eq(IfsInventoryQuantity::getId, order.getIfsInventoryId()));
@@ -253,9 +262,7 @@
         }};
         writeMarksToReportFiles(insReport, writeMarks);
 
-        // 淇敼涓存椂pdf
-        String tempUrlPdf = wordToPdfTemp(primaryReportUrl.replace("/word", wordUrl));
-        insReport.setTempUrlPdf("/word/" + tempUrlPdf);
+        refreshTemporaryPreviews(insReport);
 
         insReportMapper.updateById(insReport);
 
@@ -383,16 +390,13 @@
         info.setViewStatus(false);
         info.setJumpPath(MenuJumpPathConstants.REPORT_PREPARATION);
         informationNotificationService.addInformationNotification(info);
-        String primaryReportUrl = getPrimaryReportUrl(insReport);
         Map<String, Object> examineMarks = new HashMap<String, Object>() {{
             put("examineUrl", ReportSignaturePictureUtils.create(imgUrl, signatureUrl));
             put("examineDateUrl", Pictures.ofStream(DateImageUtil.createDateImage(null)).create());
         }};
         writeMarksToReportFiles(insReport, examineMarks);
 
-        // 淇敼涓存椂pdf
-        String tempUrlPdf = wordToPdfTemp(primaryReportUrl.replace("/word", wordUrl));
-        insReport.setTempUrlPdf("/word/" + tempUrlPdf);
+        refreshTemporaryPreviews(insReport);
 
         // 鍙戦�佷紒涓氬井淇¢�氱煡(閫氱煡鎵瑰噯浜哄鎵�)
         threadPoolTaskExecutor.execute(() -> {
@@ -438,7 +442,21 @@
     @Transactional(rollbackFor = Exception.class)
     public int ratifyReport(Integer id, Integer isRatify, String ratifyTell, String sealIds,
                             Integer maSealId, Integer reportSealId, Integer seamSealId) {
-        InsReport insReport = insReportMapper.selectById(id);
+        if (id == null || (isRatify == null || (isRatify != 0 && isRatify != 1))) {
+            throw new ErrorException("鎵瑰噯鍙傛暟涓嶆纭�");
+        }
+        InsReport insReport = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
+                .eq(InsReport::getId, id)
+                .last("FOR UPDATE"));
+        if (insReport == null) {
+            throw new ErrorException("鎶ュ憡涓嶅瓨鍦�");
+        }
+        if (Objects.equals(insReport.getIsRatify(), 1)) {
+            throw new ErrorException("鎶ュ憡宸叉壒鍑嗭紝璇峰嬁閲嶅鎿嶄綔");
+        }
+        if (!Objects.equals(insReport.getState(), 1) || !Objects.equals(insReport.getIsExamine(), 1)) {
+            throw new ErrorException("鎶ュ憡灏氭湭瀹℃牳閫氳繃锛屼笉鑳芥壒鍑�");
+        }
         if (Objects.equals(insReport.getExamineUserId(), SecurityUtils.getUserId().intValue())) {
             throw new ErrorException("瀹℃牳浜哄拰鎵瑰噯浜轰笉鑳戒负鍚屼竴浜猴紝璇烽噸鏂伴�夋嫨鎵瑰噯浜�");
         }
@@ -492,10 +510,21 @@
                 }
             });
 
-            //濡傛灉鎵瑰噯涓嶉�氳繃 鐩存帴閫�鍥炲埌鎻愪氦浜洪偅杈瑰幓
-            insReport.setState(0);
-            insReport.setIsExamine(0);
-            return insReportMapper.updateById(insReport);
+            // 鎵瑰噯涓嶉�氳繃鐩存帴閫�鍥炴姤鍛婂鏍革紝鐢卞師瀹℃牳浜轰慨鏀瑰悗閲嶆柊瀹℃牳銆佹壒鍑嗐��
+            recordReportReturn(insReport, "REPORT_APPROVAL", RETURN_TO_REPORT_REVIEW,
+                    StringUtils.isBlank(ratifyTell) ? "鎵瑰噯涓嶉�氳繃" : ratifyTell, insReport.getRatifyTime());
+            insReport.setState(1);
+            insReport.setExamineTell(ratifyTell);
+            int affected = insReportMapper.updateById(insReport);
+            if (affected != 1) {
+                throw new ErrorException("鎶ュ憡閫�鍥炲鏍稿け璐�");
+            }
+            insReportMapper.update(null, Wrappers.<InsReport>lambdaUpdate()
+                    .eq(InsReport::getId, id)
+                    .set(InsReport::getIsExamine, RETURNED_STATUS)
+                    .set(InsReport::getExamineTime, insReport.getRatifyTime()));
+            expireReportEditSessions(id);
+            return affected;
         }
         //鑾峰彇鎵瑰噯浜虹殑绛惧悕鍦板潃
         String signatureUrl;
@@ -545,6 +574,7 @@
         insReport.setReportSealName(reportSeal == null ? null : reportSeal.getName());
         insReport.setSeamSealId(seamSeal == null ? null : seamSeal.getId());
         insReport.setSeamSealName(seamSeal == null ? null : seamSeal.getName());
+        prepareApprovalCopies(insReport);
         String primaryReportUrl = getPrimaryReportUrl(insReport);
         String finalUrl = primaryReportUrl.replace("/word", wordUrl);
 
@@ -609,7 +639,12 @@
             });
         }
 
-        return insReportMapper.updateById(insReport);
+        int affected = insReportMapper.updateById(insReport);
+        if (affected != 1) {
+            throw new ErrorException("鎶ュ憡鎵瑰噯鐘舵�佷繚瀛樺け璐�");
+        }
+        sealUsageLedgerService.recordApprovedReport(insReport);
+        return affected;
     }
 
     /**
@@ -728,6 +763,61 @@
                 .collect(Collectors.toList());
     }
 
+    /** 鎵瑰噯绔犲彧鍐欏叆鍓湰锛屼繚鐣欐棤鎵瑰噯绔犵殑瀹℃牳绋跨敤浜庢壒鍑嗗悗閫�鍥炰慨鏀广�� */
+    private void prepareApprovalCopies(InsReport report) {
+        String primarySource = getPrimaryReportUrl(report);
+        String inspectionSource = report.getInspectionUrl();
+        report.setReviewUrl(primarySource);
+        report.setReviewInspectionUrl(inspectionSource);
+        report.setUrlS(copyReportForApproval(primarySource));
+        if (StringUtils.isNotBlank(inspectionSource)) {
+            report.setInspectionUrl(copyReportForApproval(inspectionSource));
+        }
+    }
+
+    private String copyReportForApproval(String sourceUrl) {
+        try {
+            Path source = Paths.get(sourceUrl.replace("/word", wordUrl));
+            if (!Files.exists(source)) {
+                throw new ErrorException("寰呮壒鍑嗘姤鍛婃枃浠朵笉瀛樺湪");
+            }
+            String fileName = "approved-" + UUID.randomUUID() + ".docx";
+            Path target = Paths.get(wordUrl, fileName);
+            Files.createDirectories(target.getParent());
+            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+            return "/word/" + fileName;
+        } catch (ErrorException e) {
+            throw e;
+        } catch (Exception e) {
+            log.error("鍒涘缓鎶ュ憡鎵瑰噯鍓湰澶辫触: {}", sourceUrl, e);
+            throw new ErrorException("鍒涘缓鎶ュ憡鎵瑰噯鍓湰澶辫触");
+        }
+    }
+
+    private void refreshTemporaryPreviews(InsReport report) {
+        String primaryPdf = wordToPdfTemp(getPrimaryReportUrl(report).replace("/word", wordUrl));
+        if (StringUtils.isBlank(primaryPdf)) {
+            throw new ErrorException("妫�娴嬫姤鍛婇瑙堢敓鎴愬け璐�");
+        }
+        report.setTempUrlPdf("/word/" + primaryPdf);
+        if (StringUtils.isNotBlank(report.getInspectionUrl())) {
+            String inspectionPdf = wordToPdfTemp(report.getInspectionUrl().replace("/word", wordUrl));
+            if (StringUtils.isBlank(inspectionPdf)) {
+                throw new ErrorException("妫�楠屾姤鍛婇瑙堢敓鎴愬け璐�");
+            }
+            report.setInspectionTempUrlPdf("/word/" + inspectionPdf);
+        }
+    }
+
+    @Override
+    public String prepareEditedReportPreview(String absoluteDocxPath) {
+        String pdfName = wordToPdfTemp(absoluteDocxPath);
+        if (StringUtils.isBlank(pdfName)) {
+            throw new ErrorException("鎶ュ憡棰勮鐢熸垚澶辫触");
+        }
+        return "/word/" + pdfName;
+    }
+
     private void writeMarksToReportFiles(InsReport report, Map<String, Object> marks) {
         for (String reportUrl : getApprovalReportUrls(report)) {
             wordInsertUrl(marks, reportUrl.replace("/word", wordUrl));
@@ -804,7 +894,12 @@
             throw new ErrorException("鎶ュ憡鏂囦欢涓嶅瓨鍦紝璇疯仈绯荤鐞嗗憳");
         }
         try {
-            String filename = file.getFileName().toString();
+            // 鐗╃悊鏂囦欢鍙兘鏄� reviewed/edited UUID锛涘鐢ㄦ埛濮嬬粓浣跨敤涓氬姟鎶ュ憡缂栧彿銆�
+            String reportNumber = StringUtils.isBlank(report.getCode()) ? "鎶ュ憡" : report.getCode();
+            reportNumber = reportNumber.replaceAll("[\\\\/:*?\"<>|\\p{Cntrl}]", "-").trim();
+            String suffix = StringUtils.isNotBlank(report.getInspectionUrl())
+                    ? (Objects.equals(reportType, INSPECTION_REPORT) ? "-妫�楠屾姤鍛�" : "-妫�娴嬫姤鍛�") : "";
+            String filename = reportNumber + suffix + ".docx";
             String encodedName = URLEncoder.encode(filename, "UTF-8").replace("+", "%20");
             response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
             response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedName);
@@ -824,6 +919,82 @@
             log.error("涓嬭浇鎶ュ憡澶辫触锛宺eportId={}", id, e);
             throw new ErrorException("鎶ュ憡涓嬭浇澶辫触");
         }
+    }
+
+    @Override
+    public void preview(Integer id, Integer reportType, Integer createOrderUser, HttpServletResponse response) {
+        int type = reportType == null ? DETECTION_REPORT : reportType;
+        if (id == null || (type != DETECTION_REPORT && type != INSPECTION_REPORT)) {
+            throw new ErrorException("鎶ュ憡鎴栨姤鍛婄被鍨嬩笉姝g‘");
+        }
+        InsReport report = insReportMapper.selectDownloadableReport(id, createOrderUser);
+        if (report == null) {
+            throw new ErrorException("鎶ュ憡涓嶅瓨鍦ㄣ�佸皻鏈敓鎴愭垨鏃犳潈鏌ョ湅");
+        }
+        String sourceUrl = type == INSPECTION_REPORT ? report.getInspectionUrl() : getPrimaryReportUrl(report);
+        if (StringUtils.isBlank(sourceUrl)) {
+            throw new ErrorException("鎶ュ憡鏂囦欢灏氭湭鐢熸垚");
+        }
+        try {
+            Path source = resolvePreviewFile(sourceUrl);
+            Path pdf;
+            if (Objects.equals(report.getIsRatify(), 1)) {
+                // 宸叉壒鍑嗘姤鍛婂繀椤讳娇鐢ㄦ壒鍑嗘椂鐢熸垚鐨� PDF锛屼繚鐣� PDF 涓撶敤鐨� MA 绔犲拰楠戠紳绔犮��
+                // inspectionTempUrlPdf 鍙兘浠嶆寚鍚戝鏍搁樁娈电殑涓存椂绋匡紝涓嶈兘浣滀负鏈夌珷鎶ュ憡杩斿洖銆�
+                pdf = resolvePreviewFile(sourceUrl.replaceFirst("(?i)\\.docx?$", ".pdf"));
+                if (pdf == null) {
+                    throw new ErrorException("鏈夌珷鎶ュ憡 PDF 涓嶅瓨鍦紝璇烽噸鏂版壒鍑嗙敓鎴�");
+                }
+            } else {
+                pdf = resolvePreviewFile(type == INSPECTION_REPORT
+                        ? report.getInspectionTempUrlPdf() : report.getTempUrlPdf());
+                if (source == null) throw new ErrorException("Word 鎶ュ憡鏂囦欢涓嶅瓨鍦�");
+                if (pdf == null || Files.getLastModifiedTime(pdf).compareTo(Files.getLastModifiedTime(source)) < 0) {
+                    // 缂哄皯棰勮鎴� Word 鏇存柊鍚庡啀杞崲锛涘悓涓�鐗堟湰閲嶅鏌ョ湅澶嶇敤缂撳瓨锛屼笉鏀瑰鎵规暟鎹��
+                    Path directory = Paths.get(wordUrl).toAbsolutePath().normalize().resolve("preview");
+                    Files.createDirectories(directory);
+                    String version = source + ":" + Files.size(source) + ":" + Files.getLastModifiedTime(source);
+                    String name = UUID.nameUUIDFromBytes(version.getBytes(java.nio.charset.StandardCharsets.UTF_8)) + ".pdf";
+                    pdf = directory.resolve(name);
+                    if (!Files.isRegularFile(pdf)) {
+                        Path temporary = Files.createTempFile(directory, "report-", ".pdf");
+                        try {
+                            if (wordToPdf(source.toString(), temporary.toString()) == null) {
+                                throw new ErrorException("鎶ュ憡杞� PDF 澶辫触锛岃鑱旂郴绠$悊鍛�");
+                            }
+                            Files.move(temporary, pdf, StandardCopyOption.REPLACE_EXISTING);
+                        } finally {
+                            Files.deleteIfExists(temporary);
+                        }
+                    }
+                }
+            }
+            String filename = (StringUtils.isBlank(report.getCode()) ? "鎶ュ憡" : report.getCode())
+                    .replaceAll("[\\\\/:*?\"<>|\\p{Cntrl}]", "-")
+                    + (type == INSPECTION_REPORT ? "-妫�楠屾姤鍛�.pdf" : "-妫�娴嬫姤鍛�.pdf");
+            response.setContentType("application/pdf");
+            response.setHeader("Content-Disposition", "inline; filename*=UTF-8''"
+                    + URLEncoder.encode(filename, "UTF-8").replace("+", "%20"));
+            response.setHeader("Cache-Control", "no-store");
+            response.setContentLengthLong(Files.size(pdf));
+            Files.copy(pdf, response.getOutputStream());
+        } catch (IOException e) {
+            log.error("鎶ュ憡棰勮澶辫触锛宺eportId={}", id, e);
+            throw new ErrorException("鎶ュ憡棰勮澶辫触锛岃鑱旂郴绠$悊鍛�");
+        }
+    }
+
+    /** 鍙鍙栨姤鍛婄洰褰曞唴鐨勬枃浠讹紝缂哄け鏂囦欢浜ょ敱璋冪敤鏂瑰鐞嗐�� */
+    private Path resolvePreviewFile(String url) throws IOException {
+        if (StringUtils.isBlank(url)) return null;
+        String path = url.replace('\\', '/');
+        if (!path.startsWith("/word/")) throw new ErrorException("鎶ュ憡鏂囦欢鍦板潃涓嶆纭�");
+        Path root = Paths.get(wordUrl).toAbsolutePath().normalize();
+        Path file = root.resolve(path.substring("/word/".length())).normalize();
+        if (!file.startsWith(root)) throw new ErrorException("鎶ュ憡鏂囦欢鍦板潃涓嶆纭�");
+        if (!Files.isRegularFile(file)) return null;
+        if (!file.toRealPath().startsWith(root.toRealPath())) throw new ErrorException("鎶ュ憡鏂囦欢鍦板潃涓嶆纭�");
+        return file;
     }
 
     //鎵归噺涓婁紶
@@ -1193,38 +1364,172 @@
         return unqualifiedCount;
     }
 
-    /**
-     * 閫�鍥炲埌妫�楠屼换鍔�
-     * @param id
-     * @return
-     */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public boolean sendBackTask(Integer id) {
-        InsReport report = insReportMapper.selectById(id);
+    public boolean sendBackTask(Integer id, String target, String reason) {
+        if (id == null || (!RETURN_TO_INSPECTION_TASK.equals(target)
+                && !RETURN_TO_REPORT_REVIEW.equals(target))) {
+            throw new ErrorException("閫�鍥炲弬鏁颁笉姝g‘");
+        }
+        if (StringUtils.isBlank(reason)) {
+            throw new ErrorException("璇疯緭鍏ラ��鍥炲師鍥�");
+        }
+
+        InsReport report = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
+                .eq(InsReport::getId, id)
+                .last("FOR UPDATE"));
         if (report == null || report.getInsOrderId() == null) {
             throw new ErrorException("鎶ュ憡涓嶅瓨鍦ㄦ垨鏈叧鑱旀楠屽崟");
         }
-
-        // 鎶ュ憡鐢辫鍗曚笅鍚勮瘯楠屽鍏卞悓褰㈡垚锛涢��鍥炴椂鍏ㄩ儴鎭㈠涓哄緟澶嶆牳锛岄伩鍏嶅彧闅忔満閫�鍥炰竴涓瘯楠屽銆�
-        insOrderStateMapper.update(null, Wrappers.<InsOrderState>lambdaUpdate()
-                .eq(InsOrderState::getInsOrderId, report.getInsOrderId())
-                .set(InsOrderState::getInsState, 4));
-
-        InsSampleUser sampleUser = insSampleUserMapper.selectOne(Wrappers.<InsSampleUser>lambdaQuery()
-                .eq(InsSampleUser::getInsSampleId, report.getInsOrderId())
-                .orderByDesc(InsSampleUser::getId)
-                .last("limit 1"));
-        if (sampleUser != null) {
-            insSampleUserMapper.deleteById(sampleUser.getId());
+        if (!Objects.equals(report.getIsPass(), 1)) {
+            throw new ErrorException("鎶ュ憡宸查��鍑烘姤鍛婃祦绋嬶紝璇峰嬁閲嶅閫�鍥�");
         }
 
-        // 淇敼鎶ュ憡琛屼负鏈樉绀�
+        LocalDateTime returnTime = LocalDateTime.now();
+        recordReportReturn(report, target, reason, returnTime);
+
+        if (RETURN_TO_REPORT_REVIEW.equals(target)) {
+            if (!Objects.equals(report.getIsRatify(), 1)) {
+                throw new ErrorException("鍙湁宸叉壒鍑嗘姤鍛婂彲浠ラ��鍥炲埌鎶ュ憡瀹℃牳");
+            }
+            String reviewUrl = report.getReviewUrl();
+            String reviewInspectionUrl = report.getReviewInspectionUrl();
+            if (StringUtils.isBlank(reviewUrl)) {
+                reviewUrl = prepareLegacyApprovedReportForReview(report,
+                        StringUtils.isNotBlank(report.getUrlS()) ? report.getUrlS() : report.getUrl());
+                if (StringUtils.isNotBlank(report.getInspectionUrl())) {
+                    reviewInspectionUrl = prepareLegacyApprovedReportForReview(report, report.getInspectionUrl());
+                }
+            }
+            int affected = insReportMapper.update(null, Wrappers.<InsReport>lambdaUpdate()
+                    .eq(InsReport::getId, id)
+                    .eq(InsReport::getIsRatify, 1)
+                    .set(InsReport::getState, 1)
+                    .set(InsReport::getIsExamine, RETURNED_STATUS)
+                    .set(InsReport::getExamineTime, returnTime)
+                    .set(InsReport::getExamineTell, reason)
+                    .set(InsReport::getIsRatify, RETURNED_STATUS)
+                    .set(InsReport::getRatifyTime, returnTime)
+                    .set(InsReport::getRatifyTell, reason)
+                    .set(InsReport::getUrlS, Objects.equals(reviewUrl, report.getUrl()) ? null : reviewUrl)
+                    .set(StringUtils.isNotBlank(reviewInspectionUrl), InsReport::getInspectionUrl,
+                            reviewInspectionUrl)
+                    .set(InsReport::getReviewUrl, null)
+                    .set(InsReport::getReviewInspectionUrl, null)
+                    .set(InsReport::getTempUrlPdf, null)
+                    .set(InsReport::getInspectionTempUrlPdf, null));
+            if (affected != 1) {
+                throw new ErrorException("鎶ュ憡鐘舵�佸凡鍙樺寲锛岃鍒锋柊鍚庨噸璇�");
+            }
+            expireReportEditSessions(id);
+            return true;
+        }
+
+        if (!Objects.equals(report.getState(), 1) && !Objects.equals(report.getIsRatify(), 1)) {
+            throw new ErrorException("褰撳墠鎶ュ憡涓嶅湪瀹℃牳鎴栧凡鎵瑰噯鐘舵�侊紝涓嶈兘閫�鍥炴楠屼换鍔�");
+        }
+
+        InsOrder order = insOrderMapper.selectById(report.getInsOrderId());
+        if (order == null) {
+            throw new ErrorException("鎶ュ憡鍏宠仈鐨勬楠屽崟涓嶅瓨鍦�");
+        }
+        boolean hadApproval = report.getIsRatify() != null;
+
+        // 鎭㈠璁㈠崟涓荤姸鎬侊紝鍚﹀垯妫�楠屼换鍔℃煡璇㈣姹� io.state=1 鏃朵粛鏃犳硶鎵惧埌璇ヤ换鍔°��
+        insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
+                .eq(InsOrder::getId, report.getInsOrderId())
+                .set(InsOrder::getState, 1)
+                .set(InsOrder::getInsState, 4));
+
+        // 鏁翠唤鎶ュ憡鐢辫鍗曚笅鍚勮瘯楠屽鍏卞悓褰㈡垚锛岄��鍥炲悗鍚勬楠屽鍧囧洖鍒板彲淇敼銆侀噸鏂版彁浜ゅ鏍哥殑鐘舵�併��
+        insOrderStateMapper.update(null, Wrappers.<InsOrderState>lambdaUpdate()
+                .eq(InsOrderState::getInsOrderId, report.getInsOrderId())
+                .set(InsOrderState::getInsState, 4)
+                .set(InsOrderState::getVerifyUser, null)
+                .set(InsOrderState::getVerifyTell, reason));
+
+        // 鍙挙閿�澶嶆牳浜轰换鍔★紝淇濈暀鍚勬楠屽鍘熸楠屼汉锛岄伩鍏嶉��鍥炲悗浠诲姟鏃犱汉鍙銆�
+        insSampleUserMapper.delete(Wrappers.<InsSampleUser>lambdaQuery()
+                .eq(InsSampleUser::getInsSampleId, report.getInsOrderId())
+                .eq(InsSampleUser::getState, 1));
+
+        // 鎶ュ憡鏆傛椂閫�鍑虹紪鍒跺垪琛ㄣ�傚師濮嬫暟鎹鏍搁�氳繃鍚庯紝鐜版湁娴佺▼浼氭仮澶嶆姤鍛婂苟閲嶆柊鎻愪氦瀹℃牳銆�
         insReportMapper.update(null, Wrappers.<InsReport>lambdaUpdate()
                 .eq(InsReport::getId, id)
-                .set(InsReport::getIsPass, 0));
+                .set(InsReport::getIsPass, 0)
+                .set(InsReport::getState, 0)
+                .set(InsReport::getIsExamine, RETURNED_STATUS)
+                .set(InsReport::getExamineTime, returnTime)
+                .set(InsReport::getExamineTell, reason)
+                .set(InsReport::getIsRatify, hadApproval ? RETURNED_STATUS : null)
+                .set(InsReport::getRatifyTime, hadApproval ? returnTime : null)
+                .set(InsReport::getRatifyTell, reason)
+                .set(InsReport::getUrlS, null)
+                .set(InsReport::getReviewUrl, null)
+                .set(InsReport::getReviewInspectionUrl, null)
+                .set(InsReport::getTempUrlPdf, null)
+                .set(InsReport::getInspectionTempUrlPdf, null));
 
-        return false;
+        expireReportEditSessions(id);
+        return true;
+    }
+
+    private String prepareLegacyApprovedReportForReview(InsReport report, String approvedUrl) {
+        if (StringUtils.isBlank(approvedUrl)) {
+            throw new ErrorException("鍘嗗彶鎵瑰噯鎶ュ憡鏂囦欢涓嶅瓨鍦紝鏃犳硶閫�鍥炴姤鍛婂鏍�");
+        }
+        try {
+            Path source = Paths.get(approvedUrl.replace("/word", wordUrl));
+            String fileName = "returned-" + UUID.randomUUID() + ".docx";
+            Path target = Paths.get(wordUrl, fileName);
+            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+
+            ReportSealLayoutUtil.restoreForReview(target.toString());
+            return "/word/" + fileName;
+        } catch (Exception e) {
+            log.error("鍘嗗彶鎵瑰噯鎶ュ憡鎭㈠瀹℃牳绋垮け璐�: {}", approvedUrl, e);
+            throw new ErrorException("鍘嗗彶鎵瑰噯鎶ュ憡鏃犳硶娓呴櫎鏃ф壒鍑嗕俊鎭紝璇烽��鍥炴楠屼换鍔¢噸鏂扮敓鎴�");
+        }
+    }
+
+    private void recordReportReturn(InsReport report, String target, String reason,
+                                    LocalDateTime returnTime) {
+        recordReportReturn(report,
+                Objects.equals(report.getIsRatify(), 1) ? "APPROVED" : "REPORT_REVIEW",
+                target, reason, returnTime);
+    }
+
+    private void recordReportReturn(InsReport report, String fromStage, String target, String reason,
+                                    LocalDateTime returnTime) {
+        InsReportReturnRecord record = new InsReportReturnRecord();
+        record.setReportId(report.getId());
+        record.setInsOrderId(report.getInsOrderId());
+        record.setFromStage(fromStage);
+        record.setTargetStage(target);
+        record.setReturnReason(reason.trim());
+        record.setState(report.getState());
+        record.setIsExamine(report.getIsExamine());
+        record.setExamineTime(report.getExamineTime());
+        record.setIsRatify(report.getIsRatify());
+        record.setRatifyTime(report.getRatifyTime());
+        record.setReportUrl(StringUtils.isNotBlank(report.getUrlS()) ? report.getUrlS() : report.getUrl());
+        record.setInspectionUrl(report.getInspectionUrl());
+        record.setTempUrlPdf(report.getTempUrlPdf());
+        record.setInspectionTempUrlPdf(report.getInspectionTempUrlPdf());
+        record.setOperatorId(SecurityUtils.getUserId().intValue());
+        record.setCreateTime(returnTime);
+        if (insReportReturnRecordMapper.insert(record) != 1) {
+            throw new ErrorException("鎶ュ憡閫�鍥炶褰曚繚瀛樺け璐�");
+        }
+    }
+
+    private void expireReportEditSessions(Integer reportId) {
+        insReportEditSessionMapper.update(null, Wrappers.<InsReportEditSession>lambdaUpdate()
+                .eq(InsReportEditSession::getReportId, reportId)
+                .in(InsReportEditSession::getStatus, "EDITING", "SAVED", "FAILED", "SAVE_REQUESTED")
+                .set(InsReportEditSession::getStatus, "EXPIRED")
+                .set(InsReportEditSession::getMessage, "鎶ュ憡宸查��鍥�")
+                .set(InsReportEditSession::getUpdateTime, LocalDateTime.now()));
     }
 
     /**

--
Gitblit v1.9.3