liyong
6 天以前 9d66bfbfcda297f628e6a857e343f98422f4534a
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
package com.ruoyi.approve.utils;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.approve.pojo.ApprovalInstance;
import com.ruoyi.approve.pojo.ApprovalInstanceNode;
import com.ruoyi.approve.pojo.ApprovalRecord;
import com.ruoyi.approve.pojo.ApprovalTask;
import com.ruoyi.approve.pojo.ApprovalTemplateNode;
import com.ruoyi.approve.pojo.ApprovalTemplateNodeApprover;
import com.ruoyi.approve.service.ApprovalInstanceNodeService;
import com.ruoyi.approve.service.ApprovalRecordService;
import com.ruoyi.approve.service.ApprovalTaskService;
import com.ruoyi.approve.service.ApprovalTemplateNodeApproverService;
import com.ruoyi.approve.service.ApprovalTemplateNodeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
 
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
 
/**
 * 审批流程节点工具类
 */
@Component
@RequiredArgsConstructor
public class ApproveProcessConfigNodeUtils {
 
    private final ApprovalInstanceNodeService instanceNodeService;
    private final ApprovalTaskService approvalTaskService;
    private final ApprovalRecordService approvalRecordService;
    private final ApprovalTemplateNodeService approvalTemplateNodeService;
    private final ApprovalTemplateNodeApproverService approvalTemplateNodeApproverService;
 
    /**
     * 按当前层级创建审批节点和审批任务。
     * 该重载会同时写入一条发起审批记录。
     */
    @Transactional(rollbackFor = Exception.class)
    public ApprovalInstanceNode createCurrentNodeAndTasks(ApprovalInstance instance) {
        return createCurrentNodeAndTasks(instance, true);
    }
 
    /**
     * 按当前层级创建审批节点和审批任务。
     *
     * @param instance 审批实例
     * @param createSubmitRecord 是否创建发起审批记录
     * @return 创建出的当前节点实例
     */
    @Transactional(rollbackFor = Exception.class)
    public ApprovalInstanceNode createCurrentNodeAndTasks(ApprovalInstance instance, boolean createSubmitRecord) {
        if (instance == null || instance.getId() == null) {
            throw new RuntimeException("审批实例不能为空");
        }
        if (instance.getTemplateId() == null) {
            throw new RuntimeException("审批模板不能为空");
        }
 
        Integer currentLevel = instance.getCurrentLevel() == null ? 1 : instance.getCurrentLevel();
 
        ApprovalInstanceNode existsNode = instanceNodeService.getOne(
                new LambdaQueryWrapper<ApprovalInstanceNode>()
                        .eq(ApprovalInstanceNode::getInstanceId, instance.getId())
                        .eq(ApprovalInstanceNode::getLevelNo, currentLevel)
                        .eq(ApprovalInstanceNode::getDeleted, 0)
                        .last("LIMIT 1")
        );
        if (existsNode != null) {
            return existsNode;
        }
 
        ApprovalTemplateNode templateNode = approvalTemplateNodeService.getOne(
                new LambdaQueryWrapper<ApprovalTemplateNode>()
                        .eq(ApprovalTemplateNode::getTemplateId, instance.getTemplateId())
                        .eq(ApprovalTemplateNode::getLevelNo, currentLevel)
                        .orderByAsc(ApprovalTemplateNode::getId)
                        .last("LIMIT 1")
        );
        if (templateNode == null) {
            throw new RuntimeException("未找到当前层级对应的审批模板节点");
        }
 
        List<ApprovalTemplateNodeApprover> approvers = approvalTemplateNodeApproverService.list(
                new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
                        .eq(ApprovalTemplateNodeApprover::getTemplateId, instance.getTemplateId())
                        .eq(ApprovalTemplateNodeApprover::getNodeId, templateNode.getId())
                        .eq(ApprovalTemplateNodeApprover::getDeleted, 0L)
                        .orderByAsc(ApprovalTemplateNodeApprover::getSortNo)
        );
        if (approvers == null || approvers.isEmpty()) {
            throw new RuntimeException("当前审批节点未配置审批人");
        }
 
        ApprovalInstanceNode instanceNode = new ApprovalInstanceNode();
        instanceNode.setInstanceId(instance.getId());
        instanceNode.setLevelNo(templateNode.getLevelNo());
        instanceNode.setApproveType(templateNode.getApproveType());
        instanceNode.setStatus("PENDING");
        instanceNode.setStartTime(LocalDateTime.now());
        instanceNode.setDeleted((byte) 0);
        instanceNodeService.save(instanceNode);
 
        List<ApprovalTask> taskList = new ArrayList<>(approvers.size());
        for (ApprovalTemplateNodeApprover approver : approvers) {
            ApprovalTask task = new ApprovalTask();
            task.setInstanceId(instance.getId());
            task.setNodeId(instanceNode.getId());
            task.setLevelNo(instanceNode.getLevelNo());
            task.setApproverId(approver.getApproverId());
            task.setApproverName(approver.getApproverName());
            task.setTaskStatus("PENDING");
            task.setIsRead((byte) 0);
            task.setDeleted((byte) 0);
            taskList.add(task);
        }
        approvalTaskService.saveBatch(taskList);
 
        if (createSubmitRecord) {
            ApprovalRecord record = new ApprovalRecord();
            record.setInstanceId(instance.getId());
            record.setNodeId(instanceNode.getId());
            record.setOperatorId(instance.getApplicantId());
            record.setOperatorName(instance.getApplicantName());
            record.setAction("SUBMIT");
            record.setComment("发起审批");
            record.setDeleted((byte) 0);
            approvalRecordService.save(record);
        }
 
        return instanceNode;
    }
 
