package jnpf.dmsService; import jnpf.dmsEntity.permission.entity.DmsDocumentEntity; import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity; import jnpf.dmsEntity.storage.DmsWorkflowSourceKey; import jnpf.dmsEntity.storage.enums.DmsWorkflowFileType; import jnpf.dmsEntity.storage.vo.DmsFileUploadVO; import jnpf.dmsIntegration.audit.DmsVersionStateAuditRow; import jnpf.dmsMapper.DmsDocumentMapper; import jnpf.dmsMapper.DmsFileObjectMapper; import jnpf.dmsMapper.DmsFileVersionMapper; import jnpf.dmsMapper.DmsVersionStateMapper; import jnpf.dmsPermission.DmsPermissionError; import jnpf.dmsPermission.DmsPermissionException; import jnpf.dmsService.search.DmsSearchIndexJobService; import jnpf.exception.DataException; import jnpf.flowable.WorkFlowApi; import jnpf.flowable.entity.TaskEntity; import jnpf.flowable.enums.TaskStatusEnum; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Objects; @Service @RequiredArgsConstructor public class DmsWorkflowFileActivationService { private static final String SERVICE_ID = "jnpf-file"; private final WorkFlowApi workFlowApi; private final DmsFileObjectMapper fileObjectMapper; private final DmsDocumentMapper documentMapper; private final DmsFileVersionMapper fileVersionMapper; private final DmsVersionStateMapper versionStateMapper; private final DmsSearchIndexJobService searchIndexJobService; private final DmsBusinessLifecycleGuard businessOccupancy; @Transactional(rollbackFor = Exception.class) public DmsFileUploadVO activate(String tenantId, String flowId, String taskId, DmsWorkflowFileType fileType, String approvedBy) { TaskEntity task = requireTask(flowId, taskId); if (!TaskStatusEnum.PASSED.getCode().equals(task.getStatus())) { throw new DataException("流程任务尚未审核通过,不能激活文件"); } return activateVerified(tenantId, flowId, taskId, fileType, approvedBy); } @Transactional(rollbackFor = Exception.class) public DmsFileUploadVO activateVerified(String tenantId, String flowId, String taskId, DmsWorkflowFileType fileType, String approvedBy) { String activationActor = actor(approvedBy); String sourceKey = DmsWorkflowSourceKey.of(flowId, taskId, fileType); DmsFileUploadVO staged = fileObjectMapper.selectUploadBySource(tenantId, SERVICE_ID, sourceKey); if (staged == null || staged.getFileVersionId() == null || staged.getDocumentId() == null) { throw new DataException("未找到当前流程任务暂存的文件"); } // Number lock precedes center row locks; no caller task ID can exempt a business chain. businessOccupancy.guardStandaloneActivation(tenantId,staged.getFileVersionId()); DmsDocumentEntity document = documentMapper.selectByTenantAndIdForUpdate( tenantId, staged.getDocumentId()); if (document == null) { throw DmsPermissionException.of(DmsPermissionError.RESOURCE_NOT_FOUND, "暂存文件不存在"); } DmsVersionStateAuditRow state = versionStateMapper.selectAuditState( tenantId, staged.getFileVersionId()); if (state != null && "EFFECTIVE".equals(state.getLifecycleStatus())) { staged.setLifecycleStatus("EFFECTIVE"); return staged; } if (state == null || !"PENDING_APPROVAL".equals(state.getLifecycleStatus())) { throw new DataException("暂存文件状态不允许激活"); } if (fileType == DmsWorkflowFileType.REVISE) { DmsFileVersionEntity current = fileVersionMapper.selectCurrentEffective( tenantId, staged.getDocumentId()); if (current == null || !Objects.equals(current.getId(), staged.getBaseFileVersionId())) { throw DmsPermissionException.of(DmsPermissionError.REVISION_CONFLICT, "待修订版本已不是现行有效版本,请重新发起审批"); } int superseded = versionStateMapper.supersedeCurrent(tenantId, staged.getDocumentId(), current.getId(), staged.getVersionLabel(), activationActor); if (superseded != 1) { throw DmsPermissionException.of(DmsPermissionError.REVISION_CONFLICT, "现行有效版本已发生变化,请重试"); } } else if (fileVersionMapper.selectCurrentEffective(tenantId, staged.getDocumentId()) != null) { throw new DataException("新增文件已经存在有效版本"); } if (versionStateMapper.activateWorkflowPending( tenantId, staged.getFileVersionId(), flowId, taskId, fileType.name(), activationActor) != 1) { throw new DataException("工作流文件激活失败,请重试"); } searchIndexJobService.enqueueContentUpsert(tenantId, staged.getDocumentId(), staged.getFileVersionId(), staged.getChecksumSha256()); staged.setLifecycleStatus("EFFECTIVE"); return staged; } TaskEntity requireTask(String flowId, String taskId) { TaskEntity task = workFlowApi.getInfoSubmit(taskId); if (task == null || !taskId.equals(task.getId())) { throw new DataException("未找到与taskId匹配的流程任务"); } if (!flowId.equals(task.getFlowId()) && !flowId.equals(task.getTemplateId())) { throw new DataException("流程任务不属于指定flowID"); } return task; } private String actor(String value) { return value == null || value.trim().isEmpty() ? "dms-workflow-activation" : value.trim(); } }