刘光辉
4 小时以前 06f314545ac3514d7ce28939920866ae8188d31c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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<DmsWenjianXinzengShenheEntity> 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<DmsWenjianXiudingShenheEntity> rows =
                revisionAuditMapper.selectByFlowForUpdate(tenantId, sourceId, taskId);
        DmsWenjianXiudingShenheEntity audit = requireUnique(rows, "文件修订审核单");
        requireStageable(audit.getFlowState(), sourceId, taskId);
        return audit;
    }
 
    private <T> T requireUnique(List<T> 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存在旧版登记记录,缺少任务归属,请核对迁移后重试");
        }
    }
}