取消报销资产事前批准强制(08-30-reimbursement-assets-prior-approval-correction)

这个提交包含在:
2026-08-30 12:44:58 +08:00
父节点 0f9f40389e
当前提交 36c86f1dca
共修改 17 个文件,包含 489 行新增和 130 行删除
@@ -83,7 +83,7 @@ function buildExpenseTypes() {
code: "assets_office_electronics",
name: "办公电子设备",
category: "assets",
description: "2,000 元及以上通常选本类型,不等同于会计固定资产标准。",
description: "单条明细金额达到 2,000 元的办公电子设备通常选择本类型;请在明细说明中写明物品名称、实际使用人或责任人、存放位置,便于资产登记。该门槛不等同于会计固定资产确认标准。",
requiresInvoice: true,
enabled: true,
},
@@ -186,6 +186,7 @@ function buildReimbursementState() {
failedInvoices: [buildFailedInvoice()],
statusPollCount: 0,
bindRequests: [] as Array<{ reimbursementId?: string; linkedItemId?: string }>,
itemSaveRequests: [] as Array<Record<string, unknown>>,
submitRequestCount: 0,
invoiceGuardEnabled: false,
detailItems: null as null | Array<Record<string, unknown>>,
@@ -384,6 +385,26 @@ async function mockApis(page: Page, state: ReturnType<typeof buildReimbursementS
return;
}
if (
(pathName === `/api/reimbursements/${reimbursementId}/items` && request.method() === "POST")
|| (pathName.startsWith(`/api/reimbursements/${reimbursementId}/items/`) && request.method() === "PATCH")
) {
const payload = request.postDataJSON() as Record<string, unknown>;
state.itemSaveRequests.push(payload);
await fulfillJson(route, {
item: {
id: "asset-item-r111",
expenseTypeId: payload.expenseTypeId ?? "expense-type-assets-r111",
expenseDate: payload.expenseDate ?? "2026-05-08",
amount: payload.amount ?? "2000.00",
description: payload.description ?? null,
assetPriorApprovalBasis: null,
},
totalAmount: "2000.00",
});
return;
}
if (pathName === `/api/reimbursements/${reimbursementId}/precheck`) {
await fulfillJson(route, {
decision: "pass",
@@ -735,7 +756,7 @@ test.describe("R111 国内报销发票与附件双端体验", () => {
await page.screenshot({ path: screenshotPath("pc-reimbursement-detail.png"), fullPage: true });
});
test("B1/B2 在 PC 和移动端显示设备提示并要求明确关联明细", async ({ page }) => {
test("B1/B2 在 PC 和移动端取消批准依据并保持设备提示与明确关联", async ({ page }) => {
const state = buildReimbursementState();
state.invoiceGuardEnabled = true;
state.detailItems = [{
@@ -758,11 +779,18 @@ test.describe("R111 国内报销发票与附件双端体验", () => {
await login(page);
await page.goto(`/reimbursements/${reimbursementId}`);
await expect(page.getByText("该金额通常应选择办公电子设备并填写事前批准依据。")).toBeVisible();
await expect(page.getByText("该金额通常应选择办公电子设备。")).toBeVisible();
await page.getByTestId("reimbursement-item-add").click();
await page.locator("#expenseTypeId").selectOption("expense-type-office-supplies-r111");
await page.getByTestId("reimbursement-item-amount").fill("2000.00");
await expect(page.getByText("该金额通常应选择办公电子设备。")).toHaveCount(2);
await page.locator("#expenseTypeId").selectOption("expense-type-assets-r111");
await expect(page.getByTestId("reimbursement-item-asset-approval-basis")).toBeVisible();
await expect(page.getByText("2,000 元及以上通常选本类型,不等同于会计固定资产标准。")).toBeVisible();
await expect(page.getByTestId("reimbursement-item-asset-approval-basis")).toHaveCount(0);
await expect(page.getByText(/请在明细说明中写明物品名称、实际使用人或责任人、存放位置/)).toBeVisible();
await page.getByTestId("reimbursement-item-description").fill("合成设备,测试员工使用,测试位置");
await page.getByTestId("reimbursement-item-save").click();
await expect.poll(() => state.itemSaveRequests.length).toBe(1);
expect(state.itemSaveRequests[0]).not.toHaveProperty("assetPriorApprovalBasis");
await page.getByTestId("reimbursement-invoice-add").click();
const invoiceDialog = page.getByTestId("reimbursement-invoice-dialog");
@@ -788,10 +816,17 @@ test.describe("R111 国内报销发票与附件双端体验", () => {
await page.keyboard.press("Escape");
await page.setViewportSize({ width: 390, height: 844 });
await page.goto(`/mobile/reimbursements/${reimbursementId}`);
await expect(page.getByText("该金额通常应选择办公电子设备并填写事前批准依据。")).toBeVisible();
await expect(page.getByText("该金额通常应选择办公电子设备。")).toBeVisible();
await page.getByRole("button", { name: "新增", exact: true }).click();
await page.getByLabel("费用类型").selectOption("expense-type-office-supplies-r111");
await page.getByRole("textbox", { name: "金额", exact: true }).fill("2000.00");
await expect(page.getByText("该金额通常应选择办公电子设备。")).toHaveCount(2);
await page.getByLabel("费用类型").selectOption("expense-type-assets-r111");
await expect(page.getByText("事前批准依据", { exact: true })).toBeVisible();
await expect(page.getByText("事前批准依据", { exact: true })).toHaveCount(0);
await page.getByRole("textbox", { name: "说明", exact: true }).fill("合成设备,测试员工使用,测试位置");
await page.getByRole("button", { name: "保存", exact: true }).click();
await expect.poll(() => state.itemSaveRequests.length).toBe(2);
expect(state.itemSaveRequests[1]).not.toHaveProperty("assetPriorApprovalBasis");
state.invoiceGuardEnabled = false;
state.invoices = [];