R36-4 放开跨域转审并同步回归
这个提交包含在:
+33
-27
@@ -54,7 +54,7 @@ const APPROVER_LIST_QUERY_SCHEMA = z.object({
|
||||
});
|
||||
|
||||
const APPROVER_ROLE_CODES = Object.keys(ROLE_PERMISSIONS).filter((roleCode) =>
|
||||
hasPermission(ROLE_PERMISSIONS[roleCode], "expense.approve"),
|
||||
ROLE_PERMISSIONS[roleCode].some((permissionCode) => permissionCode.endsWith(".approve")),
|
||||
);
|
||||
|
||||
function parseRequiredComment(body) {
|
||||
@@ -303,14 +303,12 @@ function listAllowedActionsForTask(request, task, actionable) {
|
||||
|
||||
const actions = [];
|
||||
const approvePermission = resolveEntityPermission(task.workflow_instance?.entity_type, "approve");
|
||||
if (approvePermission && hasPermission(request.employee.permissionCodes, approvePermission)) {
|
||||
const canApprove = approvePermission && hasPermission(request.employee.permissionCodes, approvePermission);
|
||||
if (canApprove) {
|
||||
actions.push("approve", "reject", "return");
|
||||
}
|
||||
|
||||
if (
|
||||
task.workflow_instance?.entity_type === "reimbursement" &&
|
||||
hasPermission(request.employee.permissionCodes, "expense.transfer")
|
||||
) {
|
||||
if (canApprove && hasPermission(request.employee.permissionCodes, "expense.transfer")) {
|
||||
actions.push("transfer");
|
||||
}
|
||||
|
||||
@@ -734,8 +732,8 @@ async function ensureTransferChainNotExceeded(tx, taskId) {
|
||||
|
||||
if (transferCount >= 3) {
|
||||
throw new AppError({
|
||||
code: "VALID_001",
|
||||
message: "参数校验失败",
|
||||
code: "WORKFLOW_003",
|
||||
message: "已达转审上限",
|
||||
statusCode: 409,
|
||||
details: { transfer: "chain_limit_exceeded" },
|
||||
});
|
||||
@@ -744,7 +742,7 @@ async function ensureTransferChainNotExceeded(tx, taskId) {
|
||||
return transferCount;
|
||||
}
|
||||
|
||||
async function ensureTransferTargetEligible(tx, toApproverId) {
|
||||
async function ensureTransferTargetEligible(tx, toApproverId, approvePermission) {
|
||||
const target = await tx.employee.findUnique({
|
||||
where: { id: toApproverId },
|
||||
select: {
|
||||
@@ -769,7 +767,7 @@ async function ensureTransferTargetEligible(tx, toApproverId) {
|
||||
|
||||
const roleCodes = target.roles.map((item) => item.role_code);
|
||||
const permissionCodes = resolvePermissionsForRoles(roleCodes);
|
||||
if (!hasPermission(permissionCodes, "expense.approve")) {
|
||||
if (!approvePermission || !hasPermission(permissionCodes, approvePermission)) {
|
||||
throw new AppError({
|
||||
code: "VALID_001",
|
||||
message: "参数校验失败",
|
||||
@@ -2039,7 +2037,11 @@ async function workflowRoutes(fastify) {
|
||||
const assignment = await ensureTaskAssignableToCurrentEmployee(tx, task, request);
|
||||
|
||||
const workflowInstance = await loadWorkflowInstanceForTask(tx, task.instance_id);
|
||||
if (workflowInstance.entity_type !== "reimbursement") {
|
||||
const approvePermission = resolveEntityPermission(
|
||||
workflowInstance.entity_type,
|
||||
"approve",
|
||||
);
|
||||
if (!approvePermission) {
|
||||
throw new AppError({
|
||||
code: "VALID_001",
|
||||
message: "参数校验失败",
|
||||
@@ -2048,7 +2050,7 @@ async function workflowRoutes(fastify) {
|
||||
});
|
||||
}
|
||||
const transferCount = await ensureTransferChainNotExceeded(tx, taskId);
|
||||
await ensureTransferTargetEligible(tx, toApproverId);
|
||||
await ensureTransferTargetEligible(tx, toApproverId, approvePermission);
|
||||
|
||||
if (toApproverId === request.employee.id) {
|
||||
throw new AppError({
|
||||
@@ -2067,19 +2069,23 @@ async function workflowRoutes(fastify) {
|
||||
},
|
||||
});
|
||||
|
||||
const transfer = await tx.approvalTransfer.create({
|
||||
data: {
|
||||
reimbursement_id: workflowInstance.entity_id,
|
||||
from_approver_id: request.employee.id,
|
||||
to_approver_id: toApproverId,
|
||||
reason,
|
||||
status: "active",
|
||||
created_by: request.employee.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
let transferId = null;
|
||||
if (workflowInstance.entity_type === "reimbursement") {
|
||||
const transfer = await tx.approvalTransfer.create({
|
||||
data: {
|
||||
reimbursement_id: workflowInstance.entity_id,
|
||||
from_approver_id: request.employee.id,
|
||||
to_approver_id: toApproverId,
|
||||
reason,
|
||||
status: "active",
|
||||
created_by: request.employee.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
transferId = transfer.id;
|
||||
}
|
||||
|
||||
await tx.workflowHistory.create({
|
||||
data: {
|
||||
@@ -2137,8 +2143,8 @@ async function workflowRoutes(fastify) {
|
||||
taskId,
|
||||
outcome: "transferred",
|
||||
workflowInstanceId: workflowInstance.id,
|
||||
reimbursementStatus: "reviewing",
|
||||
transferId: transfer.id,
|
||||
reimbursementStatus: workflowInstance.entity_type === "reimbursement" ? "reviewing" : null,
|
||||
transferId,
|
||||
fromApproverId: request.employee.id,
|
||||
toApproverId,
|
||||
transferCount: transferCount + 1,
|
||||
|
||||
在新工单中引用
屏蔽一个用户