修正CEO报销财务兜底与部署护栏(07-28-ceo-finance-fallback)
这个提交包含在:
@@ -14,7 +14,7 @@ function buildCreatePayload(roleCode) {
|
||||
level1Role: roleCode,
|
||||
level2Role: null,
|
||||
level3Role: null,
|
||||
ownerSelfFallbackRole: "finance_mgr",
|
||||
ownerSelfFallbackRole: "finance",
|
||||
enabled: true,
|
||||
priority: 1,
|
||||
};
|
||||
@@ -82,6 +82,74 @@ async function buildApp() {
|
||||
}
|
||||
|
||||
describe("reimbursement approval-rule role whitelist", () => {
|
||||
it.each(["finance", "finance_mgr"])(
|
||||
"allows owner self fallback role %s",
|
||||
async (fallbackRole) => {
|
||||
const testApp = await buildApp();
|
||||
try {
|
||||
const response = await testApp.app.inject({
|
||||
method: "POST",
|
||||
url: "/api/approval-rules",
|
||||
payload: {
|
||||
...buildCreatePayload("manager"),
|
||||
ownerSelfFallbackRole: fallbackRole,
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data.ownerSelfFallbackRole).toBe(fallbackRole);
|
||||
} finally {
|
||||
await testApp.app.close();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it("defaults owner self fallback to finance when omitted", async () => {
|
||||
const testApp = await buildApp();
|
||||
try {
|
||||
const payload = buildCreatePayload("manager");
|
||||
delete payload.ownerSelfFallbackRole;
|
||||
const response = await testApp.app.inject({
|
||||
method: "POST",
|
||||
url: "/api/approval-rules",
|
||||
payload,
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json().data.ownerSelfFallbackRole).toBe("finance");
|
||||
expect(testApp.approvalRuleCreate).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({ owner_self_fallback_role: "finance" }),
|
||||
}),
|
||||
);
|
||||
} finally {
|
||||
await testApp.app.close();
|
||||
}
|
||||
});
|
||||
|
||||
it.each(["admin", "system_admin", "hr"])(
|
||||
"rejects owner self fallback role %s",
|
||||
async (fallbackRole) => {
|
||||
const testApp = await buildApp();
|
||||
try {
|
||||
const response = await testApp.app.inject({
|
||||
method: "POST",
|
||||
url: "/api/approval-rules",
|
||||
payload: {
|
||||
...buildCreatePayload("manager"),
|
||||
ownerSelfFallbackRole: fallbackRole,
|
||||
},
|
||||
});
|
||||
|
||||
expect(response.statusCode).toBe(400);
|
||||
expect(response.json().error.code).toBe("VALID_001");
|
||||
expect(testApp.transaction).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
await testApp.app.close();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
it.each(["manager", "ceo", "finance", "finance_mgr"])(
|
||||
"allows role %s because it carries expense.approve",
|
||||
async (roleCode) => {
|
||||
|
||||
在新工单中引用
屏蔽一个用户