    /**
     * 查询当前待处理节点。
     */
    public ApprovalInstanceNode getCurrentNode(Long instanceId) {
        if (instanceId == null) {
            return null;
        }
 
        return instanceNodeService.getOne(
                new LambdaQueryWrapper<ApprovalInstanceNode>()
                        .eq(ApprovalInstanceNode::getInstanceId, instanceId)
                        .eq(ApprovalInstanceNode::getStatus, "PENDING")
                        .eq(ApprovalInstanceNode::getDeleted, 0)
                        .orderByAsc(ApprovalInstanceNode::getLevelNo)
                        .last("LIMIT 1")
        );
    }
 
    /**
     * 查询当前审批层级。
     */
    public Integer getCurrentLevel(Long instanceId) {
        ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
        return currentNode != null ? currentNode.getLevelNo() : null;
    }
 
    /**
     * 查询当前节点下的待审批任务。
     */
    public List<ApprovalTask> getCurrentPendingTasks(Long instanceId) {
        if (instanceId == null) {
            return List.of();
        }
 
        ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
        if (currentNode == null) {
            return List.of();
        }
 
        return approvalTaskService.list(
                new LambdaQueryWrapper<ApprovalTask>()
                        .eq(ApprovalTask::getInstanceId, instanceId)
                        .eq(ApprovalTask::getNodeId, currentNode.getId())
                        .eq(ApprovalTask::getTaskStatus, "PENDING")
                        .eq(ApprovalTask::getDeleted, 0)
                        .orderByAsc(ApprovalTask::getLevelNo)
        );
    }
 
    /**
     * 查询当前用户在当前节点上的待审批任务。
     */
    public ApprovalTask getCurrentUserTask(Long instanceId, Long userId) {
        if (instanceId == null || userId == null) {
            return null;
        }
 
        ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
        if (currentNode == null) {
            return null;
        }
 
        return approvalTaskService.getOne(
                new LambdaQueryWrapper<ApprovalTask>()
                        .eq(ApprovalTask::getInstanceId, instanceId)
                        .eq(ApprovalTask::getNodeId, currentNode.getId())
                        .eq(ApprovalTask::getApproverId, userId)
                        .eq(ApprovalTask::getTaskStatus, "PENDING")
                        .eq(ApprovalTask::getDeleted, 0)
                        .last("LIMIT 1")
        );
    }
 
    /**
     * 判断当前用户是否是当前审批人。
     */
    public boolean isCurrentApprover(Long instanceId, Long userId) {
        return getCurrentUserTask(instanceId, userId) != null;
    }
 
    /**
     * 查询当前节点的审批人 ID 列表。
     */
    public List<Long> getCurrentNodeApproverIds(Long instanceId) {
        return getCurrentPendingTasks(instanceId).stream()
                .map(ApprovalTask::getApproverId)
                .distinct()
                .collect(Collectors.toList());
    }
 
