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