liding
2026-10-24 f8c024b1c1de318a4de485e048d1044cd6dcaa53
cnas-process/src/main/java/com/ruoyi/process/service/impl/ProcessMethodSearchNewServiceImpl.java
@@ -20,10 +20,13 @@
import com.ruoyi.process.dto.ProcessMethodSearchNewBackupsDto;
import com.ruoyi.process.mapper.ProcessMethodSearchNewArchivedMapper;
import com.ruoyi.process.mapper.ProcessMethodSearchNewBackupsMapper;
import com.ruoyi.process.mapper.ProcessMethodSearchNewFileSeqMapper;
import com.ruoyi.process.mapper.ProcessMethodSearchNewMapper;
import com.ruoyi.process.mapper.ProcessMethodSearchNewHistoryMapper;
import com.ruoyi.process.pojo.ProcessMethodSearchNew;
import com.ruoyi.process.pojo.ProcessMethodSearchNewArchived;
import com.ruoyi.process.pojo.ProcessMethodSearchNewBackups;
import com.ruoyi.process.pojo.ProcessMethodSearchNewHistory;
import com.ruoyi.process.service.ProcessMethodSearchNewBackupsService;
import com.ruoyi.process.service.ProcessMethodSearchNewService;
import org.springframework.beans.BeanUtils;
@@ -40,6 +43,8 @@
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@@ -55,12 +60,19 @@
@Transactional(rollbackFor = Exception.class)
public class ProcessMethodSearchNewServiceImpl extends ServiceImpl<ProcessMethodSearchNewMapper, ProcessMethodSearchNew> implements ProcessMethodSearchNewService {
    private static final ZoneId CHINA_ZONE = ZoneId.of("Asia/Shanghai");
    private static final DateTimeFormatter FILE_DATE = DateTimeFormatter.BASIC_ISO_DATE;
    @Resource
    private ProcessMethodSearchNewArchivedMapper processMethodSearchNewArchivedMapper;
    @Resource
    private ProcessMethodSearchNewBackupsService processMethodSearchNewBackupsService;
    @Resource
    private ProcessMethodSearchNewBackupsMapper processMethodSearchNewBackupsMapper;
    @Resource
    private ProcessMethodSearchNewHistoryMapper processMethodSearchNewHistoryMapper;
    @Resource
    private ProcessMethodSearchNewFileSeqMapper processMethodSearchNewFileSeqMapper;
    /**
     * 新增标准查新
@@ -71,12 +83,86 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addMethodSearchNew(List<ProcessMethodSearchNew> processMethodSearchNewList) {
        for (ProcessMethodSearchNew processMethodSearchNew : processMethodSearchNewList) {
            processMethodSearchNew.setIsNewStandard(1);
        if (processMethodSearchNewList == null || processMethodSearchNewList.isEmpty()) {
            throw new ErrorException("请填写标准查新记录");
        }
        // 新增
        this.saveBatch(processMethodSearchNewList);
        Integer userId = SecurityUtils.getUserId().intValue();
        for (ProcessMethodSearchNew processMethodSearchNew : processMethodSearchNewList) {
            validateSearchRecord(processMethodSearchNew);
            processMethodSearchNew.setIsNewStandard(1);
            processMethodSearchNew.setIsAutoArchived(0);
            processMethodSearchNew.setStandardMethodId(null);
            processMethodSearchNew.setCurrentAutoStandardId(null);
            processMethodSearchNew.setAutoArchivedTime(null);
            processMethodSearchNew.setSearchNewUserId(userId);
            processMethodSearchNew.setRemark(toLegacyRemark(processMethodSearchNew.getSearchNewResult()));
            if (!Integer.valueOf(3).equals(processMethodSearchNew.getSearchNewSource())) {
                processMethodSearchNew.setSearchNewWebsite(null);
            }
            this.save(processMethodSearchNew);
            insertHistory(processMethodSearchNew, userId);
            handleSearchResult(processMethodSearchNew);
        }
        return true;
    }
    @Override
    public boolean updateMethodSearchNew(ProcessMethodSearchNew processMethodSearchNew) {
        ProcessMethodSearchNew old = getById(processMethodSearchNew.getMethodSearchNewId());
        if (old == null) {
            throw new ErrorException("标准查新记录不存在");
        }
        if (Integer.valueOf(1).equals(old.getIsAutoArchived())) {
            throw new ErrorException("已归档标准不能继续查新");
        }
        processMethodSearchNew.setMethodName(old.getMethodName());
        processMethodSearchNew.setStandardNo(old.getStandardNo());
        processMethodSearchNew.setFileNo(old.getFileNo());
        processMethodSearchNew.setStandardMethodId(old.getStandardMethodId());
        validateSearchRecord(processMethodSearchNew);
        Integer userId = SecurityUtils.getUserId().intValue();
        boolean updated = update(Wrappers.<ProcessMethodSearchNew>lambdaUpdate()
                .eq(ProcessMethodSearchNew::getMethodSearchNewId, old.getMethodSearchNewId())
                .set(ProcessMethodSearchNew::getNewMethodName, processMethodSearchNew.getNewMethodName())
                .set(ProcessMethodSearchNew::getNewStandardNo, processMethodSearchNew.getNewStandardNo())
                .set(ProcessMethodSearchNew::getSearchNewSource, processMethodSearchNew.getSearchNewSource())
                .set(ProcessMethodSearchNew::getSearchNewTime, processMethodSearchNew.getSearchNewTime())
                .set(ProcessMethodSearchNew::getNextSearchDatePersisted,
                        processMethodSearchNew.getNextSearchDatePersisted())
                .set(ProcessMethodSearchNew::getSearchNewResult, processMethodSearchNew.getSearchNewResult())
                .set(ProcessMethodSearchNew::getSearchNewUserId, userId)
                .set(ProcessMethodSearchNew::getSearchNewWebsite,
                        Integer.valueOf(3).equals(processMethodSearchNew.getSearchNewSource())
                                ? processMethodSearchNew.getSearchNewWebsite() : null)
                .set(ProcessMethodSearchNew::getRemark, toLegacyRemark(processMethodSearchNew.getSearchNewResult()))
                .set(ProcessMethodSearchNew::getIsNewStandard, 1));
        if (updated) {
            ProcessMethodSearchNew latest = getById(old.getMethodSearchNewId());
            insertHistory(latest, userId);
            handleSearchResult(latest);
        }
        return updated;
    }
    @Override
    public boolean delMethodSearchNew(Integer methodSearchNewId) {
        if (methodSearchNewId == null) {
            throw new ErrorException("缺少标准查新记录id");
        }
        ProcessMethodSearchNew old = getById(methodSearchNewId);
        if (old == null) {
            throw new ErrorException("标准查新记录不存在");
        }
        if (Integer.valueOf(1).equals(old.getIsAutoArchived())) {
            throw new ErrorException("已归档标准不能删除");
        }
        Long historyCount = processMethodSearchNewHistoryMapper.selectCount(
                Wrappers.<ProcessMethodSearchNewHistory>lambdaQuery()
                        .eq(ProcessMethodSearchNewHistory::getMethodSearchNewId, methodSearchNewId));
        if (historyCount != null && historyCount > 0) {
            throw new ErrorException("该标准已有查新记录,不允许删除");
        }
        return removeById(methodSearchNewId);
    }
    /**
@@ -91,7 +177,152 @@
        String endDate = processMethodSearchNew.getEndDate();
        processMethodSearchNew.setBeginDate(null);
        processMethodSearchNew.setEndDate(null);
        return baseMapper.pageMethodSearchNew(page, QueryWrappers.queryWrappers(processMethodSearchNew), beginDate, endDate);
        IPage<ProcessMethodSearchNew> result = baseMapper.pageMethodSearchNew(
                page, QueryWrappers.queryWrappers(processMethodSearchNew), beginDate, endDate);
        LocalDate today = LocalDate.now(CHINA_ZONE);
        result.getRecords().forEach(item -> {
            LocalDate nextDate = item.getNextSearchDate();
            if (nextDate == null) {
                item.setSearchDueStatus("待首次查新");
            } else if (today.isAfter(nextDate)) {
                item.setSearchDueStatus("已逾期");
            } else if (today.isEqual(nextDate)) {
                item.setSearchDueStatus("今日到期");
            } else {
                item.setSearchDueStatus("未到期");
            }
        });
        return result;
    }
    @Override
    public List<ProcessMethodSearchNewHistory> listSearchNewHistory(Integer methodSearchNewId) {
        if (methodSearchNewId == null) {
            throw new ErrorException("缺少标准查新记录id");
        }
        if (getById(methodSearchNewId) == null) {
            throw new ErrorException("标准查新记录不存在");
        }
        return processMethodSearchNewHistoryMapper.selectByMainId(methodSearchNewId);
    }
    @Override
    public IPage<ProcessMethodSearchNewHistory> pageSearchNewHistory(Page<ProcessMethodSearchNewHistory> page,
                                                                      String standardNo) {
        return processMethodSearchNewHistoryMapper.pageAll(page,
                StringUtils.isBlank(standardNo) ? null : standardNo.trim());
    }
    private void validateSearchRecord(ProcessMethodSearchNew row) {
        if (row == null) {
            throw new ErrorException("请填写标准查新记录");
        }
        if (StringUtils.isBlank(row.getMethodName()) || StringUtils.isBlank(row.getStandardNo())
                || StringUtils.isBlank(row.getFileNo())) {
            throw new ErrorException("请填写标准名称、标准号和文件编号");
        }
        if (row.getSearchNewTime() == null) {
            throw new ErrorException("请选择查新日期");
        }
        row.setSearchNewTime(row.getSearchNewTime().toLocalDate().atStartOfDay());
        if (!"现行有效".equals(row.getSearchNewResult())
                && !"已修订/有新版本替代".equals(row.getSearchNewResult())
                && !"废止(无替代)".equals(row.getSearchNewResult())
                && !"即将实施".equals(row.getSearchNewResult())) {
            throw new ErrorException("请选择有效的查新结果");
        }
        Integer source = row.getSearchNewSource();
        if (source == null || source < 3 || source > 8) {
            throw new ErrorException("请选择有效的查新记录来源");
        }
        if ("已修订/有新版本替代".equals(row.getSearchNewResult())
                && (StringUtils.isBlank(row.getNewMethodName()) || StringUtils.isBlank(row.getNewStandardNo()))) {
            throw new ErrorException("查新结果为已修订/有新版本替代时,请填写新标准名称和新标准号");
        }
        if (!"已修订/有新版本替代".equals(row.getSearchNewResult())) {
            row.setNewMethodName(null);
            row.setNewStandardNo(null);
        }
        if (!Integer.valueOf(3).equals(source)) {
            row.setSearchNewWebsite(null);
        }
        if ("已修订/有新版本替代".equals(row.getSearchNewResult())
                || "废止(无替代)".equals(row.getSearchNewResult())) {
            row.setNextSearchDate(null);
        } else if (row.getNextSearchDate() == null) {
            row.setNextSearchDate(row.getSearchNewTime().toLocalDate().plusMonths(3));
        }
        row.setNextSearchDatePersisted(row.getNextSearchDate());
    }
    private Integer toLegacyRemark(String result) {
        if ("废止(无替代)".equals(result)) return 0;
        if ("已修订/有新版本替代".equals(result)) return 1;
        return null;
    }
    private void insertHistory(ProcessMethodSearchNew row, Integer userId) {
        ProcessMethodSearchNewHistory history = new ProcessMethodSearchNewHistory();
        history.setMethodSearchNewId(row.getMethodSearchNewId());
        history.setStandardMethodId(row.getStandardMethodId());
        history.setMethodName(row.getMethodName());
        history.setStandardNo(row.getStandardNo());
        history.setFileNo(row.getFileNo());
        history.setSearchNewDate(row.getSearchNewTime().toLocalDate());
        history.setNextSearchDate(row.getNextSearchDatePersisted());
        history.setSearchNewResult(row.getSearchNewResult());
        history.setSearchNewSource(row.getSearchNewSource());
        history.setSearchNewWebsite(row.getSearchNewWebsite());
        history.setNewMethodName(row.getNewMethodName());
        history.setNewStandardNo(row.getNewStandardNo());
        history.setSearchNewUserId(userId);
        history.setCreateTime(LocalDateTime.now(CHINA_ZONE));
        processMethodSearchNewHistoryMapper.insert(history);
    }
    /** 旧标准只保留在查新记录;有新版时创建新的主列表记录。 */
    private void handleSearchResult(ProcessMethodSearchNew oldStandard) {
        String result = oldStandard.getSearchNewResult();
        if (!"废止(无替代)".equals(result) && !"已修订/有新版本替代".equals(result)) {
            return;
        }
        LocalDateTime now = LocalDateTime.now(CHINA_ZONE);
        update(Wrappers.<ProcessMethodSearchNew>lambdaUpdate()
                .eq(ProcessMethodSearchNew::getMethodSearchNewId, oldStandard.getMethodSearchNewId())
                .set(ProcessMethodSearchNew::getIsNewStandard, 0)
                .set(ProcessMethodSearchNew::getIsAutoArchived, 1)
                .set(ProcessMethodSearchNew::getCurrentAutoStandardId, null)
                .set(ProcessMethodSearchNew::getAutoArchivedTime, now));
        if (!"已修订/有新版本替代".equals(result)) {
            return;
        }
        if (count(Wrappers.<ProcessMethodSearchNew>lambdaQuery()
                .eq(ProcessMethodSearchNew::getStandardNo, oldStandard.getNewStandardNo())
                .eq(ProcessMethodSearchNew::getIsAutoArchived, 0)) > 0) {
            return;
        }
        ProcessMethodSearchNew replacement = new ProcessMethodSearchNew();
        replacement.setMethodName(oldStandard.getNewMethodName());
        replacement.setStandardNo(oldStandard.getNewStandardNo());
        replacement.setFileNo(nextFileNo(now.toLocalDate()));
        replacement.setIsNewStandard(1);
        replacement.setStandardMethodId(oldStandard.getStandardMethodId());
        replacement.setCurrentAutoStandardId(oldStandard.getCurrentAutoStandardId());
        replacement.setIsAutoArchived(0);
        save(replacement);
    }
    private String nextFileNo(LocalDate date) {
        String prefix = date.format(FILE_DATE);
        processMethodSearchNewFileSeqMapper.insertIfAbsent(date);
        Integer stored = processMethodSearchNewFileSeqMapper.selectForUpdate(date);
        Integer existing = processMethodSearchNewFileSeqMapper.selectMaxExisting(prefix);
        int next = Math.max(stored == null ? 0 : stored, existing == null ? 0 : existing) + 1;
        processMethodSearchNewFileSeqMapper.updateValue(date, next);
        return prefix + String.format("%03d", next);
    }
    /**
@@ -121,33 +352,40 @@
        for (ProcessMethodSearchNewBackups methodSearchNew : methodSearchNewBackups) {
            ProcessMethodSearchNewBackupsDto searchNewBackupsDto = new ProcessMethodSearchNewBackupsDto();
            BeanUtils.copyProperties(methodSearchNew, searchNewBackupsDto);
            // 是否是跟新标准
            if (methodSearchNew.getIsNewStandard().equals(1)) {
                searchNewBackupsDto.setIsNewStandardString("是");
            } else {
                searchNewBackupsDto.setIsNewStandardString("否");
            }
            // 备注
            if (methodSearchNew.getRemark() != null) {
                if (methodSearchNew.getRemark().equals(1)) {
                    searchNewBackupsDto.setRemarkString("替换");
                } else {
                    searchNewBackupsDto.setRemarkString("作废");
                }
            }
            switch (methodSearchNew.getSearchNewSource()) {
            searchNewBackupsDto.setSearchNewDateString(methodSearchNew.getSearchNewTime() == null
                    ? null : methodSearchNew.getSearchNewTime().format(timeFormatter));
            searchNewBackupsDto.setSearchNewResultString(methodSearchNew.getSearchNewResult());
            if (methodSearchNew.getSearchNewSource() != null) switch (methodSearchNew.getSearchNewSource()) {
                case 0:
                    searchNewBackupsDto.setStandardNet("√");
                    searchNewBackupsDto.setOther("√");
                    searchNewBackupsDto.setOtherWebsite("标准网(历史来源)");
                    break;
                case 1:
                    searchNewBackupsDto.setInformationOffices("√");
                    searchNewBackupsDto.setOther("√");
                    searchNewBackupsDto.setOtherWebsite("委托情报所(历史来源)");
                    break;
                case 2:
                    searchNewBackupsDto.setStandardBookstore("√");
                    searchNewBackupsDto.setOther("√");
                    searchNewBackupsDto.setOtherWebsite("标准书店(历史来源)");
                    break;
                case 4:
                    searchNewBackupsDto.setStandardizationAdministration("√");
                    break;
                case 5:
                    searchNewBackupsDto.setMarketRegulation("√");
                    break;
                case 6:
                    searchNewBackupsDto.setNationalStandardInfo("√");
                    break;
                case 7:
                    searchNewBackupsDto.setNationalStandardFullText("√");
                    break;
                case 8:
                    searchNewBackupsDto.setIndustryStandard("√");
                    break;
                case 3:
                    searchNewBackupsDto.setOther("√");
                    searchNewBackupsDto.setOtherWebsite(methodSearchNew.getSearchNewWebsite());
                    break;
            }
            searchNewBackupsDto.setIndex(index);
@@ -214,7 +452,7 @@
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode(
                    "原材料检测信息导出", "UTF-8");
                    "标准查新记录", "UTF-8");
            response.setHeader("Content-disposition",
                    "attachment;filename=" + fileName + ".xlsx");
        } catch (Exception e) {
@@ -257,37 +495,39 @@
            List<ProcessMethodSearchNew> collect = searchNewDtoList.stream().map(searchNewDto -> {
                ProcessMethodSearchNew searchNew = new ProcessMethodSearchNew();
                BeanUtils.copyProperties(searchNewDto, searchNew);
                // 是否是更新
                if (StringUtils.isNotBlank(searchNewDto.getIsNewStandardString())) {
                    if (searchNewDto.getIsNewStandardString().equals("是")) {
                        searchNew.setIsNewStandard(1);
                    } else {
                        searchNew.setIsNewStandard(0);
                    }
                if (StringUtils.isNotBlank(searchNewDto.getSearchNewDateString())) {
                    String dateText = searchNewDto.getSearchNewDateString().trim();
                    searchNew.setSearchNewTime(LocalDate.parse(dateText.substring(0, Math.min(10, dateText.length()))).atStartOfDay());
                }
                searchNew.setSearchNewResult(searchNewDto.getSearchNewResultString());
                int sourceCount = 0;
                if (StringUtils.isNotBlank(searchNewDto.getStandardizationAdministration())) sourceCount++;
                if (StringUtils.isNotBlank(searchNewDto.getMarketRegulation())) sourceCount++;
                if (StringUtils.isNotBlank(searchNewDto.getNationalStandardInfo())) sourceCount++;
                if (StringUtils.isNotBlank(searchNewDto.getNationalStandardFullText())) sourceCount++;
                if (StringUtils.isNotBlank(searchNewDto.getIndustryStandard())) sourceCount++;
                if (StringUtils.isNotBlank(searchNewDto.getOther())) sourceCount++;
                if (sourceCount != 1) {
                    throw new ErrorException("标准号" + searchNew.getStandardNo() + "必须且只能选择一个查新来源");
                }
                // 查新记录
                if (StringUtils.isNotBlank(searchNewDto.getStandardNet())) {
                    searchNew.setSearchNewSource(0);
                } else if (StringUtils.isNotBlank(searchNewDto.getInformationOffices())) {
                    searchNew.setSearchNewSource(1);
                } else if (StringUtils.isNotBlank(searchNewDto.getIsNewStandardString())) {
                    searchNew.setSearchNewSource(2);
                if (StringUtils.isNotBlank(searchNewDto.getStandardizationAdministration())) {
                    searchNew.setSearchNewSource(4);
                } else if (StringUtils.isNotBlank(searchNewDto.getMarketRegulation())) {
                    searchNew.setSearchNewSource(5);
                } else if (StringUtils.isNotBlank(searchNewDto.getNationalStandardInfo())) {
                    searchNew.setSearchNewSource(6);
                } else if (StringUtils.isNotBlank(searchNewDto.getNationalStandardFullText())) {
                    searchNew.setSearchNewSource(7);
                } else if (StringUtils.isNotBlank(searchNewDto.getIndustryStandard())) {
                    searchNew.setSearchNewSource(8);
                } else if (StringUtils.isNotBlank(searchNewDto.getOther())) {
                    searchNew.setSearchNewSource(3);
                    searchNew.setSearchNewWebsite(searchNewDto.getOtherWebsite());
                }
                // 备注
                if (StringUtils.isNotBlank(searchNewDto.getRemarkString())) {
                    if (searchNewDto.getRemarkString().equals("替换")) {
                        searchNew.setRemark(1);
                    } else if (searchNewDto.getRemarkString().equals("作废")) {
                        searchNew.setRemark(0);
                    }
                }
                return searchNew;
            }).collect(Collectors.toList());
            this.saveBatch(collect);
            addMethodSearchNew(collect);
        } catch (IOException e) {
            throw new RuntimeException(e);
@@ -309,12 +549,15 @@
        processMethodSearchNewArchivedMapper.insert(archived);
        // 查询所有的标准查新
        List<ProcessMethodSearchNew> searchNewList = this.list();
        List<ProcessMethodSearchNew> searchNewList = this.list(Wrappers.<ProcessMethodSearchNew>lambdaQuery()
                .eq(ProcessMethodSearchNew::getIsAutoArchived, 0));
        // 新增复制
        List<ProcessMethodSearchNewBackups> methodSearchNewBackups = searchNewList.stream().map(processMethodSearchNew -> {
            ProcessMethodSearchNewBackups backups = new ProcessMethodSearchNewBackups();
            BeanUtils.copyProperties(processMethodSearchNew, backups);
            backups.setNextSearchDate(processMethodSearchNew.getNextSearchDatePersisted());
            backups.setIsNewStandard(0);
            backups.setArchivedId(archived.getArchivedId());
            return backups;
        }).collect(Collectors.toList());