mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-09 15:39:24 +08:00
114 lines
3.3 KiB
TypeScript
114 lines
3.3 KiB
TypeScript
/**
|
|
* This file is part of the NocoBase (R) project.
|
|
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
* Authors: NocoBase Team.
|
|
*
|
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
*/
|
|
|
|
import { Context, utils } from '@nocobase/actions';
|
|
import WorkflowPlugin, { EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow';
|
|
|
|
import ManualInstruction from './ManualInstruction';
|
|
|
|
export async function submit(context: Context, next) {
|
|
const repository = utils.getRepositoryFromParams(context);
|
|
const { filterByTk, values } = context.action.params;
|
|
const { currentUser } = context.state;
|
|
|
|
if (!currentUser) {
|
|
return context.throw(401);
|
|
}
|
|
|
|
const plugin: WorkflowPlugin = context.app.getPlugin(WorkflowPlugin);
|
|
const instruction = plugin.instructions.get('manual') as ManualInstruction;
|
|
|
|
const userJob = await repository.findOne({
|
|
filterByTk,
|
|
// filter: {
|
|
// userId: currentUser?.id
|
|
// },
|
|
appends: ['job', 'node', 'execution', 'workflow'],
|
|
context,
|
|
});
|
|
|
|
if (!userJob) {
|
|
return context.throw(404);
|
|
}
|
|
|
|
const { forms = {} } = userJob.node.config;
|
|
const [formKey] = Object.keys(values.result ?? {}).filter((key) => key !== '_');
|
|
const actionKey = values.result?._;
|
|
|
|
const actionItem = forms[formKey]?.actions?.find((item) => item.key === actionKey);
|
|
// NOTE: validate status
|
|
if (
|
|
userJob.status !== JOB_STATUS.PENDING ||
|
|
userJob.job.status !== JOB_STATUS.PENDING ||
|
|
userJob.execution.status !== EXECUTION_STATUS.STARTED ||
|
|
!userJob.workflow.enabled ||
|
|
!actionKey ||
|
|
actionItem?.status == null
|
|
) {
|
|
return context.throw(400);
|
|
}
|
|
|
|
userJob.execution.workflow = userJob.workflow;
|
|
const processor = plugin.createProcessor(userJob.execution);
|
|
await processor.prepare();
|
|
|
|
// NOTE: validate assignee
|
|
const assignees = processor
|
|
.getParsedValue(userJob.node.config.assignees ?? [], userJob.nodeId)
|
|
.flat()
|
|
.filter(Boolean);
|
|
if (!assignees.includes(currentUser.id) || userJob.userId !== currentUser.id) {
|
|
return context.throw(403);
|
|
}
|
|
const presetValues = processor.getParsedValue(actionItem.values ?? {}, userJob.nodeId, {
|
|
additionalScope: {
|
|
// @deprecated
|
|
currentUser: currentUser,
|
|
// @deprecated
|
|
currentRecord: values.result[formKey],
|
|
// @deprecated
|
|
currentTime: new Date(),
|
|
$user: currentUser,
|
|
$nForm: values.result[formKey],
|
|
$nDate: {
|
|
now: new Date(),
|
|
},
|
|
},
|
|
});
|
|
|
|
userJob.set({
|
|
status: actionItem.status,
|
|
result: actionItem.status
|
|
? { [formKey]: Object.assign(values.result[formKey], presetValues), _: actionKey }
|
|
: Object.assign(userJob.result ?? {}, values.result),
|
|
});
|
|
|
|
const handler = instruction.formTypes.get(forms[formKey].type);
|
|
if (handler && userJob.status) {
|
|
await handler.call(instruction, userJob, forms[formKey], processor);
|
|
}
|
|
|
|
await userJob.save();
|
|
|
|
await processor.exit();
|
|
|
|
context.body = userJob;
|
|
context.status = 202;
|
|
|
|
await next();
|
|
|
|
userJob.job.execution = userJob.execution;
|
|
userJob.job.latestUserJob = userJob;
|
|
|
|
// NOTE: resume the process and no `await` for quick returning
|
|
processor.logger.info(`manual node (${userJob.nodeId}) action trigger execution (${userJob.execution.id}) to resume`);
|
|
|
|
plugin.resume(userJob.job);
|
|
}
|