const { DEFAULT_APPROVAL_RULES, DEFAULT_FEATURE_FLAGS, ENABLED_EXPENSE_TYPES, seedApprovalRules, seedExpenseTypes, seedFeatureFlags, } = require("../../../src/scripts/seed-config"); describe("default travel expense types", () => { it("keeps intercity bus tickets separate from the two travel allowances", () => { expect(ENABLED_EXPENSE_TYPES).toEqual( expect.arrayContaining([ expect.objectContaining({ code: "travel_bus", name: "大巴车票", category: "travel" }), expect.objectContaining({ code: "travel_meal", name: "伙食补助费", category: "travel" }), expect.objectContaining({ code: "travel_local_transport_allowance", name: "市内交通补助费", category: "travel", }), ]), ); const travelCodes = ENABLED_EXPENSE_TYPES.filter((item) => ["travel_bus", "travel_meal", "travel_local_transport_allowance"].includes(item.code), ); expect(travelCodes).toHaveLength(3); }); it("upserts the distinct travel types by stable code", async () => { const upsert = vi.fn().mockResolvedValue({}); await seedExpenseTypes({ expenseType: { upsert } }); for (const [code, name] of [ ["travel_bus", "大巴车票"], ["travel_meal", "伙食补助费"], ["travel_local_transport_allowance", "市内交通补助费"], ]) { expect(upsert).toHaveBeenCalledWith( expect.objectContaining({ where: { code }, update: expect.objectContaining({ name, enabled: true }), create: expect.objectContaining({ code, name, enabled: true }), }), ); } }); }); describe("reimbursement expense policy defaults", () => { it("keeps only the two allowances invoice-free and replaces ambiguous selectable types", () => { expect(ENABLED_EXPENSE_TYPES).toEqual(expect.arrayContaining([ expect.objectContaining({ code: "business_client_meal", name: "业务招待费" }), expect.objectContaining({ code: "business_meeting", name: "会议费" }), expect.objectContaining({ code: "business_training_fee", name: "培训费" }), expect.objectContaining({ code: "assets_office_electronics", name: "办公电子设备" }), expect.objectContaining({ code: "travel_meal", requiresInvoice: false }), expect.objectContaining({ code: "travel_local_transport_allowance", requiresInvoice: false }), ])); expect(ENABLED_EXPENSE_TYPES.some((item) => item.code === "business_training")).toBe(false); expect(ENABLED_EXPENSE_TYPES.some((item) => item.code === "assets_it_hardware")).toBe(false); }); it("provides employee-readable guidance for every selectable expense type", () => { for (const expenseType of ENABLED_EXPENSE_TYPES) { expect(expenseType.description, expenseType.code).toEqual(expect.any(String)); expect(expenseType.description.trim().length, expenseType.code).toBeGreaterThan(0); } }); it("uses asset-registration guidance without inventing a prior-approval policy", () => { const assetTypes = ENABLED_EXPENSE_TYPES.filter((item) => item.category === "assets"); expect(assetTypes.map((item) => item.code)).toEqual([ "assets_equipment", "assets_furniture", "assets_office_electronics", ]); for (const expenseType of assetTypes) { expect(expenseType.description).toContain("物品名称"); expect(expenseType.description).toContain("实际使用人或责任人"); expect(expenseType.description).toContain("存放位置"); expect(expenseType.description).not.toMatch(/事前批准|批准人|批准时间|批准依据/); } expect(assetTypes.find((item) => item.code === "assets_office_electronics")?.description) .toContain("不等同于会计固定资产确认标准"); }); it("seeds the invoice guard disabled by default", () => { expect(DEFAULT_FEATURE_FLAGS).toContainEqual({ flag_key: "reimbursement_invoice_guard_v1", override_mode: "force_off", rollout_type: "global", department_ids: [], note: "bootstrap default: force_off", }); }); it("preserves finance-maintained account mappings during repeated init", async () => { const upsert = vi.fn().mockResolvedValue({}); await seedExpenseTypes({ expenseType: { upsert } }); for (const call of upsert.mock.calls) { expect(call[0].update).not.toHaveProperty("account_code_default"); expect(call[0].create).toEqual(expect.objectContaining({ account_code_default: null })); } }); }); describe("small-team default reimbursement approval rules", () => { it("uses finance for every owner fallback and finance review node", () => { expect(DEFAULT_APPROVAL_RULES).toEqual([ expect.objectContaining({ name: "小额", level1_role: "manager", level2_role: "finance", level3_role: null, owner_self_fallback_role: "finance", }), expect.objectContaining({ name: "中额", level1_role: "manager", level2_role: "finance", level3_role: null, owner_self_fallback_role: "finance", }), expect.objectContaining({ name: "大额", level1_role: "manager", level2_role: "ceo", level3_role: "finance", owner_self_fallback_role: "finance", }), ]); }); it("preserves existing production approval rules instead of replacing them", async () => { const approvalRule = { count: vi.fn().mockResolvedValue(3), createMany: vi.fn(), deleteMany: vi.fn(), }; await expect(seedApprovalRules({ approvalRule })).resolves.toEqual({ created: 0, preserved: 3, }); expect(approvalRule.createMany).not.toHaveBeenCalled(); expect(approvalRule.deleteMany).not.toHaveBeenCalled(); }); it("creates the three defaults only for an empty approval-rule table", async () => { const approvalRule = { count: vi.fn().mockResolvedValue(0), createMany: vi.fn().mockResolvedValue({ count: 3 }), }; await expect(seedApprovalRules({ approvalRule })).resolves.toEqual({ created: 3, preserved: 0, }); expect(approvalRule.createMany).toHaveBeenCalledWith({ data: DEFAULT_APPROVAL_RULES.map((item) => ({ ...item, enabled: true, created_by: null, updated_by: null, })), }); }); }); describe("trialrun payment batch baseline", () => { it("creates payment_batch_v1 as globally enabled", () => { expect(DEFAULT_FEATURE_FLAGS).toContainEqual({ flag_key: "payment_batch_v1", override_mode: "force_on", rollout_type: "global", department_ids: [], note: "bootstrap default: force_on", }); }); it("preserves an existing payment flag instead of overwriting it", async () => { const create = vi.fn(async ({ data }) => { if (data.flag_key === "payment_batch_v1") { throw Object.assign(new Error("unique conflict"), { code: "P2002" }); } return data; }); const prisma = { featureFlag: { create } }; await expect(seedFeatureFlags(prisma)).resolves.toBeUndefined(); expect(create).toHaveBeenCalledWith({ data: expect.objectContaining({ flag_key: "payment_batch_v1", override_mode: "force_on", }), }); expect(prisma.featureFlag.update).toBeUndefined(); expect(prisma.featureFlag.upsert).toBeUndefined(); }); });