feat: 完成P13治理收尾并创建P14执行合同(Issue: P13-1,P13-2,P13-3,P13-4,P13-5,P13-6,P13-7,P13-8,P14-0)

这个提交包含在:
2026-02-13 00:25:04 +08:00
父节点 3b221a2202
当前提交 1412fead5d
共修改 30 个文件,包含 3988 行新增和 105 行删除
@@ -0,0 +1,106 @@
const {
IntegrationDispatchError,
dispatchOutboxEvent,
} = require("../../src/services/integrations/dispatcher");
describe("dispatchOutboxEvent", () => {
it("handles mock ERP success", async () => {
const result = await dispatchOutboxEvent({
config: {
erpSyncEnabled: true,
erpSyncProvider: "mock",
},
eventType: "erp.reimbursement.paid",
payload: {
reimbursementId: "rb-1",
formNumber: "BX-001",
},
});
expect(result.channel).toBe("erp");
expect(result.code).toBe("mock_synced");
expect(result.response.externalId).toContain("BX-001");
});
it("maps ERP disabled as non-retryable dispatch error", async () => {
await expect(
dispatchOutboxEvent({
config: {
erpSyncEnabled: false,
erpSyncProvider: "mock",
},
eventType: "erp.reimbursement.paid",
payload: {
reimbursementId: "rb-2",
formNumber: "BX-002",
},
}),
).rejects.toMatchObject({
name: "IntegrationDispatchError",
code: "erp_sync_disabled",
retryable: false,
});
});
it("maps invalid ERP provider as non-retryable dispatch error", async () => {
await expect(
dispatchOutboxEvent({
config: {
erpSyncEnabled: true,
erpSyncProvider: "invalid-provider",
},
eventType: "erp.reimbursement.paid",
payload: {
reimbursementId: "rb-3",
formNumber: "BX-003",
},
}),
).rejects.toMatchObject({
name: "IntegrationDispatchError",
code: "erp_sync_provider_invalid",
retryable: false,
});
});
it("handles IM notification outbox", async () => {
const result = await dispatchOutboxEvent({
config: {},
eventType: "notification.im",
payload: {
channelType: "wecom",
},
});
expect(result.channel).toBe("im");
expect(result.code).toBe("mock_sent");
expect(result.response.channelType).toBe("wecom");
});
it("throws non-retryable error for unsupported event", async () => {
await expect(
dispatchOutboxEvent({
config: { erpSyncEnabled: true, erpSyncProvider: "mock" },
eventType: "unsupported.event",
payload: {},
}),
).rejects.toMatchObject({
name: "IntegrationDispatchError",
code: "unsupported_outbox_event",
retryable: false,
});
});
it("preserves error class semantics", () => {
const error = new IntegrationDispatchError({
code: "unit_test",
message: "unit test",
retryable: true,
statusCode: 503,
});
expect(error).toBeInstanceOf(Error);
expect(error.code).toBe("unit_test");
expect(error.retryable).toBe(true);
expect(error.statusCode).toBe(503);
});
});