刘光辉
3 小时以前 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
package jnpf.fileStorage.dms;
 
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jnpf.audit.sdk.annotation.AuditLog;
import jnpf.base.ActionResult;
import jnpf.dms.DmsResourceApi;
import jnpf.dmsEntity.storage.approval.DmsApprovedBatch;
import jnpf.dmsEntity.storage.approval.DmsApprovedItem;
import jnpf.dmsEntity.storage.form.DmsApprovedRegistrationForm;
import jnpf.dmsEntity.storage.form.DmsApprovedRegistrationCallback;
import jnpf.dmsEntity.storage.form.DmsApprovedRegistrationCallback.StoredFile;
import jnpf.dmsEntity.storage.form.DmsFileUploadRegisterForm;
import jnpf.exception.DataException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
 
import java.util.Objects;
 
@Service
@RequiredArgsConstructor
public class DmsWorkflowFileCreateService {
    private static final String SERVICE_ID = "jnpf-file";
    private final DmsResourceApi dmsResourceApi;
    private final DmsFileStorageService fileStorageService;
    private final DmsCommonFileReader commonFileReader;
    private final DmsApprovalPageMergeService approvalPageMergeService;
    private final DmsQianpiyeDocxWriter qianpiyeDocxWriter;
    private final ObjectMapper json;
 
    /** DMS owns source data and registration progress; file only consumes the pushed set. */
    @AuditLog(action = "DMS_WORKFLOW_REGISTER_APPROVED", bizCodeExpr = "#form.taskId")
    public DmsApprovedBatch process(DmsApprovedRegistrationForm form, String auditBizSign) {
        if (form.getBatchId() == null || form.getSourceDigest() == null || form.getFiles() == null || form.getFiles().isEmpty())
            throw new DataException("DMS推送的登记批次不完整");
        DmsApprovedRegistrationCallback callback = new DmsApprovedRegistrationCallback();
        callback.setTenantId(form.getTenantId());
        callback.setAttemptToken(form.getAttemptToken());
        callback.setBatchId(form.getBatchId());
        callback.setSourceDigest(form.getSourceDigest());
        for (DmsApprovedItem item : form.getFiles()) {
            if (item == null || item.getDocumentId() == null || item.getFileVersionId() == null)
                throw new DataException("DMS推送的文件缺少登记ID");
            if ("REUSE".equals(item.getChangeType())) continue;
            if (!"CREATE".equals(item.getChangeType()) && !"REVISE".equals(item.getChangeType()))
                throw new DataException("DMS推送的文件操作类型无效");
            StoredFile stored = new StoredFile();
            stored.setSourceKey(item.getSourceKey());
            stored.setFileJson(item.getFileJson());
            stored.setContent(commonFileReader.withFile(singleFileUrl(item.getFileJson()), item.getFileJson(),
                    item.getDocumentName(), file -> store(item, file)));
            callback.getFiles().add(stored);
        }
        DmsApprovedBatch accepted = requireBatch(dmsResourceApi.registerWorkflowUpload(
                SERVICE_ID, auditBizSign, callback), form);
        if (!form.getBatchId().equals(accepted.getId()) || !Objects.equals(form.getSourceDigest(), accepted.getSourceDigest())
                || !("WAITING".equals(accepted.getStatus()) || "APPLIED".equals(accepted.getStatus())))
            throw new DataException("DMS未返回完整的登记确认结果");
        return accepted;
    }
 
    private DmsFileUploadRegisterForm store(DmsApprovedItem item, MultipartFile file) {
        String approvalPage = item.getQianpiyeFiles() == null || item.getQianpiyeFiles().isBlank()
                ? item.getApprovalPageFileJson() : item.getQianpiyeFiles();
        MultipartFile source = isDocx(file) && item.getApprovalValuesByTag() != null
                && approvalPage != null && !approvalPage.isBlank()
                ? approvalPageMergeService.withoutApprovalPages(file) : file;
        MultipartFile renderedFile = isDocx(file) && item.getApprovalValuesByTag() != null
                ? qianpiyeDocxWriter.render(source, item.getApprovalValuesByTag(),
                        item.getApprovalFlowVersionId()) : file;
        if (approvalPage == null || approvalPage.isBlank() || !isDocx(file)) {
            return fileStorageService.storeWorkflowContent(
                    item.getDocumentId(), item.getFileVersionId(), renderedFile);
        }
        return commonFileReader.withFile(singleFileUrl(approvalPage), approvalPage, "签批页",
                page -> {
                    MultipartFile rendered = isDocx(page) ? qianpiyeDocxWriter.render(
                            page, item.getApprovalValuesByTag(), item.getApprovalFlowVersionId()) : page;
                    return fileStorageService.storeWorkflowContent(item.getDocumentId(),
                            item.getFileVersionId(), approvalPageMergeService.replaceOrPrepend(renderedFile, rendered));
                });
    }
 
    private boolean isDocx(MultipartFile file) {
        String name = file == null ? null : file.getOriginalFilename();
        return name != null && name.toLowerCase(java.util.Locale.ROOT).endsWith(".docx");
    }
 
    private DmsApprovedBatch requireBatch(ActionResult<DmsApprovedBatch> result, DmsApprovedRegistrationForm form) {
        if (result == null || !Integer.valueOf(200).equals(result.getCode()) || result.getData() == null)
            throw new DataException(result == null ? "DMS文件登记无响应" : result.getMsg());
        DmsApprovedBatch batch = result.getData();
        if (!form.getSourceId().trim().equals(batch.getFlowId()) || !form.getTaskId().trim().equals(batch.getTaskId())
                || !Objects.equals(form.getAuditType(), batch.getAuditType()))
            throw new DataException("DMS返回的批准批次与请求不匹配");
        return batch;
    }
 
    String singleFileUrl(String fileJson) {
        try {
            JsonNode value = json.readTree(fileJson);
            if (value.isArray()) {
                if (value.size() != 1) throw new DataException("每个主文件或记录必须有且只有一个文件");
                value = value.get(0);
            }
            String url = value.path("url").asText(null);
            if (url == null || url.isBlank()) throw new DataException("审核附件缺少URL");
            return url;
        } catch (DataException e) { throw e; }
        catch (Exception e) { throw new DataException("审核附件格式不正确"); }
    }
}