From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/impl/DmsWenjianBanbenServiceImpl.java |  369 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 369 insertions(+), 0 deletions(-)

diff --git a/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/impl/DmsWenjianBanbenServiceImpl.java b/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/impl/DmsWenjianBanbenServiceImpl.java
new file mode 100644
index 0000000..cd50e4b
--- /dev/null
+++ b/jnpf-dms/jnpf-dms-biz/src/main/java/jnpf/dmsService/impl/DmsWenjianBanbenServiceImpl.java
@@ -0,0 +1,369 @@
+package jnpf.dmsService.impl;
+
+import jnpf.base.UserInfo;
+import jnpf.dmsEntity.DmsWenjianBanbenKongzhiEntity;
+import jnpf.dmsEntity.DmsWenjianXinzengGuanliEntity;
+import jnpf.dmsEntity.DmsWenjianXinzengShenheEntity;
+import jnpf.dmsEntity.DmsWenjianXiudingShenheEntity;
+import jnpf.dmsEntity.DmsWenjianXiudingShenqingEntity;
+import jnpf.dmsEntity.wenjianbianhao.DmsFlowEventType;
+import jnpf.dmsMapper.DmsWenjianBanbenKongzhiMapper;
+import jnpf.dmsMapper.DmsWenjianXinzengGuanliMapper;
+import jnpf.dmsMapper.DmsWenjianXinzengShenheMapper;
+import jnpf.dmsMapper.DmsWenjianXiudingShenheMapper;
+import jnpf.dmsMapper.DmsWenjianXiudingShenqingMapper;
+import jnpf.dmsPermission.DmsCurrentIdentity;
+import jnpf.dmsService.DmsWenjianBanbenService;
+import jnpf.exception.DataException;
+import jnpf.util.RandomUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class DmsWenjianBanbenServiceImpl implements DmsWenjianBanbenService {
+
+    private static final int RUNNING = 1;
+    private static final int PASSED = 2;
+    private static final int EXCEPTION = 10;
+    private static final String EFFECTIVE = "effective";
+    private static final String NEW = "xinzeng";
+    private static final String REVISION = "xiuding";
+    private static final String NEW_SOURCE = "xinding";
+    private static final String UPGRADE = "shengji";
+    private static final String UNCHANGED = "wubianhua";
+
+    private final DmsCurrentIdentity identity;
+    private final DmsWenjianBanbenKongzhiMapper controlMapper;
+    private final DmsWenjianXinzengGuanliMapper newRequestMapper;
+    private final DmsWenjianXinzengShenheMapper newAuditMapper;
+    private final DmsWenjianXiudingShenqingMapper revisionRequestMapper;
+    private final DmsWenjianXiudingShenheMapper revisionAuditMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void syncNewAuditFlow(String flowId, String taskId, Integer flowState,
+                                 DmsFlowEventType eventType) throws DataException {
+        UserInfo user = identity.requireUser();
+        String tenantId = identity.tenantId(user);
+        String resolvedFlowId = requireText(flowId, "娴佺▼ID涓嶈兘涓虹┖");
+        String resolvedTaskId = requireText(taskId, "娴佺▼浠诲姟ID涓嶈兘涓虹┖");
+        requireEvent(eventType);
+
+        DmsWenjianXinzengShenheEntity audit = uniqueNewAudit(
+                newAuditMapper.selectByFlowForUpdate(tenantId, resolvedFlowId, resolvedTaskId));
+        verifyPersistedState(audit.getFlowState(), flowState);
+        if (!requiresVersionCheck(flowState)) {
+            return;
+        }
+        if (hasCompleteNewResult(audit)) {
+            return;
+        }
+
+        String requestId = requireText(audit.getShenqingdanId(), "鏂板瀹℃牳鍗曟湭鍏宠仈鏂板鐢宠");
+        DmsWenjianXinzengGuanliEntity request =
+                newRequestMapper.selectByIdForUpdate(tenantId, requestId);
+        validateNewRequest(request);
+
+        DmsWenjianBanbenKongzhiEntity control =
+                controlMapper.selectByFileForUpdate(tenantId, request.getId());
+        if (control != null) {
+            if (NEW.equals(control.getZuihouShengxiaoLeixing())
+                    && audit.getId().equals(control.getZuihouShengxiaoDanjuId())) {
+                if (flowState == PASSED) {
+                    writeNewAuditResult(audit, new Date());
+                }
+                return;
+            }
+            throw new DataException("璇ユ枃浠跺凡缁忓瓨鍦ㄦ寮忕増鏈紝涓嶈兘閲嶅鍒濆鍖�");
+        }
+        if (flowState != PASSED) {
+            return;
+        }
+
+        Date now = new Date();
+        DmsWenjianBanbenKongzhiEntity created = new DmsWenjianBanbenKongzhiEntity();
+        created.setId(RandomUtil.uuId());
+        created.setTenantId(tenantId);
+        created.setWenjianId(request.getId());
+        created.setBanbenXuhao(0);
+        created.setBiangengXuhao(0L);
+        created.setZuihouShengxiaoLeixing(NEW);
+        created.setZuihouShengxiaoDanjuId(audit.getId());
+        created.setBizStatus(EFFECTIVE);
+        created.setCreatorUserId(user.getUserId());
+        created.setCreatorTime(now);
+        requireSingleUpdate(controlMapper.insertControl(created), "鍒濆鍖栨枃浠舵寮忕増鏈け璐�");
+        writeNewAuditResult(audit, now);
+        log.info("鏂囦欢鏂板瀹℃牳鐢熸垚姝e紡鐗堟湰锛宎uditId={}, wenjianId={}, version=D(00)",
+                audit.getId(), request.getId());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void syncRevisionAuditFlow(String flowId, String taskId, Integer flowState,
+                                      DmsFlowEventType eventType) throws DataException {
+        UserInfo user = identity.requireUser();
+        String tenantId = identity.tenantId(user);
+        String resolvedFlowId = requireText(flowId, "娴佺▼ID涓嶈兘涓虹┖");
+        String resolvedTaskId = requireText(taskId, "娴佺▼浠诲姟ID涓嶈兘涓虹┖");
+        requireEvent(eventType);
+
+        DmsWenjianXiudingShenheEntity audit = uniqueRevisionAudit(
+                revisionAuditMapper.selectByFlowForUpdate(
+                        tenantId, resolvedFlowId, resolvedTaskId));
+        verifyPersistedState(audit.getFlowState(), flowState);
+        if (!requiresVersionCheck(flowState)) {
+            return;
+        }
+        if (hasCompleteRevisionResult(audit)) {
+            return;
+        }
+
+        String requestId = requireText(audit.getXiudingShenqingId(), "淇瀹℃牳鍗曟湭鍏宠仈淇鐢宠");
+        DmsWenjianXiudingShenqingEntity request =
+                revisionRequestMapper.selectByIdForUpdate(tenantId, requestId);
+        validateRevisionRequest(request);
+
+        DmsWenjianBanbenKongzhiEntity control = controlMapper.selectByFileForUpdate(
+                tenantId, request.getWenjianId());
+        validateControl(control);
+        verifySourceSnapshot(request, control);
+        validateChangeType(audit.getBiangengFangshi());
+        if (flowState != PASSED) {
+            return;
+        }
+
+        int expectedVersion = control.getBanbenXuhao();
+        long expectedChange = control.getBiangengXuhao();
+        int effectiveVersion = calculateEffectiveVersion(
+                expectedVersion, audit.getBiangengFangshi());
+        long effectiveChange;
+        try {
+            effectiveChange = Math.addExact(expectedChange, 1L);
+        } catch (ArithmeticException exception) {
+            throw new DataException("鏂囦欢鍙樻洿搴忓彿宸茶揪鍒颁笂闄�");
+        }
+
+        Date now = new Date();
+        control.setBanbenXuhao(effectiveVersion);
+        control.setBiangengXuhao(effectiveChange);
+        control.setZuihouShengxiaoLeixing(REVISION);
+        control.setZuihouShengxiaoDanjuId(audit.getId());
+        control.setBizStatus(EFFECTIVE);
+        control.setLastModifyUserId(user.getUserId());
+        control.setLastModifyTime(now);
+        requireSingleUpdate(controlMapper.advance(
+                control, expectedVersion, expectedChange), "鏇存柊鏂囦欢姝e紡鐗堟湰澶辫触");
+
+        audit.setShengxiaoBanbenXuhao(effectiveVersion);
+        audit.setShengxiaoBanbenhao(formatVersion(effectiveVersion));
+        audit.setShengxiaoBiangengXuhao(effectiveChange);
+        audit.setBanbenShengxiaoShijian(now);
+        requireSingleUpdate(revisionAuditMapper.updateEffectiveVersion(audit),
+                "鍥炲啓淇瀹℃牳鐢熸晥鐗堟湰澶辫触");
+        log.info("鏂囦欢淇瀹℃牳鐢熸垚姝e紡鐗堟湰锛宎uditId={}, wenjianId={}, version={}, changeSequence={}",
+                audit.getId(), request.getWenjianId(), audit.getShengxiaoBanbenhao(),
+                effectiveChange);
+    }
+
+    private void validateNewRequest(DmsWenjianXinzengGuanliEntity request)
+            throws DataException {
+        if (request == null) {
+            throw new DataException("鏈壘鍒版柊澧炲鏍稿崟鍏宠仈鐨勬柊澧炵敵璇�");
+        }
+        if (!Objects.equals(request.getFlowState(), PASSED)) {
+            throw new DataException("鍏宠仈鐨勬枃浠舵柊澧炵敵璇峰皻鏈鎵归�氳繃");
+        }
+        if (!NEW_SOURCE.equals(request.getXinxiuding())) {
+            throw new DataException("鍏宠仈璁板綍涓嶆槸鏂囦欢鏂拌鐢宠");
+        }
+        if (!Objects.equals(request.getBanbenXuhao(), 0)
+                || !formatVersion(0).equals(request.getBanbenhao())) {
+            throw new DataException("鏂囦欢鏂拌鐢宠鐨勫垵濮嬬増鏈繀椤讳负D(00)");
+        }
+    }
+
+    private void validateRevisionRequest(DmsWenjianXiudingShenqingEntity request)
+            throws DataException {
+        if (request == null) {
+            throw new DataException("鏈壘鍒颁慨璁㈠鏍稿崟鍏宠仈鐨勪慨璁㈢敵璇�");
+        }
+        if (!Objects.equals(request.getFlowState(), PASSED)) {
+            throw new DataException("鍏宠仈鐨勬枃浠朵慨璁㈢敵璇峰皻鏈鎵归�氳繃");
+        }
+        requireText(request.getWenjianId(), "淇鐢宠鏈叧鑱旀潵婧愭枃浠�");
+        if (request.getBanbenXuhao() == null || request.getBanbenXuhao() < 0) {
+            throw new DataException("淇鐢宠鏉ユ簮鐗堟湰搴忓彿鏃犳晥");
+        }
+        if (request.getYuanBiangengXuhao() == null || request.getYuanBiangengXuhao() < 0) {
+            throw new DataException("淇鐢宠鏉ユ簮鍙樻洿搴忓彿鏃犳晥");
+        }
+        if (!formatVersion(request.getBanbenXuhao()).equals(request.getBanbenhao())) {
+            throw new DataException("淇鐢宠鏉ユ簮鐗堟湰鍙蜂笌鐗堟湰搴忓彿涓嶄竴鑷�");
+        }
+    }
+
+    private void validateControl(DmsWenjianBanbenKongzhiEntity control)
+            throws DataException {
+        if (control == null) {
+            throw new DataException("鏉ユ簮鏂囦欢灏氭湭寤虹珛姝e紡鐗堟湰");
+        }
+        if (!EFFECTIVE.equals(control.getBizStatus())) {
+            throw new DataException("鏉ユ簮鏂囦欢褰撳墠涓嶆槸鏈夋晥鐘舵��");
+        }
+        if (control.getBanbenXuhao() == null || control.getBanbenXuhao() < 0
+                || control.getBiangengXuhao() == null || control.getBiangengXuhao() < 0) {
+            throw new DataException("鏉ユ簮鏂囦欢鐗堟湰鎺у埗鏁版嵁鏃犳晥");
+        }
+    }
+
+    private void verifySourceSnapshot(DmsWenjianXiudingShenqingEntity request,
+                                      DmsWenjianBanbenKongzhiEntity control)
+            throws DataException {
+        if (!Objects.equals(request.getBanbenXuhao(), control.getBanbenXuhao())
+                || !Objects.equals(request.getYuanBiangengXuhao(), control.getBiangengXuhao())) {
+            throw new DataException("鏉ユ簮鏂囦欢宸叉湁鍏朵粬淇鐢熸晥锛岃閲嶆柊鍙戣捣淇鐢宠");
+        }
+    }
+
+    private int calculateEffectiveVersion(int currentVersion, String changeType)
+            throws DataException {
+        if (UNCHANGED.equals(changeType)) {
+            return currentVersion;
+        }
+        try {
+            return Math.addExact(currentVersion, 1);
+        } catch (ArithmeticException exception) {
+            throw new DataException("鏂囦欢鐗堟湰搴忓彿宸茶揪鍒颁笂闄�");
+        }
+    }
+
+    private void validateChangeType(String changeType) throws DataException {
+        if (!UPGRADE.equals(changeType) && !UNCHANGED.equals(changeType)) {
+            throw new DataException("淇瀹℃牳鍗曠殑鍙樻洿鏂瑰紡鏃犳晥");
+        }
+    }
+
+    private void writeNewAuditResult(DmsWenjianXinzengShenheEntity audit, Date now)
+            throws DataException {
+        audit.setShengxiaoBanbenXuhao(0);
+        audit.setShengxiaoBanbenhao(formatVersion(0));
+        audit.setShengxiaoBiangengXuhao(0L);
+        audit.setBanbenShengxiaoShijian(now);
+        requireSingleUpdate(newAuditMapper.updateEffectiveVersion(audit),
+                "鍥炲啓鏂板瀹℃牳鐢熸晥鐗堟湰澶辫触");
+    }
+
+    private boolean hasCompleteNewResult(DmsWenjianXinzengShenheEntity audit)
+            throws DataException {
+        boolean any = audit.getShengxiaoBanbenXuhao() != null
+                || audit.getShengxiaoBanbenhao() != null
+                || audit.getShengxiaoBiangengXuhao() != null
+                || audit.getBanbenShengxiaoShijian() != null;
+        if (!any) {
+            return false;
+        }
+        boolean complete = Objects.equals(audit.getShengxiaoBanbenXuhao(), 0)
+                && formatVersion(0).equals(audit.getShengxiaoBanbenhao())
+                && Objects.equals(audit.getShengxiaoBiangengXuhao(), 0L)
+                && audit.getBanbenShengxiaoShijian() != null;
+        if (!complete) {
+            throw new DataException("鏂板瀹℃牳鍗曠殑鐢熸晥鐗堟湰缁撴灉涓嶅畬鏁�");
+        }
+        return true;
+    }
+
+    private boolean hasCompleteRevisionResult(DmsWenjianXiudingShenheEntity audit)
+            throws DataException {
+        boolean any = audit.getShengxiaoBanbenXuhao() != null
+                || audit.getShengxiaoBanbenhao() != null
+                || audit.getShengxiaoBiangengXuhao() != null
+                || audit.getBanbenShengxiaoShijian() != null;
+        if (!any) {
+            return false;
+        }
+        boolean complete = audit.getShengxiaoBanbenXuhao() != null
+                && audit.getShengxiaoBanbenXuhao() >= 0
+                && formatVersion(audit.getShengxiaoBanbenXuhao())
+                .equals(audit.getShengxiaoBanbenhao())
+                && audit.getShengxiaoBiangengXuhao() != null
+                && audit.getShengxiaoBiangengXuhao() >= 0
+                && audit.getBanbenShengxiaoShijian() != null;
+        if (!complete) {
+            throw new DataException("淇瀹℃牳鍗曠殑鐢熸晥鐗堟湰缁撴灉涓嶅畬鏁�");
+        }
+        return true;
+    }
+
+    private boolean requiresVersionCheck(Integer flowState) throws DataException {
+        if (flowState == null) {
+            throw new DataException("宸ヤ綔娴佺姸鎬佷笉鑳戒负绌�");
+        }
+        if (flowState == EXCEPTION) {
+            throw new DataException("鏂囦欢瀹℃牳娴佺▼澶勪簬寮傚父鐘舵�侊紝璇蜂慨澶嶆祦绋嬪悗閲嶈瘯");
+        }
+        return flowState == RUNNING || flowState == PASSED;
+    }
+
+    private void verifyPersistedState(Integer persistedState, Integer workflowState)
+            throws DataException {
+        if (!Objects.equals(persistedState, workflowState)) {
+            throw new DataException("娴佺▼鐘舵�佸皻鏈悓姝ュ畬鎴愶細琛ㄥ崟鐘舵��=" + persistedState
+                    + "锛屼换鍔$姸鎬�=" + workflowState + "锛岃绋嶅悗閲嶈瘯");
+        }
+    }
+
+    private DmsWenjianXinzengShenheEntity uniqueNewAudit(
+            List<DmsWenjianXinzengShenheEntity> rows) throws DataException {
+        if (rows == null || rows.isEmpty()) {
+            throw new DataException("鏈壘鍒版枃浠舵柊澧炲鏍告祦绋嬪叧鑱旇褰�");
+        }
+        if (rows.size() > 1) {
+            throw new DataException("澶氫釜鏂囦欢鏂板瀹℃牳鍗曞叧鑱斿悓涓�娴佺▼浠诲姟");
+        }
+        return rows.get(0);
+    }
+
+    private DmsWenjianXiudingShenheEntity uniqueRevisionAudit(
+            List<DmsWenjianXiudingShenheEntity> rows) throws DataException {
+        if (rows == null || rows.isEmpty()) {
+            throw new DataException("鏈壘鍒版枃浠朵慨璁㈠鏍告祦绋嬪叧鑱旇褰�");
+        }
+        if (rows.size() > 1) {
+            throw new DataException("澶氫釜鏂囦欢淇瀹℃牳鍗曞叧鑱斿悓涓�娴佺▼浠诲姟");
+        }
+        return rows.get(0);
+    }
+
+    private void requireEvent(DmsFlowEventType eventType) throws DataException {
+        if (eventType == null) {
+            throw new DataException("娴佺▼浜嬩欢绫诲瀷涓嶈兘涓虹┖");
+        }
+    }
+
+    private String requireText(String value, String message) throws DataException {
+        if (value == null || value.trim().isEmpty()) {
+            throw new DataException(message);
+        }
+        return value.trim();
+    }
+
+    private void requireSingleUpdate(int affected, String message) throws DataException {
+        if (affected != 1) {
+            throw new DataException(message);
+        }
+    }
+
+    static String formatVersion(int sequence) {
+        String value = Integer.toString(sequence);
+        return "D(" + (value.length() < 2 ? "0" + value : value) + ")";
+    }
+}

--
Gitblit v1.8.0