@tachybase/plugin-workflow-approval
Version:
Approval base in Workflow
267 lines (266 loc) • 9.39 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var approvals_exports = {};
__export(approvals_exports, {
approvals: () => approvals
});
module.exports = __toCommonJS(approvals_exports);
var import_module_workflow = require("@tachybase/module-workflow");
var import_server = require("@tego/server");
var import_constants = require("../../common/constants");
var import_status = require("../constants/status");
var import_tools = require("../tools");
const approvals = {
async create(context, next) {
const { status, collectionName, data, workflowId, workflowKey } = context.action.params.values ?? {};
const [dataSourceName, cName] = (0, import_server.parseCollectionName)(collectionName);
const dataSource = context.app.dataSourceManager.dataSources.get(dataSourceName);
if (!dataSource) {
return context.throw(400, `Data source "${dataSourceName}" not found`);
}
const collection = dataSource.collectionManager.getCollection(cName);
if (!collection) {
return context.throw(400, `Collection "${cName}" not found`);
}
let workflow;
if (workflowKey) {
workflow = await context.db.getRepository("workflows").findOne({
filter: {
key: workflowKey,
enabled: true
}
});
} else {
workflow = await context.db.getRepository("workflows").findOne({
filterByTk: workflowId
});
}
if (!workflow) {
return context.throw(400, "Current workflow not found or disabled, please refresh and try again");
}
if (status !== import_status.APPROVAL_STATUS.DRAFT) {
context.action.mergeParams({
values: {
status: import_status.APPROVAL_STATUS.SUBMITTED
}
});
}
const { repository, model } = collection;
const values = await repository.create({
values: {
...(0, import_server.traverseJSON)(data, { collection }),
createdBy: context.state.currentUser.id,
updatedBy: context.state.currentUser.id
},
context
});
const instance = values.get();
const summary = (0, import_tools.getSummary)({
summaryConfig: workflow.config.summary,
data: {
...instance,
...data
}
});
Object.keys(model.associations).forEach((key) => {
delete instance[key];
});
context.action.mergeParams({
values: {
collectionName,
data: instance,
dataKey: values[collection.filterTargetKey],
workflowKey: workflow.key,
workflowId: workflow.id,
applicantRoleName: context.state.currentRole,
summary
}
});
return import_server.actions.create(context, next);
},
async update(context, next) {
const { collectionName, data, status, updateAssociationValues, summaryConfig } = context.action.params.values ?? {};
const [dataSourceName, cName] = (0, import_server.parseCollectionName)(collectionName);
const dataSource = context.app.dataSourceManager.dataSources.get(dataSourceName);
const collection = dataSource.collectionManager.getCollection(cName);
const [target] = await collection.repository.update({
filterByTk: data[collection.filterTargetKey],
values: data,
updateAssociationValues
});
const summary = (0, import_tools.getSummary)({
summaryConfig,
data
});
context.action.mergeParams({
values: {
status: status ?? import_status.APPROVAL_STATUS.SUBMITTED,
data,
applicantRoleName: context.state.currentRole,
summary
}
});
return import_server.actions.update(context, next);
},
async destroy(context, next) {
const {
filterByTk,
values: { status }
} = context.action.params ?? {};
if (status !== import_status.APPROVAL_STATUS.DRAFT) {
return context.throw(400);
}
const repository = import_server.utils.getRepositoryFromParams(context);
const approval = await repository.findOne({
filterByTk,
filter: {
createdById: context.state.currentUser.id
}
});
if (!approval) {
return context.throw(404);
}
return import_server.actions.destroy(context, next);
},
async withdraw(context, next) {
var _a;
const { filterByTk } = context.action.params;
const repository = import_server.utils.getRepositoryFromParams(context);
const approval = await repository.findOne({
filterByTk,
appends: ["workflow"],
except: ["workflow.options"]
});
if (!approval) {
return context.throw(404);
}
if (approval.createdById !== ((_a = context.state.currentUser) == null ? void 0 : _a.id)) {
return context.throw(403);
}
if (approval.status !== import_status.APPROVAL_STATUS.SUBMITTED || !approval.workflow.config.withdrawable) {
return context.throw(400);
}
const [execution] = await approval.getExecutions({
where: {
status: import_module_workflow.EXECUTION_STATUS.STARTED
},
limit: 1
});
execution.workflow = approval.workflow;
await context.db.sequelize.transaction(async (transaction) => {
const records = await approval.getRecords({
where: {
executionId: execution.id
},
include: [
{
association: "job",
where: {
status: import_module_workflow.JOB_STATUS.PENDING
},
required: true
}
],
transaction
});
await context.db.getRepository("approvalRecords").destroy({
filter: {
id: records.map((record) => record.id)
},
transaction
});
const jobsMap = records.reduce((map, record) => {
if (!map.has(record.job.id)) {
record.job.execution = execution;
record.job.latestUserJob = record.get();
record.job.latestUserJob.approval = approval;
map.set(record.job.id, record.job);
}
return map;
}, /* @__PURE__ */ new Map());
return Array.from(jobsMap.values());
});
context.body = approval;
context.status = 202;
await next();
await execution.update({
status: import_module_workflow.EXECUTION_STATUS.CANCELED
});
},
async listCentralized(context, next) {
const centralizedApprovalFlow = await context.db.getRepository("workflows").find({
filter: {
type: "approval",
"config.centralized": true
},
fields: ["id"]
});
context.action.mergeParams({
filter: {
workflowId: centralizedApprovalFlow.map((item) => item.id)
}
});
return await import_server.actions.list(context, next);
},
async reminder(context, next) {
var _a, _b, _c;
const { filterByTk } = context.action.params;
const repository = import_server.utils.getRepositoryFromParams(context);
const approval = await repository.findOne({
filterByTk,
appends: ["records", "workflow", "createdBy.nickname"]
});
if (!approval) {
return context.throw(404);
}
if (approval.createdById !== ((_a = context.state.currentUser) == null ? void 0 : _a.id)) {
return context.throw(403);
}
if ([import_status.APPROVAL_STATUS.APPROVED, import_status.APPROVAL_STATUS.REJECTED, import_status.APPROVAL_STATUS.ERROR].includes(approval.status)) {
return context.throw(400);
}
if (((_b = approval.records) == null ? void 0 : _b.length) === 0) {
return context.throw(400);
}
const assignees = approval.records.map((record) => record.userId);
for (const userId of assignees) {
const [dataSourceName] = (0, import_server.parseCollectionName)(approval.collectionName);
const collection = this.workflow.app.dataSourceManager.dataSources.get(dataSourceName).collectionManager.getCollection(approval.collectionName);
const message = {
userId,
title: `{{t("Approval", { ns: '${import_constants.NAMESPACE}' })}}`,
content: `{{t("{{user}} reminder", { ns: "${import_constants.NAMESPACE}", user: "${approval.createdBy.nickname}" })}}`,
collectionName: approval.collectionName,
jsonContent: approval.summary,
schemaName: (_c = approval.workflow) == null ? void 0 : _c.config.applyDetail,
dataKey: approval.data[collection.filterTargetKey]
};
context.app.messageManager.sendMessage(+userId, message);
}
await next();
context.status = 200;
context.body = {
message: "reminder sent",
success: true
};
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
approvals
});