122 行
3.9 KiB
JavaScript
122 行
3.9 KiB
JavaScript
const {
|
|
buildTravelOrderPaymentJournalPayload,
|
|
buildTravelOrderPaymentJournalDedupeKey,
|
|
buildTravelOrderPaymentJournalPreview,
|
|
} = require("../../../src/services/integrations/erpJournal");
|
|
|
|
describe("erpJournal travel helpers", () => {
|
|
it("builds payment journal payload with travel dimensions", () => {
|
|
const payload = buildTravelOrderPaymentJournalPayload({
|
|
travelOrder: {
|
|
id: "order-1",
|
|
source: "ctrip",
|
|
external_order_no: "EXT-001",
|
|
employee_id: "employee-1",
|
|
department_id: "dept-1",
|
|
travel_request_id: "travel-1",
|
|
amount: "500.00",
|
|
currency: "CNY",
|
|
payment_voucher_no: "BANK-001",
|
|
payment_date: new Date("2026-03-10T00:00:00.000Z"),
|
|
payment_channel: "bank_transfer",
|
|
paid_at: new Date("2026-03-10T09:00:00.000Z"),
|
|
created_at: new Date("2026-03-10T08:00:00.000Z"),
|
|
updated_at: new Date("2026-03-10T09:00:00.000Z"),
|
|
travel_request: {
|
|
id: "travel-1",
|
|
request_no: "CL-20260310-0001",
|
|
applicant_employee_id: "employee-1",
|
|
submitter_id: null,
|
|
legal_entity: { code: "HY" },
|
|
cost_center: { code: "CC001" },
|
|
budget_pool: { code: "POOL-1" },
|
|
},
|
|
},
|
|
});
|
|
|
|
expect(payload).toEqual(
|
|
expect.objectContaining({
|
|
journalType: "travel_order_payment",
|
|
sourceEventName: "travel_order.paid",
|
|
entityType: "travel_order",
|
|
entityId: "order-1",
|
|
documentNo: "EXT-001",
|
|
paymentVoucherNo: "BANK-001",
|
|
paymentDate: "2026-03-10",
|
|
paymentChannel: "bank_transfer",
|
|
dimensions: expect.objectContaining({
|
|
legalEntityCode: "HY",
|
|
costCenterCode: "CC001",
|
|
budgetPoolCode: "POOL-1",
|
|
}),
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("builds stable travel-order dedupe key", () => {
|
|
expect(buildTravelOrderPaymentJournalDedupeKey("order-1")).toBe("travel_order:order-1:paid");
|
|
});
|
|
|
|
it("builds preview with current binding and outbox state", async () => {
|
|
const prisma = {
|
|
integrationBinding: {
|
|
findUnique: vi.fn().mockResolvedValue({
|
|
id: "binding-1",
|
|
provider: "erp",
|
|
entity_type: "travel_order_payment_journal",
|
|
local_id: "order-1",
|
|
external_id: "erp-1",
|
|
external_code: "EXT-001",
|
|
last_synced_at: new Date("2026-03-10T10:00:00.000Z"),
|
|
}),
|
|
},
|
|
integrationOutbox: {
|
|
findFirst: vi.fn().mockResolvedValue({
|
|
id: "outbox-1",
|
|
event_type: "erp.journal.export",
|
|
status: "succeeded",
|
|
last_error: null,
|
|
processed_at: new Date("2026-03-10T10:00:00.000Z"),
|
|
updated_at: new Date("2026-03-10T10:00:00.000Z"),
|
|
}),
|
|
},
|
|
};
|
|
|
|
const preview = await buildTravelOrderPaymentJournalPreview(prisma, {
|
|
id: "order-1",
|
|
source: "ctrip",
|
|
external_order_no: "EXT-001",
|
|
employee_id: "employee-1",
|
|
department_id: "dept-1",
|
|
linked_reimbursement_id: null,
|
|
travel_request_id: "travel-1",
|
|
amount: "500.00",
|
|
currency: "CNY",
|
|
payment_voucher_no: "BANK-001",
|
|
payment_date: new Date("2026-03-10T00:00:00.000Z"),
|
|
payment_channel: "bank_transfer",
|
|
paid_at: new Date("2026-03-10T09:00:00.000Z"),
|
|
created_at: new Date("2026-03-10T08:00:00.000Z"),
|
|
updated_at: new Date("2026-03-10T09:00:00.000Z"),
|
|
travel_request: {
|
|
id: "travel-1",
|
|
request_no: "CL-20260310-0001",
|
|
applicant_employee_id: "employee-1",
|
|
submitter_id: null,
|
|
legal_entity: { code: "HY" },
|
|
cost_center: { code: "CC001" },
|
|
budget_pool: { code: "POOL-1" },
|
|
},
|
|
});
|
|
|
|
expect(preview.exportState).toEqual(
|
|
expect.objectContaining({
|
|
externalId: "erp-1",
|
|
lastOutboxId: "outbox-1",
|
|
lastOutboxStatus: "succeeded",
|
|
}),
|
|
);
|
|
expect(preview.binding).toEqual(expect.objectContaining({ localId: "order-1" }));
|
|
});
|
|
});
|