FL6 完善财务台账与导出审计

这个提交包含在:
2026-05-12 09:33:45 +08:00
父节点 a0dc6fc408
当前提交 f99fbce3d8
共修改 14 个文件,包含 1005 行新增和 18 行删除
@@ -484,6 +484,7 @@ test.describe("R3 权限直连审计", () => {
try {
await expectApiStatus({ role: "employee", api: employee.api, path: "/api/budgets", statuses: [403], note: "员工不得直连预算" });
await expectApiStatus({ role: "employee", api: employee.api, path: "/api/ap-operations", statuses: [403, 409], note: "员工不得直连 AP;409 表示功能门禁关闭且未泄露数据" });
await expectApiStatus({ role: "employee", api: employee.api, path: "/api/ap-operations/reimbursement-ledger", statuses: [403, 409], note: "员工不得直连财务台账;409 表示功能门禁关闭且未泄露数据" });
await expectApiStatus({ role: "employee", api: employee.api, path: "/api/payment-batches", statuses: [403, 409], note: "员工不得直连付款批次;409 表示功能门禁关闭且未泄露数据" });
await expectApiStatus({ role: "employee", api: employee.api, path: "/api/integrations/erp/master-data/status", statuses: [403], note: "员工不得直连 ERP 管理" });
await expectApiStatus({ role: "employee", api: employee.api, path: "/api/invoice-pool?ownerScope=all", statuses: [403], note: "员工不得查看全量票据" });
@@ -520,6 +521,7 @@ test.describe("R3 权限直连审计", () => {
}
await expectApiStatus({ role: "manager", api: manager.api, path: "/api/ap-operations", statuses: [403, 409], note: "主管不得直连 AP" });
await expectApiStatus({ role: "manager", api: manager.api, path: "/api/ap-operations/reimbursement-ledger", statuses: [403, 409], note: "主管不得直连财务台账" });
await expectApiStatus({ role: "manager", api: manager.api, path: "/api/payment-batches", statuses: [403, 409], note: "主管不得直连付款批次" });
await expectApiStatus({ role: "manager", api: manager.api, path: "/api/integrations/erp/master-data/status", statuses: [403], note: "主管不得直连 ERP 管理" });
await expectApiStatus({ role: "manager", api: manager.api, path: "/api/audit-logs", statuses: [403], note: "主管不得查看审计日志" });
@@ -531,6 +533,7 @@ test.describe("R3 权限直连审计", () => {
await expectApiStatus({ role: "finance", api: finance.api, path: "/api/notifications/deliveries", statuses: [403], note: "普通财务不得查看通知渠道投递审计" });
await expectApiStatus({ role: "finance", api: finance.api, path: "/api/invoice-pool?ownerScope=all&pageSize=20", statuses: [200], note: "财务可看票据财务范围" });
await expectApiStatus({ role: "finance", api: finance.api, path: "/api/payment-batches", statuses: [200, 409], note: "财务可看付款批次或受功能门禁限制" });
await expectApiStatus({ role: "finance", api: finance.api, path: "/api/ap-operations/reimbursement-ledger?pageSize=5", statuses: [200, 409], note: "财务可看财务台账或受功能门禁限制" });
const erpStatus = await expectApiStatus({
role: "finance_mgr",
@@ -158,7 +158,7 @@ test("E2E 报销支付批次主链路:提交 -> 审批 -> 创建批次 -> 复
await login(page, FINANCE_MGR);
await page.goto("/ap-operations");
await expect(page.getByRole("tab", { name: /待付款/ })).toBeVisible();
await page.getByRole("tab", { name: /待付款/ }).click();
const pendingRow = page.locator("tr").filter({ hasText: batchName }).first();
await expect(pendingRow).toBeVisible();
await pendingRow.getByRole("button", { name: "快捷复核" }).click();
@@ -180,8 +180,23 @@ test("E2E 报销支付批次主链路:提交 -> 审批 -> 创建批次 -> 复
await page.goto(`/reimbursements/${reimbursementId}`);
await reimbursementDetail.assertLoaded();
await expect(page.getByText(/状态:(paid|已支付)/)).toBeVisible({ timeout: 30_000 });
await expect(page.getByTestId("reimbursement-payment-status")).toContainText("已付款");
const paymentAudit = await apiGetData<{
items: Array<{ action: string; targetId: string | null; extra: Record<string, unknown> }>;
}>(
adminApi.api,
"/api/audit-logs?action=REIMBURSEMENT_PAYMENT_MARKED&page=1&pageSize=20",
);
expect(
paymentAudit.items.some((item) => item.targetId === reimbursementId && item.extra?.idempotent === false),
"付款动作应写入报销付款审计",
).toBe(true);
await page.goto("/ap-operations");
await expect(page.getByRole("tab", { name: /财务台账/ })).toBeVisible();
await expect(page.getByTestId("finance-ledger-table")).toContainText(reimbursementDisplayCode);
await expect(page.getByTestId("finance-ledger-table")).toContainText("已付款");
await expect(page.getByRole("tab", { name: /待付款/ })).toBeVisible();
await expect(page.getByText(batchName)).toHaveCount(0);