package jnpf.dmsService; import jnpf.base.UserInfo; import jnpf.dmsEntity.DmsWenjianXinzengShenheEntity; import jnpf.dmsEntity.DmsWenjianXiudingShenheEntity; import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity; import jnpf.dmsEntity.permission.enums.DmsPermissionAction; import jnpf.dmsEntity.permission.enums.DmsResourceType; import jnpf.dmsEntity.storage.form.DmsWorkflowFilePrepareForm; import jnpf.dmsEntity.storage.DmsWorkflowSourceKey; import jnpf.dmsEntity.storage.enums.DmsWorkflowFileType; import jnpf.dmsEntity.storage.vo.DmsFileUploadVO; import jnpf.dmsEntity.storage.vo.DmsWorkflowFilePrepareVO; import jnpf.dmsMapper.DmsFileObjectMapper; import jnpf.dmsMapper.DmsFileVersionMapper; import jnpf.dmsMapper.DmsWenjianXinzengShenheMapper; import jnpf.dmsMapper.DmsWenjianXiudingShenheMapper; import jnpf.dmsPermission.DmsCurrentIdentity; import jnpf.dmsPermission.DmsPermissionError; import jnpf.dmsPermission.DmsPermissionException; import jnpf.exception.DataException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.UUID; @Service @RequiredArgsConstructor public class DmsWorkflowFilePrepareService { private static final int TO_BE_SUBMIT = 0; private static final int RUNNING = 1; private final DmsCurrentIdentity currentIdentity; private final DmsPermissionDecisionService decisionService; private final DmsWenjianXinzengShenheMapper newAuditMapper; private final DmsWenjianXiudingShenheMapper revisionAuditMapper; private final DmsFileVersionMapper fileVersionMapper; private final DmsFileObjectMapper fileObjectMapper; private final DmsWorkflowApprovalValidator approvalValidator; @Transactional public DmsWorkflowFilePrepareVO prepare(DmsWorkflowFilePrepareForm form, String serviceId) { UserInfo user = currentIdentity.requireUser(); String tenantId = currentIdentity.tenantId(user); String sourceId = form.getSourceId().trim(); String taskId = form.getTaskId().trim(); String sourceKey = DmsWorkflowSourceKey.of(sourceId, taskId, form.getFileType()); if (form.getFileType() == DmsWorkflowFileType.CREATE) { DmsWenjianXinzengShenheEntity audit = requireStageableNewAudit(tenantId, sourceId, taskId); requireNoLegacyRegistration(tenantId, serviceId, sourceId); DmsWorkflowFilePrepareVO result = new DmsWorkflowFilePrepareVO(); result.setSourceKey(sourceKey); result.setApprovedFileJson(approvalValidator.validateNew(audit, form)); result.setVersionLabel("D(00)"); return result; } DmsWenjianXiudingShenheEntity audit = requireStageableRevisionAudit(tenantId, sourceId, taskId); UUID baseVersionId = form.getVersionId(); if (baseVersionId == null) { throw new DataException("修订文件时versionId不能为空"); } String approvedFile = approvalValidator.validateRevision(tenantId, audit, form); requireNoLegacyRegistration(tenantId, serviceId, sourceId); DmsFileUploadVO existing = fileObjectMapper.selectUploadBySource( tenantId, serviceId, sourceKey); if (existing != null) { if (!Objects.equals(existing.getBaseFileVersionId(), baseVersionId)) { throw DmsPermissionException.of(DmsPermissionError.IDEMPOTENCY_CONFLICT, "source_id已用于另一个文件版本的修订"); } decisionService.requireAllowed(DmsResourceType.DOCUMENT, existing.getDocumentId(), DmsPermissionAction.UPDATE); DmsWorkflowFilePrepareVO result = new DmsWorkflowFilePrepareVO(); result.setSourceKey(sourceKey); result.setApprovedFileJson(approvedFile); result.setDocumentId(existing.getDocumentId()); result.setVersionLabel(existing.getVersionLabel()); result.setRevisionReason(existing.getRevisionReason()); return result; } DmsFileVersionEntity baseVersion = fileVersionMapper.selectByTenantAndId( tenantId, baseVersionId); if (baseVersion == null) { throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND, "待修订文件版本不存在"); } UUID documentId = baseVersion.getDocumentId(); decisionService.requireAllowed(DmsResourceType.DOCUMENT, documentId, DmsPermissionAction.UPDATE); DmsFileVersionEntity current = fileVersionMapper.selectCurrentEffective( tenantId, documentId); if (current == null || !Objects.equals(current.getId(), baseVersionId)) { throw DmsPermissionException.of(DmsPermissionError.REVISION_CONFLICT, "待修订版本已不是现行有效版本,请刷新后重试"); } long nextVersionNo = fileVersionMapper.selectNextVersionNo(tenantId, documentId); DmsWorkflowFilePrepareVO result = new DmsWorkflowFilePrepareVO(); result.setSourceKey(sourceKey); result.setApprovedFileJson(approvedFile); result.setDocumentId(documentId); result.setVersionLabel(String.format(Locale.ROOT, "D(%02d)", nextVersionNo - 1)); result.setRevisionReason("工作流审核通过"); return result; } private DmsWenjianXinzengShenheEntity requireStageableNewAudit(String tenantId, String sourceId, String taskId) { List rows = newAuditMapper.selectByFlowForUpdate(tenantId, sourceId, taskId); DmsWenjianXinzengShenheEntity audit = requireUnique(rows, "文件新增审核单"); requireStageable(audit.getFlowState(), sourceId, taskId); return audit; } private DmsWenjianXiudingShenheEntity requireStageableRevisionAudit(String tenantId, String sourceId, String taskId) { List rows = revisionAuditMapper.selectByFlowForUpdate(tenantId, sourceId, taskId); DmsWenjianXiudingShenheEntity audit = requireUnique(rows, "文件修订审核单"); requireStageable(audit.getFlowState(), sourceId, taskId); return audit; } private T requireUnique(List rows, String label) { if (rows == null || rows.isEmpty()) { throw new DataException("未找到与sourceId、taskId匹配的" + label); } if (rows.size() != 1) { throw new DataException("sourceId、taskId匹配到多条" + label); } return rows.get(0); } private void requireStageable(Integer state, String sourceId, String taskId) { if (!Integer.valueOf(TO_BE_SUBMIT).equals(state) && !Integer.valueOf(RUNNING).equals(state)) { throw new DataException("文件流程不处于待提交或审批中,不能登记待生效文件:" + sourceId + "/" + taskId); } } private void requireNoLegacyRegistration(String tenantId, String serviceId, String flowId) { if (fileObjectMapper.selectUploadBySource(tenantId, serviceId, flowId) != null) { throw new DataException("该flowID存在旧版登记记录,缺少任务归属,请核对迁移后重试"); } } }