@nocobase/plugin-workflow-manual 2.3.0-alpha.1 → 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.
@@ -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
- async updateManualTaskStats(userIds, transaction) {
49
- if (!userIds.length) {
50
- return;
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 uniqueUserIds = Array.from(new Set(userIds.filter(Boolean)));
55
- const userStatsMap = new Map(uniqueUserIds.map((userId) => [userId, { pending: 0, all: 0 }]));
56
- const pendingCounts = await WorkflowManualTaskModel.count({
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
- status: import_constants.TASK_STATUS.PENDING,
59
- userId: uniqueUserIds
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
- col: "id",
72
- group: ["userId"],
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 allCounts = await WorkflowManualTaskModel.count({
76
- where: {
77
- userId: uniqueUserIds
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
- col: "id",
80
- group: ["userId"],
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
- for (const row of pendingCounts) {
84
- userStatsMap.set(row.userId, { ...userStatsMap.get(row.userId), pending: Number(row.count) || 0 });
85
- }
86
- for (const row of allCounts) {
87
- userStatsMap.set(row.userId, { ...userStatsMap.get(row.userId), all: Number(row.count) || 0 });
164
+ return workflow == null ? void 0 : workflow.key;
165
+ }
166
+ async updateManualTaskStats(userIds, transaction) {
167
+ if (!userIds.length) {
168
+ return;
88
169
  }
89
- for (const [userId, stats] of userStatsMap.entries()) {
90
- await workflowPlugin.updateTasksStats(userId, import_constants.TASK_TYPE_MANUAL, stats, { transaction });
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 workflowPlugin = this.app.pm.get(import_plugin_workflow.default);
95
- const ModelClass = task.constructor;
96
- const pending = await ModelClass.count({
97
- where: {
98
- userId: task.userId,
99
- status: import_constants.TASK_STATUS.PENDING
100
- },
101
- include: [
102
- {
103
- association: "execution",
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 enalbedSet = new Set(workflowPlugin.enabledCache.keys());
173
- let pendingCounts = [];
174
- let allCounts = [];
175
- const userStatsMap = /* @__PURE__ */ new Map();
176
- if (workflow.enabled) {
177
- enalbedSet.add(workflow.id);
178
- const workflowId = [...enalbedSet];
179
- pendingCounts = await WorkflowManualTaskModel.count({
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
- this.db.on("workflowManualTasks.afterSave", this.onTaskSave);
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
  }
@@ -41,7 +41,62 @@ __export(actions_exports, {
41
41
  });
42
42
  module.exports = __toCommonJS(actions_exports);
43
43
  var import_actions = __toESM(require("@nocobase/actions"));
44
+ var import_database = require("@nocobase/database");
44
45
  var import_plugin_workflow = __toESM(require("@nocobase/plugin-workflow"));
46
+ function getSubmittedRatio(tasks) {
47
+ if (!tasks.length) {
48
+ return 0;
49
+ }
50
+ const submitted = tasks.reduce((count, item) => item.status !== import_plugin_workflow.JOB_STATUS.PENDING ? count + 1 : count, 0);
51
+ return submitted / tasks.length;
52
+ }
53
+ function getSingleModeStatus(distribution) {
54
+ var _a;
55
+ return ((_a = distribution.find((item) => item.status !== import_plugin_workflow.JOB_STATUS.PENDING && item.count > 0)) == null ? void 0 : _a.status) ?? null;
56
+ }
57
+ function getAllModeStatus(distribution, assignees) {
58
+ const resolved = distribution.find((item) => item.status === import_plugin_workflow.JOB_STATUS.RESOLVED);
59
+ if ((resolved == null ? void 0 : resolved.count) === assignees.length) {
60
+ return import_plugin_workflow.JOB_STATUS.RESOLVED;
61
+ }
62
+ const rejected = distribution.find((item) => item.status < import_plugin_workflow.JOB_STATUS.PENDING);
63
+ return (rejected == null ? void 0 : rejected.count) ? rejected.status : null;
64
+ }
65
+ function getAnyModeStatus(distribution, assignees) {
66
+ const resolved = distribution.find((item) => item.status === import_plugin_workflow.JOB_STATUS.RESOLVED);
67
+ if (resolved == null ? void 0 : resolved.count) {
68
+ return import_plugin_workflow.JOB_STATUS.RESOLVED;
69
+ }
70
+ const rejectedCount = distribution.reduce(
71
+ (count, item) => item.status < import_plugin_workflow.JOB_STATUS.PENDING ? count + item.count : count,
72
+ 0
73
+ );
74
+ return rejectedCount === assignees.length ? import_plugin_workflow.JOB_STATUS.REJECTED : null;
75
+ }
76
+ async function updateJobByManualTasks(job, node, database, latestTask, transaction) {
77
+ const mode = node.config.mode ?? 0;
78
+ const tasks = await database.getModel("workflowManualTasks").findAll({
79
+ where: {
80
+ jobId: job.id
81
+ },
82
+ transaction
83
+ });
84
+ const assignees = [];
85
+ const distributionMap = /* @__PURE__ */ new Map();
86
+ for (const task of tasks) {
87
+ distributionMap.set(task.status, (distributionMap.get(task.status) ?? 0) + 1);
88
+ assignees.push(task.userId);
89
+ }
90
+ const distribution = Array.from(distributionMap.entries()).map(([status2, count]) => ({ status: status2, count }));
91
+ const status = mode === 1 ? getAllModeStatus(distribution, assignees) : mode === -1 ? getAnyModeStatus(distribution, assignees) : getSingleModeStatus(distribution);
92
+ await job.update(
93
+ {
94
+ status: status ?? import_plugin_workflow.JOB_STATUS.PENDING,
95
+ result: mode ? getSubmittedRatio(tasks) : latestTask.result ?? job.result
96
+ },
97
+ { transaction }
98
+ );
99
+ }
45
100
  async function submit(context, next) {
46
101
  var _a, _b, _c;
47
102
  const repository = import_actions.utils.getRepositoryFromParams(context);
@@ -78,48 +133,99 @@ async function submit(context, next) {
78
133
  return context.throw(400);
79
134
  }
80
135
  task.execution.workflow = task.workflow;
81
- const processor = plugin.createProcessor(task.execution);
82
- await processor.prepare();
83
- const assignees = processor.getParsedValue(task.node.config.assignees ?? [], task.nodeId).flat().filter(Boolean);
84
- if (!assignees.includes(currentUser.id) || task.userId !== currentUser.id) {
85
- return context.throw(403);
86
- }
87
- const presetValues = processor.getParsedValue(actionItem.values ?? {}, task.nodeId, {
88
- additionalScope: {
89
- // @deprecated
90
- currentUser,
91
- // @deprecated
92
- currentRecord: values.result[formKey],
93
- // @deprecated
94
- currentTime: /* @__PURE__ */ new Date(),
95
- $user: currentUser,
96
- $nForm: values.result[formKey],
97
- $nDate: {
98
- now: /* @__PURE__ */ new Date()
136
+ const formConfig = forms[formKey];
137
+ const handler = instruction.formTypes.get(formConfig.type);
138
+ const usesMainDataSource = (formConfig.dataSource ?? "main") === "main";
139
+ const transactionOptions = context.db.sequelize.getDialect() === "sqlite" ? { type: import_database.Transaction.TYPES.IMMEDIATE } : {};
140
+ const validateTask = () => {
141
+ if (task.status !== import_plugin_workflow.JOB_STATUS.PENDING || task.job.status !== import_plugin_workflow.JOB_STATUS.PENDING || task.execution.status !== import_plugin_workflow.EXECUTION_STATUS.STARTED) {
142
+ return context.throw(400);
143
+ }
144
+ };
145
+ const getPresetValues = (processor) => {
146
+ const assignees = processor.getParsedValue(task.node.config.assignees ?? [], task.nodeId).flat().filter(Boolean);
147
+ if (!assignees.includes(currentUser.id) || task.userId !== currentUser.id) {
148
+ return context.throw(403);
149
+ }
150
+ return processor.getParsedValue(actionItem.values ?? {}, task.nodeId, {
151
+ additionalScope: {
152
+ // @deprecated
153
+ currentUser,
154
+ // @deprecated
155
+ currentRecord: values.result[formKey],
156
+ // @deprecated
157
+ currentTime: /* @__PURE__ */ new Date(),
158
+ $user: currentUser,
159
+ $nForm: values.result[formKey],
160
+ $nDate: {
161
+ now: /* @__PURE__ */ new Date()
162
+ }
99
163
  }
164
+ });
165
+ };
166
+ const setTaskResult = (presetValues) => {
167
+ task.set({
168
+ status: actionItem.status,
169
+ result: actionItem.status ? { [formKey]: { ...values.result[formKey], ...presetValues }, _: actionKey } : { ...task.result ?? {}, ...values.result }
170
+ });
171
+ task.changed("result", true);
172
+ };
173
+ const handleFormSubmission = async (transaction) => {
174
+ const processor = plugin.createProcessor(task.execution, { transaction });
175
+ await processor.prepare();
176
+ const presetValues = getPresetValues(processor);
177
+ setTaskResult(presetValues);
178
+ if (handler && task.status) {
179
+ const { actions: actions2, ...formOptions } = formConfig;
180
+ const parsedFormConfig = {
181
+ ...processor.getParsedValue(formOptions, task.nodeId),
182
+ actions: actions2
183
+ };
184
+ await handler.call(instruction, task, parsedFormConfig, transaction);
100
185
  }
101
- });
102
- task.set({
103
- status: actionItem.status,
104
- result: actionItem.status ? { [formKey]: { ...values.result[formKey], ...presetValues }, _: actionKey } : { ...task.result ?? {}, ...values.result }
105
- });
106
- task.changed("result", true);
107
- const handler = instruction.formTypes.get(forms[formKey].type);
108
- if (handler && task.status) {
109
- await handler.call(instruction, task, forms[formKey], processor);
186
+ return presetValues;
187
+ };
188
+ let shouldResume = false;
189
+ try {
190
+ const lock = await context.app.lockManager.tryAcquire((0, import_plugin_workflow.getJobLockKey)(task.job.id));
191
+ await lock.runExclusive(async () => {
192
+ let presetValues = {};
193
+ if (!usesMainDataSource) {
194
+ await Promise.all([task.reload(), task.job.reload(), task.execution.reload()]);
195
+ validateTask();
196
+ presetValues = await handleFormSubmission();
197
+ }
198
+ await context.db.sequelize.transaction(transactionOptions, async (transaction) => {
199
+ await Promise.all([
200
+ task.reload({ transaction }),
201
+ task.job.reload({ transaction }),
202
+ task.execution.reload({ transaction })
203
+ ]);
204
+ validateTask();
205
+ if (usesMainDataSource) {
206
+ await handleFormSubmission(transaction);
207
+ } else {
208
+ setTaskResult(presetValues);
209
+ }
210
+ await task.save({ transaction });
211
+ await updateJobByManualTasks(task.job, task.node, context.db, task, transaction);
212
+ shouldResume = task.job.status !== import_plugin_workflow.JOB_STATUS.PENDING;
213
+ });
214
+ }, 6e4);
215
+ } catch (error) {
216
+ if ((0, import_plugin_workflow.isLockAcquireError)(error)) {
217
+ return context.throw(409);
218
+ }
219
+ throw error;
110
220
  }
111
- await task.save();
112
- await processor.exit();
113
221
  context.body = task;
114
222
  context.status = 202;
115
223
  await next();
116
- if (task.execution.status !== import_plugin_workflow.EXECUTION_STATUS.STARTED) {
224
+ if (!shouldResume) {
117
225
  return;
118
226
  }
119
- task.job.execution = task.execution;
120
- task.job.latestTask = task;
121
- processor.logger.info(`manual node (${task.nodeId}) action trigger execution (${task.execution.id}) to resume`);
122
- plugin.resume(task.job);
227
+ plugin.getLogger(task.execution.workflowId).info(`manual node (${task.nodeId}) action trigger execution (${task.execution.id}) to resume`);
228
+ plugin.resume(task.job).catch(() => void 0);
123
229
  }
124
230
  async function listMine(context, next) {
125
231
  context.action.mergeParams({
@@ -6,9 +6,9 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- import { Processor } from '@nocobase/plugin-workflow';
9
+ import type { Transaction } from '@nocobase/database';
10
10
  import ManualInstruction from '../ManualInstruction';
11
11
  export default function (this: ManualInstruction, instance: any, { dataSource, collection }: {
12
12
  dataSource?: string;
13
13
  collection: any;
14
- }, processor: Processor): Promise<void>;
14
+ }, transaction?: Transaction): Promise<void>;
@@ -29,7 +29,7 @@ __export(create_exports, {
29
29
  default: () => create_default
30
30
  });
31
31
  module.exports = __toCommonJS(create_exports);
32
- async function create_default(instance, { dataSource = "main", collection }, processor) {
32
+ async function create_default(instance, { dataSource = "main", collection }, transaction) {
33
33
  const repo = this.workflow.app.dataSourceManager.dataSources.get(dataSource).collectionManager.getRepository(collection);
34
34
  if (!repo) {
35
35
  throw new Error(`collection ${collection} for create data on manual node not found`);
@@ -43,8 +43,8 @@ async function create_default(instance, { dataSource = "main", collection }, pro
43
43
  updatedBy: instance.userId
44
44
  },
45
45
  context: {
46
- executionId: processor.execution.id
46
+ executionId: instance.executionId
47
47
  },
48
- transaction: processor.transaction
48
+ transaction
49
49
  });
50
50
  }
@@ -6,9 +6,9 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- import { Processor } from '@nocobase/plugin-workflow';
9
+ import type { Transaction } from '@nocobase/database';
10
10
  import ManualInstruction from '../ManualInstruction';
11
- export type FormHandler = (this: ManualInstruction, instance: any, formConfig: any, processor: Processor) => Promise<void>;
11
+ export type FormHandler = (this: ManualInstruction, instance: any, formConfig: any, transaction?: Transaction) => Promise<void>;
12
12
  export default function ({ formTypes }: {
13
13
  formTypes: any;
14
14
  }): void;
@@ -6,10 +6,10 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- import { Processor } from '@nocobase/plugin-workflow';
9
+ import type { Transaction } from '@nocobase/database';
10
10
  import ManualInstruction from '../ManualInstruction';
11
11
  export default function (this: ManualInstruction, instance: any, { dataSource, collection, filter }: {
12
12
  dataSource?: string;
13
13
  collection: any;
14
14
  filter?: {};
15
- }, processor: Processor): Promise<void>;
15
+ }, transaction?: Transaction): Promise<void>;
@@ -29,7 +29,7 @@ __export(update_exports, {
29
29
  default: () => update_default
30
30
  });
31
31
  module.exports = __toCommonJS(update_exports);
32
- async function update_default(instance, { dataSource = "main", collection, filter = {} }, processor) {
32
+ async function update_default(instance, { dataSource = "main", collection, filter = {} }, transaction) {
33
33
  const repo = this.workflow.app.dataSourceManager.dataSources.get(dataSource).collectionManager.getRepository(collection);
34
34
  if (!repo) {
35
35
  throw new Error(`collection ${collection} for update data on manual node not found`);
@@ -37,14 +37,14 @@ async function update_default(instance, { dataSource = "main", collection, filte
37
37
  const { _, ...form } = instance.result;
38
38
  const [values] = Object.values(form);
39
39
  await repo.update({
40
- filter: processor.getParsedValue(filter, instance.nodeId),
40
+ filter,
41
41
  values: {
42
42
  ...values ?? {},
43
43
  updatedBy: instance.userId
44
44
  },
45
45
  context: {
46
- executionId: processor.execution.id
46
+ executionId: instance.executionId
47
47
  },
48
- transaction: processor.transaction
48
+ transaction
49
49
  });
50
50
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import { Migration } from '@nocobase/server';
10
+ export default class extends Migration {
11
+ on: string;
12
+ up(): Promise<void>;
13
+ }