刘光辉
117 分钟以前 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
package jnpf.dmsService;
 
import jnpf.audit.sdk.annotation.AuditLog;
import jnpf.base.UserInfo;
import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity;
import jnpf.dmsEntity.permission.enums.DmsPermissionAction;
import jnpf.dmsEntity.permission.enums.DmsResourceType;
import jnpf.dmsEntity.storage.form.DmsFileExtendValidityForm;
import jnpf.dmsEntity.storage.form.DmsFileExtendValidityForm.FileRequest;
import jnpf.dmsMapper.DmsDocumentMapper;
import jnpf.dmsMapper.DmsFileVersionMapper;
import jnpf.dmsMapper.DmsVersionStateMapper;
import jnpf.dmsPermission.DmsCurrentIdentity;
import jnpf.exception.DataException;
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.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
 
@Service
@RequiredArgsConstructor
public class DmsFileValidityService {
    private final DmsCurrentIdentity currentIdentity;
    private final DmsPermissionDecisionService decisionService;
    private final DmsWorkflowFileActivationService workflowService;
    private final DmsFileVersionMapper fileVersionMapper;
    private final DmsDocumentMapper documentMapper;
    private final DmsVersionStateMapper versionStateMapper;
    private final DmsFileValidityProjection projection;
    private final DmsBusinessLifecycleGuard businessOccupancy;
 
    @Transactional(rollbackFor = Exception.class)
    @AuditLog(action = "UPDATE", label = "批量调整文件有效期", bizModule = "DMS",
            bizType = "DMS_FILE_VERSION", bizCodeExpr = "", bizCodeRequired = false,
            targetTable = "dms_version_states", targetIdExpr = "#p0.files[0].fileVersionId",
            targetIdsExpr = "#p0.files.![fileVersionId]",
            extraExpr = "{'sourceId': #p0.sourceId, 'taskId': #p0.taskId, 'files': #p0.files}")
    public void extendValidity(DmsFileExtendValidityForm form) {
        validateRequest(form);
        UserInfo user = currentIdentity.requireUser();
        String tenantId = currentIdentity.tenantId(user);
        boolean withWorkflow = form.getSourceId() != null && !form.getSourceId().trim().isEmpty();
        if (withWorkflow) {
            TaskEntity task = workflowService.requireTask(form.getSourceId().trim(), form.getTaskId().trim());
            if (!TaskStatusEnum.PASSED.getCode().equals(task.getStatus())) {
                throw new DataException("流程任务尚未审核通过,不能更新有效期");
            }
        }
 
        businessOccupancy.guardValidity(tenantId,withWorkflow ? form.getTaskId().trim() : null,
                form.getFiles().stream().map(f->f.getFileVersionId().toString()).toList());
        Set<UUID> documentIds = new TreeSet<>();
        for (FileRequest file : form.getFiles()) {
            decisionService.requireAllowed(DmsResourceType.FILE_VERSION, file.getFileVersionId(),
                    DmsPermissionAction.UPDATE);
            DmsFileVersionEntity version = fileVersionMapper.selectByTenantAndId(tenantId, file.getFileVersionId());
            if (version == null) {
                throw new DataException("文件版本不存在:" + file.getFileVersionId());
            }
            documentIds.add(version.getDocumentId());
        }
        // 按统一顺序锁定文档,与修订、激活互斥,避免并发批次反向加锁。
        for (UUID documentId : documentIds) {
            if (documentMapper.selectByTenantAndIdForUpdate(tenantId, documentId) == null) {
                throw new DataException("文件所属文档不存在:" + documentId);
            }
        }
        for (FileRequest file : form.getFiles()) {
            int updated = versionStateMapper.updateCurrentEffectiveTo(tenantId, file.getFileVersionId(), file.getEffectiveTo());
            if (updated != 1) {
                throw new DataException("文件有效期更新失败:" + file.getFileVersionId()
                        + ",文件已过期或不是现行有效版本,或新截止时间未延长");
            }
            projection.apply(tenantId, file.getFileVersionId(), file.getEffectiveTo(), user.getUserId());
        }
    }
 
    private void validateRequest(DmsFileExtendValidityForm form) {
        if (form == null || form.getFiles() == null || form.getFiles().isEmpty()) {
            throw new DataException("文件请求列表不能为空");
        }
        if (!form.isWorkflowPairValid()) {
            throw new DataException("sourceId和taskId必须同时提供或同时为空");
        }
        Set<UUID> ids = new HashSet<>();
        for (FileRequest file : form.getFiles()) {
            if (file == null || file.getFileVersionId() == null || file.getEffectiveTo() == null) {
                throw new DataException("文件版本ID和有效期至不能为空");
            }
            if (!ids.add(file.getFileVersionId())) {
                throw new DataException("文件版本ID不能重复:" + file.getFileVersionId());
            }
        }
    }
}