完善差旅补助规定与费用类型(07-28-travel-reimbursement-guide)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-07-29 20:04:35 +08:00
父节点 5df5f12ad6
当前提交 13a3f4b57d
共修改 10 个文件,包含 201 行新增和 15 行删除
+9 -2
查看文件
@@ -7,8 +7,13 @@ const ENABLED_EXPENSE_TYPES = [
{ code: "travel_train", name: "火车票", category: "travel" },
{ code: "travel_taxi", name: "打车费", category: "travel" },
{ code: "travel_hotel", name: "住宿费", category: "travel" },
{ code: "travel_bus", name: "市内交通", category: "travel" },
{ code: "travel_meal", name: "差旅餐补", category: "travel" },
{ code: "travel_bus", name: "大巴车票", category: "travel" },
{ code: "travel_meal", name: "伙食补助费", category: "travel" },
{
code: "travel_local_transport_allowance",
name: "市内交通补助费",
category: "travel",
},
{ code: "travel_fuel", name: "油费", category: "travel" },
{ code: "travel_toll", name: "过路费", category: "travel" },
{ code: "travel_parking", name: "停车费", category: "travel" },
@@ -1088,5 +1093,7 @@ if (require.main === module) {
module.exports = {
DEFAULT_APPROVAL_RULES,
ENABLED_EXPENSE_TYPES,
seedApprovalRules,
seedExpenseTypes,
};
@@ -21,7 +21,7 @@ function buildTemplate(overrides = {}) {
return {
id: TEMPLATE_ID,
name: "国内差旅报销",
description: "机票、火车票与市内交通占位模板",
description: "机票、火车票与大巴车票占位模板",
items: [
{
expenseTypeId: EXPENSE_TYPE_ID,
@@ -60,7 +60,7 @@ function buildTemplate(overrides = {}) {
},
{
expenseTypeId: BUS_TYPE_ID,
description: "市内交通占位",
description: "大巴车票占位",
},
],
...overrides,
@@ -127,7 +127,7 @@ async function buildApp(options = {}) {
expenseTypes: options.expenseTypes ?? [
{ id: AIRFARE_TYPE_ID, code: "travel_airfare", name: "机票", category: "travel", enabled: true },
{ id: TRAIN_TYPE_ID, code: "travel_train", name: "火车票", category: "travel", enabled: true },
{ id: BUS_TYPE_ID, code: "travel_bus", name: "市内交通", category: "travel", enabled: true },
{ id: BUS_TYPE_ID, code: "travel_bus", name: "大巴车票", category: "travel", enabled: true },
{ id: TAXI_TYPE_ID, code: "travel_taxi", name: "打车费", category: "travel", enabled: true },
{ id: TRANSPORT_TYPE_ID, code: "transport", name: "legacy-交通费", category: "travel", enabled: true },
],
@@ -1,8 +1,51 @@
const {
DEFAULT_APPROVAL_RULES,
ENABLED_EXPENSE_TYPES,
seedApprovalRules,
seedExpenseTypes,
} = 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("small-team default reimbursement approval rules", () => {
it("uses finance for every owner fallback and finance review node", () => {
expect(DEFAULT_APPROVAL_RULES).toEqual([