@nocobase/plugin-workflow-manual 2.2.0-beta.9 → 3.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client-v2.d.ts +2 -0
- package/client-v2.js +3 -0
- package/dist/client/WorkflowTodo.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client-v2/collections.d.ts +10 -0
- package/dist/client-v2/index.d.ts +9 -0
- package/dist/client-v2/index.js +10 -0
- package/dist/client-v2/locale.d.ts +10 -0
- package/dist/client-v2/plugin.d.ts +13 -0
- package/dist/client-v2/tasks.d.ts +17 -0
- package/dist/externalVersion.js +11 -9
- package/dist/locale/en-US.json +4 -1
- package/dist/locale/zh-CN.json +4 -1
- package/dist/node_modules/joi/package.json +1 -1
- package/dist/server/ManualInstruction.d.ts +4 -3
- package/dist/server/ManualInstruction.js +1 -87
- package/dist/server/Plugin.d.ts +4 -0
- package/dist/server/Plugin.js +137 -150
- package/dist/server/actions.js +140 -34
- package/dist/server/forms/create.d.ts +2 -2
- package/dist/server/forms/create.js +3 -3
- package/dist/server/forms/index.d.ts +2 -2
- package/dist/server/forms/update.d.ts +2 -2
- package/dist/server/forms/update.js +4 -4
- package/dist/server/migrations/20260723120000-rebuild-workflow-task-stats.d.ts +13 -0
- package/dist/server/migrations/20260723120000-rebuild-workflow-task-stats.js +51 -0
- package/package.json +4 -2
package/dist/locale/en-US.json
CHANGED
|
@@ -17,9 +17,12 @@
|
|
|
17
17
|
"Field name existed in form": "Field name existed in form",
|
|
18
18
|
"Filter settings": "Filter settings",
|
|
19
19
|
"Manual": "Manual",
|
|
20
|
+
"Manual task cannot be processed on the new page": "Manual task cannot be processed on the new page",
|
|
21
|
+
"Manual tasks are not yet supported on the new page. Return to the legacy page to process this task.": "Manual tasks are not yet supported on the new page. Return to the legacy page to process this task.",
|
|
20
22
|
"My manual tasks": "My manual tasks",
|
|
21
23
|
"Negotiation": "Negotiation",
|
|
22
24
|
"Please check one of your update record form, and add at least one filter condition in form settings.": "Please check one of your update record form, and add at least one filter condition in form settings.",
|
|
25
|
+
"Return to legacy page": "Return to legacy page",
|
|
23
26
|
"Save temporarily": "Save temporarily",
|
|
24
27
|
"Separately": "Separately",
|
|
25
28
|
"Task": "Task",
|
|
@@ -33,4 +36,4 @@
|
|
|
33
36
|
"Values preset in this form will override user submitted ones when continue or reject.": "Values preset in this form will override user submitted ones when continue or reject.",
|
|
34
37
|
"View user interface": "View user interface",
|
|
35
38
|
"Workflow todos": "Workflow todos"
|
|
36
|
-
}
|
|
39
|
+
}
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -17,9 +17,12 @@
|
|
|
17
17
|
"Field name existed in form": "表单中已有对应标识的字段",
|
|
18
18
|
"Filter settings": "筛选设置",
|
|
19
19
|
"Manual": "人工处理",
|
|
20
|
+
"Manual task cannot be processed on the new page": "人工任务无法在新版页面中处理",
|
|
21
|
+
"Manual tasks are not yet supported on the new page. Return to the legacy page to process this task.": "新版页面暂不支持处理人工任务,请返回旧版页面处理该任务。",
|
|
20
22
|
"My manual tasks": "我的人工任务",
|
|
21
23
|
"Negotiation": "协商机制",
|
|
22
24
|
"Please check one of your update record form, and add at least one filter condition in form settings.": "请检查您的其中的更新数据表单,并在表单设置中至少添加一个筛选条件。",
|
|
25
|
+
"Return to legacy page": "返回旧版页面",
|
|
23
26
|
"Save temporarily": "暂存",
|
|
24
27
|
"Separately": "分别处理",
|
|
25
28
|
"Task": "Task",
|
|
@@ -33,4 +36,4 @@
|
|
|
33
36
|
"Values preset in this form will override user submitted ones when continue or reject.": "表单中预设的字段值会在用户提交继续或拒绝时覆盖相应字段的值。",
|
|
34
37
|
"View user interface": "查看界面",
|
|
35
38
|
"Workflow todos": "工作流待办"
|
|
36
|
-
}
|
|
39
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"joi","description":"Object schema validation","version":"17.13.3","repository":"git://github.com/hapijs/joi","main":"lib/index.js","types":"lib/index.d.ts","browser":"dist/joi-browser.min.js","files":["lib/**/*","dist/*"],"keywords":["schema","validation"],"dependencies":{"@hapi/hoek":"^9.3.0","@hapi/topo":"^5.1.0","@sideway/address":"^4.1.5","@sideway/formula":"^3.0.1","@sideway/pinpoint":"^2.0.0"},"devDependencies":{"@hapi/bourne":"2.x.x","@hapi/code":"8.x.x","@hapi/joi-legacy-test":"npm:@hapi/joi@15.x.x","@hapi/lab":"^25.1.3","@types/node":"^14.18.63","typescript":"4.3.x"},"scripts":{"prepublishOnly":"cd browser && npm install && npm run build","test":"lab -t 100 -a @hapi/code -L -Y","test-cov-html":"lab -r html -o coverage.html -a @hapi/code"},"license":"BSD-3-Clause","_lastModified":"2026-07-
|
|
1
|
+
{"name":"joi","description":"Object schema validation","version":"17.13.3","repository":"git://github.com/hapijs/joi","main":"lib/index.js","types":"lib/index.d.ts","browser":"dist/joi-browser.min.js","files":["lib/**/*","dist/*"],"keywords":["schema","validation"],"dependencies":{"@hapi/hoek":"^9.3.0","@hapi/topo":"^5.1.0","@sideway/address":"^4.1.5","@sideway/formula":"^3.0.1","@sideway/pinpoint":"^2.0.0"},"devDependencies":{"@hapi/bourne":"2.x.x","@hapi/code":"8.x.x","@hapi/joi-legacy-test":"npm:@hapi/joi@15.x.x","@hapi/lab":"^25.1.3","@types/node":"^14.18.63","typescript":"4.3.x"},"scripts":{"prepublishOnly":"cd browser && npm install && npm run build","test":"lab -t 100 -a @hapi/code -L -Y","test-cov-html":"lab -r html -o coverage.html -a @hapi/code"},"license":"BSD-3-Clause","_lastModified":"2026-07-30T03:57:12.870Z"}
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { Registry } from '@nocobase/utils';
|
|
10
|
-
import WorkflowPlugin, {
|
|
10
|
+
import WorkflowPlugin, { Instruction, Processor } from '@nocobase/plugin-workflow';
|
|
11
|
+
import type { FlowNodeModel, JobModel } from '@nocobase/plugin-workflow';
|
|
11
12
|
import { FormHandler } from './forms';
|
|
12
13
|
type FormType = {
|
|
13
14
|
type: 'custom' | 'create' | 'update';
|
|
@@ -31,7 +32,7 @@ export default class extends Instruction {
|
|
|
31
32
|
workflow: WorkflowPlugin;
|
|
32
33
|
formTypes: Registry<FormHandler>;
|
|
33
34
|
constructor(workflow: WorkflowPlugin);
|
|
34
|
-
run(node: any, prevJob: any, processor: Processor): Promise<
|
|
35
|
-
resume(node:
|
|
35
|
+
run(node: any, prevJob: any, processor: Processor): Promise<JobModel>;
|
|
36
|
+
resume(node: FlowNodeModel, job: JobModel, processor: Processor): Promise<JobModel>;
|
|
36
37
|
}
|
|
37
38
|
export {};
|
|
@@ -42,64 +42,6 @@ module.exports = __toCommonJS(ManualInstruction_exports);
|
|
|
42
42
|
var import_utils = require("@nocobase/utils");
|
|
43
43
|
var import_plugin_workflow = require("@nocobase/plugin-workflow");
|
|
44
44
|
var import_forms = __toESM(require("./forms"));
|
|
45
|
-
const MULTIPLE_ASSIGNED_MODE = {
|
|
46
|
-
SINGLE: Symbol("single"),
|
|
47
|
-
ALL: Symbol("all"),
|
|
48
|
-
ANY: Symbol("any"),
|
|
49
|
-
ALL_PERCENTAGE: Symbol("all percentage"),
|
|
50
|
-
ANY_PERCENTAGE: Symbol("any percentage")
|
|
51
|
-
};
|
|
52
|
-
const Modes = {
|
|
53
|
-
[MULTIPLE_ASSIGNED_MODE.SINGLE]: {
|
|
54
|
-
getStatus(distribution, assignees) {
|
|
55
|
-
const done = distribution.find((item) => item.status !== import_plugin_workflow.JOB_STATUS.PENDING && item.count > 0);
|
|
56
|
-
return done ? done.status : null;
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
[MULTIPLE_ASSIGNED_MODE.ALL]: {
|
|
60
|
-
getStatus(distribution, assignees) {
|
|
61
|
-
const resolved = distribution.find((item) => item.status === import_plugin_workflow.JOB_STATUS.RESOLVED);
|
|
62
|
-
if (resolved && resolved.count === assignees.length) {
|
|
63
|
-
return import_plugin_workflow.JOB_STATUS.RESOLVED;
|
|
64
|
-
}
|
|
65
|
-
const rejected = distribution.find((item) => item.status < import_plugin_workflow.JOB_STATUS.PENDING);
|
|
66
|
-
if (rejected && rejected.count) {
|
|
67
|
-
return rejected.status;
|
|
68
|
-
}
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
[MULTIPLE_ASSIGNED_MODE.ANY]: {
|
|
73
|
-
getStatus(distribution, assignees) {
|
|
74
|
-
const resolved = distribution.find((item) => item.status === import_plugin_workflow.JOB_STATUS.RESOLVED);
|
|
75
|
-
if (resolved && resolved.count) {
|
|
76
|
-
return import_plugin_workflow.JOB_STATUS.RESOLVED;
|
|
77
|
-
}
|
|
78
|
-
const rejectedCount = distribution.reduce(
|
|
79
|
-
(count, item) => item.status < import_plugin_workflow.JOB_STATUS.PENDING ? count + item.count : count,
|
|
80
|
-
0
|
|
81
|
-
);
|
|
82
|
-
if (rejectedCount === assignees.length) {
|
|
83
|
-
return import_plugin_workflow.JOB_STATUS.REJECTED;
|
|
84
|
-
}
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
function getMode(mode) {
|
|
90
|
-
switch (true) {
|
|
91
|
-
case mode === 1:
|
|
92
|
-
return Modes[MULTIPLE_ASSIGNED_MODE.ALL];
|
|
93
|
-
case mode === -1:
|
|
94
|
-
return Modes[MULTIPLE_ASSIGNED_MODE.ANY];
|
|
95
|
-
case mode > 0:
|
|
96
|
-
return Modes[MULTIPLE_ASSIGNED_MODE.ALL_PERCENTAGE];
|
|
97
|
-
case mode < 0:
|
|
98
|
-
return Modes[MULTIPLE_ASSIGNED_MODE.ANY_PERCENTAGE];
|
|
99
|
-
default:
|
|
100
|
-
return Modes[MULTIPLE_ASSIGNED_MODE.SINGLE];
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
45
|
class ManualInstruction_default extends import_plugin_workflow.Instruction {
|
|
104
46
|
constructor(workflow) {
|
|
105
47
|
super(workflow);
|
|
@@ -136,35 +78,7 @@ class ManualInstruction_default extends import_plugin_workflow.Instruction {
|
|
|
136
78
|
return job;
|
|
137
79
|
}
|
|
138
80
|
async resume(node, job, processor) {
|
|
139
|
-
|
|
140
|
-
const { mode } = node.config;
|
|
141
|
-
const TaskRepo = this.workflow.app.db.getRepository("workflowManualTasks");
|
|
142
|
-
const tasks = await TaskRepo.find({
|
|
143
|
-
where: {
|
|
144
|
-
jobId: job.id
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
const assignees = [];
|
|
148
|
-
const distributionMap = tasks.reduce((result2, item) => {
|
|
149
|
-
if (result2[item.status] == null) {
|
|
150
|
-
result2[item.status] = 0;
|
|
151
|
-
}
|
|
152
|
-
result2[item.status] += 1;
|
|
153
|
-
assignees.push(item.userId);
|
|
154
|
-
return result2;
|
|
155
|
-
}, {});
|
|
156
|
-
const distribution = Object.keys(distributionMap).map((status2) => ({
|
|
157
|
-
status: Number.parseInt(status2, 10),
|
|
158
|
-
count: distributionMap[status2]
|
|
159
|
-
}));
|
|
160
|
-
const submitted = tasks.reduce((count, item) => item.status !== import_plugin_workflow.JOB_STATUS.PENDING ? count + 1 : count, 0);
|
|
161
|
-
const status = job.status || (getMode(mode).getStatus(distribution, assignees) ?? import_plugin_workflow.JOB_STATUS.PENDING);
|
|
162
|
-
const result = mode ? (submitted || 0) / assignees.length : ((_a = job.latestTask) == null ? void 0 : _a.result) ?? job.result;
|
|
163
|
-
processor.logger.debug(`manual resume job and next status: ${status}`);
|
|
164
|
-
job.set({
|
|
165
|
-
status,
|
|
166
|
-
result
|
|
167
|
-
});
|
|
81
|
+
processor.logger.debug(`manual resume job and next status: ${job.status}`);
|
|
168
82
|
return job;
|
|
169
83
|
}
|
|
170
84
|
}
|
package/dist/server/Plugin.d.ts
CHANGED
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
import { Plugin } from '@nocobase/server';
|
|
10
10
|
import { Model } from '@nocobase/database';
|
|
11
11
|
export default class extends Plugin {
|
|
12
|
+
private mergeTaskCounts;
|
|
13
|
+
private collectManualTaskStats;
|
|
14
|
+
private updateManualWorkflowTaskStats;
|
|
15
|
+
private getWorkflowKeyById;
|
|
12
16
|
private updateManualTaskStats;
|
|
13
17
|
onTaskSave: (task: Model, { transaction }: {
|
|
14
18
|
transaction: any;
|
package/dist/server/Plugin.js
CHANGED
|
@@ -45,18 +45,62 @@ var jobActions = __toESM(require("./actions"));
|
|
|
45
45
|
var import_ManualInstruction = __toESM(require("./ManualInstruction"));
|
|
46
46
|
var import_constants = require("../common/constants");
|
|
47
47
|
class Plugin_default extends import_server.Plugin {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
mergeTaskCounts(statsMap, rows, workflowKeyMap, field) {
|
|
49
|
+
for (const row of rows) {
|
|
50
|
+
const userId = row.userId;
|
|
51
|
+
const workflowKey = workflowKeyMap.get(row.workflowId);
|
|
52
|
+
if (!userId || !workflowKey) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const key = `${userId}\0${workflowKey}`;
|
|
56
|
+
const stats = statsMap.get(key) ?? {
|
|
57
|
+
userId,
|
|
58
|
+
workflowKey,
|
|
59
|
+
type: import_constants.TASK_TYPE_MANUAL,
|
|
60
|
+
pending: 0,
|
|
61
|
+
all: 0
|
|
62
|
+
};
|
|
63
|
+
stats[field] += Number(row.count) || 0;
|
|
64
|
+
statsMap.set(key, stats);
|
|
51
65
|
}
|
|
66
|
+
}
|
|
67
|
+
async collectManualTaskStats(options) {
|
|
68
|
+
var _a, _b;
|
|
52
69
|
const workflowPlugin = this.app.pm.get(import_plugin_workflow.default);
|
|
53
70
|
const WorkflowManualTaskModel = this.db.getModel("workflowManualTasks");
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
71
|
+
const qualifiedColumn = (name) => {
|
|
72
|
+
const fieldName = WorkflowManualTaskModel.getAttributes()[name].field ?? name;
|
|
73
|
+
return this.db.sequelize.col(`${WorkflowManualTaskModel.name}.${fieldName}`);
|
|
74
|
+
};
|
|
75
|
+
const group = ["userId", "workflowId"].map((name) => qualifiedColumn(name));
|
|
76
|
+
const countColumn = qualifiedColumn("id");
|
|
77
|
+
const where = {};
|
|
78
|
+
if ((_a = options.userIds) == null ? void 0 : _a.length) {
|
|
79
|
+
where.userId = options.userIds;
|
|
80
|
+
}
|
|
81
|
+
if ((_b = options.workflowKeys) == null ? void 0 : _b.length) {
|
|
82
|
+
const workflowIds2 = (await Promise.all(
|
|
83
|
+
options.workflowKeys.map(
|
|
84
|
+
(workflowKey) => workflowPlugin.getWorkflowIdsByKey(workflowKey, options.transaction)
|
|
85
|
+
)
|
|
86
|
+
)).flat();
|
|
87
|
+
if (!workflowIds2.length) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
where.workflowId = workflowIds2;
|
|
91
|
+
}
|
|
92
|
+
const allCounts = await WorkflowManualTaskModel.findAll({
|
|
93
|
+
attributes: ["userId", "workflowId", [this.db.sequelize.fn("COUNT", countColumn), "count"]],
|
|
94
|
+
where,
|
|
95
|
+
group,
|
|
96
|
+
raw: true,
|
|
97
|
+
transaction: options.transaction
|
|
98
|
+
});
|
|
99
|
+
const pendingCounts = await WorkflowManualTaskModel.findAll({
|
|
100
|
+
attributes: ["userId", "workflowId", [this.db.sequelize.fn("COUNT", countColumn), "count"]],
|
|
57
101
|
where: {
|
|
58
|
-
|
|
59
|
-
|
|
102
|
+
...where,
|
|
103
|
+
status: import_constants.TASK_STATUS.PENDING
|
|
60
104
|
},
|
|
61
105
|
include: [
|
|
62
106
|
{
|
|
@@ -68,58 +112,87 @@ class Plugin_default extends import_server.Plugin {
|
|
|
68
112
|
required: true
|
|
69
113
|
}
|
|
70
114
|
],
|
|
71
|
-
|
|
72
|
-
|
|
115
|
+
group,
|
|
116
|
+
raw: true,
|
|
117
|
+
transaction: options.transaction
|
|
118
|
+
});
|
|
119
|
+
const workflowIds = Array.from(new Set([...allCounts, ...pendingCounts].map((row) => row.workflowId)));
|
|
120
|
+
const workflows = workflowIds.length ? await this.db.getRepository("workflows").find({
|
|
121
|
+
filter: { id: workflowIds },
|
|
122
|
+
fields: ["id", "key"],
|
|
123
|
+
transaction: options.transaction
|
|
124
|
+
}) : [];
|
|
125
|
+
const workflowKeyMap = new Map(
|
|
126
|
+
workflows.map((workflow) => [workflow.id, workflow.key])
|
|
127
|
+
);
|
|
128
|
+
const statsMap = /* @__PURE__ */ new Map();
|
|
129
|
+
this.mergeTaskCounts(statsMap, allCounts, workflowKeyMap, "all");
|
|
130
|
+
this.mergeTaskCounts(statsMap, pendingCounts, workflowKeyMap, "pending");
|
|
131
|
+
return Array.from(statsMap.values());
|
|
132
|
+
}
|
|
133
|
+
async updateManualWorkflowTaskStats(userId, workflowKey, transaction) {
|
|
134
|
+
const workflowPlugin = this.app.pm.get(import_plugin_workflow.default);
|
|
135
|
+
const [row] = await this.collectManualTaskStats({
|
|
136
|
+
userIds: [userId],
|
|
137
|
+
workflowKeys: [workflowKey],
|
|
73
138
|
transaction
|
|
74
139
|
});
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
140
|
+
const stats = row ?? {
|
|
141
|
+
userId,
|
|
142
|
+
workflowKey,
|
|
143
|
+
type: import_constants.TASK_TYPE_MANUAL,
|
|
144
|
+
pending: 0,
|
|
145
|
+
all: 0
|
|
146
|
+
};
|
|
147
|
+
await workflowPlugin.updateTaskStatsByWorkflow(
|
|
148
|
+
{
|
|
149
|
+
userId,
|
|
150
|
+
workflowKey,
|
|
151
|
+
type: import_constants.TASK_TYPE_MANUAL,
|
|
152
|
+
stats
|
|
78
153
|
},
|
|
79
|
-
|
|
80
|
-
|
|
154
|
+
{ transaction }
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
async getWorkflowKeyById(workflowId, transaction) {
|
|
158
|
+
const WorkflowRepo = this.db.getRepository("workflows");
|
|
159
|
+
const workflow = await WorkflowRepo.findOne({
|
|
160
|
+
filterByTk: workflowId,
|
|
161
|
+
fields: ["key"],
|
|
81
162
|
transaction
|
|
82
163
|
});
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
164
|
+
return workflow == null ? void 0 : workflow.key;
|
|
165
|
+
}
|
|
166
|
+
async updateManualTaskStats(userIds, transaction) {
|
|
167
|
+
if (!userIds.length) {
|
|
168
|
+
return;
|
|
88
169
|
}
|
|
89
|
-
|
|
90
|
-
|
|
170
|
+
const workflowPlugin = this.app.pm.get(import_plugin_workflow.default);
|
|
171
|
+
const uniqueUserIds = Array.from(new Set(userIds.filter(Boolean)));
|
|
172
|
+
const rows = await this.collectManualTaskStats({ userIds: uniqueUserIds, transaction });
|
|
173
|
+
for (const row of rows) {
|
|
174
|
+
await workflowPlugin.updateTaskStatsByWorkflow(
|
|
175
|
+
{
|
|
176
|
+
userId: row.userId,
|
|
177
|
+
workflowKey: row.workflowKey,
|
|
178
|
+
type: import_constants.TASK_TYPE_MANUAL,
|
|
179
|
+
stats: row
|
|
180
|
+
},
|
|
181
|
+
{ transaction }
|
|
182
|
+
);
|
|
91
183
|
}
|
|
92
184
|
}
|
|
93
185
|
onTaskSave = async (task, { transaction }) => {
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
attributes: [],
|
|
105
|
-
where: {
|
|
106
|
-
status: import_plugin_workflow.EXECUTION_STATUS.STARTED
|
|
107
|
-
},
|
|
108
|
-
required: true
|
|
109
|
-
}
|
|
110
|
-
],
|
|
111
|
-
col: "id",
|
|
112
|
-
distinct: true,
|
|
113
|
-
transaction
|
|
114
|
-
});
|
|
115
|
-
const all = await ModelClass.count({
|
|
116
|
-
where: {
|
|
117
|
-
userId: task.userId
|
|
118
|
-
},
|
|
119
|
-
col: "id",
|
|
120
|
-
transaction
|
|
121
|
-
});
|
|
122
|
-
await workflowPlugin.updateTasksStats(task.userId, import_constants.TASK_TYPE_MANUAL, { pending, all }, { transaction });
|
|
186
|
+
const userId = task.get("userId");
|
|
187
|
+
const workflowId = task.get("workflowId");
|
|
188
|
+
if (!userId || !workflowId) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const workflowKey = await this.getWorkflowKeyById(workflowId, transaction);
|
|
192
|
+
if (!workflowKey) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
await this.updateManualWorkflowTaskStats(userId, workflowKey, transaction);
|
|
123
196
|
};
|
|
124
197
|
onExecutionStatusChange = async (execution, { transaction }) => {
|
|
125
198
|
if (!execution.status) {
|
|
@@ -167,105 +240,15 @@ class Plugin_default extends import_server.Plugin {
|
|
|
167
240
|
await this.updateManualTaskStats(userIds, transaction);
|
|
168
241
|
};
|
|
169
242
|
onWorkflowStatusChange = async (workflow, { transaction }) => {
|
|
170
|
-
const workflowPlugin = this.app.pm.get(import_plugin_workflow.default);
|
|
171
243
|
const WorkflowManualTaskModel = this.db.getModel("workflowManualTasks");
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
where: {
|
|
181
|
-
status: import_constants.TASK_STATUS.PENDING,
|
|
182
|
-
workflowId
|
|
183
|
-
},
|
|
184
|
-
include: [
|
|
185
|
-
{
|
|
186
|
-
association: "execution",
|
|
187
|
-
attributes: [],
|
|
188
|
-
where: {
|
|
189
|
-
status: import_plugin_workflow.EXECUTION_STATUS.STARTED
|
|
190
|
-
},
|
|
191
|
-
required: true
|
|
192
|
-
}
|
|
193
|
-
],
|
|
194
|
-
col: "id",
|
|
195
|
-
group: ["userId"],
|
|
196
|
-
transaction
|
|
197
|
-
});
|
|
198
|
-
allCounts = await WorkflowManualTaskModel.count({
|
|
199
|
-
where: {
|
|
200
|
-
workflowId
|
|
201
|
-
},
|
|
202
|
-
col: "id",
|
|
203
|
-
group: ["userId"],
|
|
204
|
-
transaction
|
|
205
|
-
});
|
|
206
|
-
} else {
|
|
207
|
-
enalbedSet.delete(workflow.id);
|
|
208
|
-
const workflowId = [...enalbedSet];
|
|
209
|
-
const tasksByUser = await WorkflowManualTaskModel.count({
|
|
210
|
-
col: "userId",
|
|
211
|
-
where: {
|
|
212
|
-
status: import_constants.TASK_STATUS.PENDING,
|
|
213
|
-
workflowId: workflow.id
|
|
214
|
-
},
|
|
215
|
-
distinct: true,
|
|
216
|
-
group: ["userId"],
|
|
217
|
-
transaction
|
|
218
|
-
});
|
|
219
|
-
const userId = [];
|
|
220
|
-
for (const item of tasksByUser) {
|
|
221
|
-
userId.push(item.userId);
|
|
222
|
-
userStatsMap.set(item.userId, { pending: 0, all: 0 });
|
|
223
|
-
}
|
|
224
|
-
pendingCounts = await WorkflowManualTaskModel.count({
|
|
225
|
-
where: {
|
|
226
|
-
status: import_constants.TASK_STATUS.PENDING,
|
|
227
|
-
userId,
|
|
228
|
-
workflowId
|
|
229
|
-
},
|
|
230
|
-
include: [
|
|
231
|
-
{
|
|
232
|
-
association: "execution",
|
|
233
|
-
attributes: [],
|
|
234
|
-
where: {
|
|
235
|
-
status: import_plugin_workflow.EXECUTION_STATUS.STARTED
|
|
236
|
-
},
|
|
237
|
-
required: true
|
|
238
|
-
}
|
|
239
|
-
],
|
|
240
|
-
col: "id",
|
|
241
|
-
group: ["userId"],
|
|
242
|
-
transaction
|
|
243
|
-
});
|
|
244
|
-
allCounts = await WorkflowManualTaskModel.count({
|
|
245
|
-
where: {
|
|
246
|
-
userId,
|
|
247
|
-
workflowId
|
|
248
|
-
},
|
|
249
|
-
col: "id",
|
|
250
|
-
group: ["userId"],
|
|
251
|
-
transaction
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
for (const row of pendingCounts) {
|
|
255
|
-
if (!userStatsMap.get(row.userId)) {
|
|
256
|
-
userStatsMap.set(row.userId, { pending: 0, all: 0 });
|
|
257
|
-
}
|
|
258
|
-
userStatsMap.set(row.userId, { ...userStatsMap.get(row.userId), pending: Number(row.count) || 0 });
|
|
259
|
-
}
|
|
260
|
-
for (const row of allCounts) {
|
|
261
|
-
if (!userStatsMap.get(row.userId)) {
|
|
262
|
-
userStatsMap.set(row.userId, { pending: 0, all: 0 });
|
|
263
|
-
}
|
|
264
|
-
userStatsMap.set(row.userId, { ...userStatsMap.get(row.userId), all: Number(row.count) || 0 });
|
|
265
|
-
}
|
|
266
|
-
for (const [userId, stats] of userStatsMap.entries()) {
|
|
267
|
-
await workflowPlugin.updateTasksStats(userId, import_constants.TASK_TYPE_MANUAL, stats, { transaction });
|
|
268
|
-
}
|
|
244
|
+
const rows = await WorkflowManualTaskModel.findAll({
|
|
245
|
+
attributes: ["userId"],
|
|
246
|
+
where: {
|
|
247
|
+
workflowId: workflow.id
|
|
248
|
+
},
|
|
249
|
+
transaction
|
|
250
|
+
});
|
|
251
|
+
await this.updateManualTaskStats(rows.map((row) => row.get("userId")).filter(Boolean), transaction);
|
|
269
252
|
};
|
|
270
253
|
async load() {
|
|
271
254
|
this.app.resourceManager.define({
|
|
@@ -275,7 +258,11 @@ class Plugin_default extends import_server.Plugin {
|
|
|
275
258
|
this.app.acl.allow("workflowManualTasks", ["listMine", "get", "submit"], "loggedIn");
|
|
276
259
|
const workflowPlugin = this.app.pm.get(import_plugin_workflow.default);
|
|
277
260
|
workflowPlugin.registerInstruction("manual", import_ManualInstruction.default);
|
|
278
|
-
|
|
261
|
+
workflowPlugin.registerTaskStatsProvider(import_constants.TASK_TYPE_MANUAL, {
|
|
262
|
+
collectTaskStats: (options) => this.collectManualTaskStats(options)
|
|
263
|
+
});
|
|
264
|
+
this.db.on("workflowManualTasks.afterCreateWithAssociations", this.onTaskSave);
|
|
265
|
+
this.db.on("workflowManualTasks.afterUpdate", this.onTaskSave);
|
|
279
266
|
this.db.on("workflowManualTasks.afterDestroy", this.onTaskSave);
|
|
280
267
|
this.db.on("executions.afterUpdate", this.onExecutionStatusChange);
|
|
281
268
|
}
|