    /**
     * 查询当前节点剩余待审批人数。
     */
    public int getRemainingApproverCount(Long instanceId) {
        return getCurrentPendingTasks(instanceId).size();
    }
 
    /**
     * 查询当前节点已同意人数。
     */
    public int getApprovedCount(Long instanceId) {
        if (instanceId == null) {
            return 0;
        }
 
        ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
        if (currentNode == null) {
            return 0;
        }
 
        return Math.toIntExact(approvalTaskService.count(
                new LambdaQueryWrapper<ApprovalTask>()
                        .eq(ApprovalTask::getInstanceId, instanceId)
                        .eq(ApprovalTask::getNodeId, currentNode.getId())
                        .eq(ApprovalTask::getTaskStatus, "APPROVED")
                        .eq(ApprovalTask::getDeleted, 0)
        ));
    }
 
    /**
     * 查询当前节点已拒绝人数。
     */
    public int getRejectedCount(Long instanceId) {
        if (instanceId == null) {
            return 0;
        }
 
        ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
        if (currentNode == null) {
            return 0;
        }
 
        return Math.toIntExact(approvalTaskService.count(
                new LambdaQueryWrapper<ApprovalTask>()
                        .eq(ApprovalTask::getInstanceId, instanceId)
                        .eq(ApprovalTask::getNodeId, currentNode.getId())
                        .eq(ApprovalTask::getTaskStatus, "REJECTED")
                        .eq(ApprovalTask::getDeleted, 0)
        ));
    }
 
    /**
     * 判断当前节点是否可以流转到下一层。
     */
    public boolean canProceedToNextLevel(Long instanceId, String approveType) {
        if (instanceId == null || approveType == null) {
            return false;
        }
 
        if (getRejectedCount(instanceId) > 0) {
            return false;
        }
 
        int totalApproverCount = getCurrentPendingTasks(instanceId).size() + getApprovedCount(instanceId);
        int approvedCount = getApprovedCount(instanceId);
 
        if ("AND".equalsIgnoreCase(approveType)) {
            return approvedCount > 0 && approvedCount == totalApproverCount;
        }
        if ("OR".equalsIgnoreCase(approveType)) {
            return approvedCount > 0;
        }
        return false;
    }
 
    /**
     * 查询当前用户在当前节点上的任务状态。
     */
    public String getUserTaskStatus(Long instanceId, Long userId) {
        if (instanceId == null || userId == null) {
            return null;
        }
 
        ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
        if (currentNode == null) {
            return null;
        }
 
        ApprovalTask task = approvalTaskService.getOne(
                new LambdaQueryWrapper<ApprovalTask>()
                        .eq(ApprovalTask::getInstanceId, instanceId)
                        .eq(ApprovalTask::getNodeId, currentNode.getId())
                        .eq(ApprovalTask::getApproverId, userId)
                        .eq(ApprovalTask::getDeleted, 0)
                        .last("LIMIT 1")
        );
 
        return task != null ? task.getTaskStatus() : null;
    }
 
    /**
     * 查询指定用户的全部待审批任务。
     */
    public List<ApprovalTask> getUserAllPendingTasks(Long userId) {
        if (userId == null) {
            return List.of();
        }
 
        return approvalTaskService.list(
                new LambdaQueryWrapper<ApprovalTask>()
                        .eq(ApprovalTask::getApproverId, userId)
                        .eq(ApprovalTask::getTaskStatus, "PENDING")
                        .eq(ApprovalTask::getDeleted, 0)
                        .orderByDesc(ApprovalTask::getCreateTime)
        );
    }
 
    /**
     * 查询审批实例的进度摘要。
     */
    public String getApprovalProgress(Long instanceId) {
        if (instanceId == null) {
            return "无效的审批实例";
        }
 
        ApprovalInstanceNode currentNode = getCurrentNode(instanceId);
        if (currentNode == null) {
            return "审批已完成或尚未开始";
        }
 
        int approvedCount = getApprovedCount(instanceId);
        int rejectedCount = getRejectedCount(instanceId);
        int pendingCount = getRemainingApproverCount(instanceId);
        int totalCount = approvedCount + rejectedCount + pendingCount;
 
        return String.format(
                "第%d级审批:总人数=%d,已同意=%d,已拒绝=%d,待审批=%d",
                currentNode.getLevelNo(),
                totalCount,
                approvedCount,
                rejectedCount,
                pendingCount
        );
    }
}