eims integration master test complete

This commit is contained in:
Hagernesh
2026-08-12 14:08:28 +00:00
parent 8d53dc17ce
commit 2d4da8110b
38 changed files with 2270 additions and 173 deletions

View File

@@ -80,6 +80,7 @@ describe("BillingService.generateInvoice", () => {
{} as never, // companies
{} as never, // invoiceDocuments
{} as never, // files
{ get: () => undefined } as never, // config
);
});
@@ -142,6 +143,7 @@ describe("BillingService.markInvoiceAsPaid", () => {
{} as never, // companies
{} as never, // invoiceDocuments
{} as never, // files
{ get: () => undefined } as never, // config
);
await service.markInvoiceAsPaid("inv-1", "pay-1", mg as never);
@@ -196,6 +198,7 @@ describe("BillingService.markInvoiceAsPaid", () => {
{} as never, // companies
{} as never, // invoiceDocuments
{} as never, // files
{ get: () => undefined } as never, // config
);
await service.markInvoiceAsPaid("inv-1", "pay-1", mg as never);
@@ -240,6 +243,7 @@ describe("BillingService.settleByPaymentId", () => {
{} as never, // companies
{} as never, // invoiceDocuments
{} as never, // files
{ get: () => undefined } as never, // config
);
return { service, mg, events };
}
@@ -352,6 +356,7 @@ describe("BillingService.recordPayment", () => {
{} as never, // companies
{} as never, // invoiceDocuments
{} as never, // files
{ get: () => undefined } as never, // config
);
return { service, mg, events };
}
@@ -468,6 +473,7 @@ describe("BillingService.expirePayable — locked write runs in a transaction",
{} as never,
{} as never,
{} as never,
{} as never, // config
);
return { service, defaultManager, txManager, transaction };
};
@@ -540,6 +546,7 @@ describe("BillingService.issuePayable", () => {
{} as never,
{} as never,
{} as never,
{} as never, // config
);
return { service, manager };
};
@@ -630,6 +637,7 @@ describe("BillingService — CAC Bank (OTP debit)", () => {
{} as never,
{} as never,
{} as never,
{} as never, // config
);
return { service, repo };
};
@@ -712,6 +720,7 @@ describe("BillingService — CBE bill amounts carry cents, never rounded", () =>
{} as never,
{} as never,
{} as never,
{} as never, // config
);
return { service, repo };
};
@@ -740,3 +749,102 @@ describe("BillingService — CBE bill amounts carry cents, never rounded", () =>
});
});
});
describe("BillingService.document", () => {
const invoiceRow = (over: Record<string, unknown> = {}) => ({
id: "inv-1",
invoiceNumber: "INV-20260812-00001",
source: "booking",
sourceId: "booking-1",
status: Freight.InvoiceStatus.Pending,
type: "freight",
currency: "ETB",
subtotalAmount: 100,
taxAmount: 0,
totalAmount: 100,
paidAmount: 0,
balanceAmount: 100,
issuedAt: new Date(2026, 7, 12),
dueAt: new Date(2026, 7, 19),
eimsIrn: null,
eimsSignedQr: null,
company: { name: "ABC Trading PLC", tin: "0999930000", vatNumber: "123475885858" },
...over,
});
const build = (invoice: Record<string, unknown>) => {
const render = jest.fn().mockResolvedValue({ filename: "x.pdf", buffer: Buffer.from("") });
const service = new BillingService(
{} as never,
{ findById: jest.fn().mockResolvedValue(invoice) } as never,
{ findAll: jest.fn().mockResolvedValue([]) } as never,
{} as never,
{} as never,
{} as never,
{ render } as never,
{} as never,
{
get: (key: string) =>
key === "eims"
? { tin: "0053481357", invoice: { sellerVatNumber: "43256663343256663322" } }
: undefined,
} as never, // config
);
return { service, render };
};
it("adds no EIMS IRN row and no QR for an unregistered invoice", async () => {
const { service, render } = build(invoiceRow());
await service.document("inv-1");
const model = render.mock.calls[0][0];
expect(model.summary.find((r: { label: string }) => r.label === "EIMS IRN")).toBeUndefined();
expect(model.qrImageUrl).toBeNull();
});
it("shows the buyer's name, TIN and VAT number on every invoice", async () => {
const { service, render } = build(invoiceRow());
await service.document("inv-1");
const model = render.mock.calls[0][0];
expect(model.summary).toContainEqual({ label: "Buyer", value: "ABC Trading PLC" });
expect(model.summary).toContainEqual({ label: "Buyer TIN", value: "0999930000" });
expect(model.summary).toContainEqual({ label: "Buyer VAT No.", value: "123475885858" });
});
it("omits the VAT row when the buyer company has none", async () => {
const { service, render } = build(invoiceRow({ company: { name: "Acme", tin: "0011223344" } }));
await service.document("inv-1");
const model = render.mock.calls[0][0];
expect(model.summary.find((r: { label: string }) => r.label === "Buyer VAT No.")).toBeUndefined();
});
it("shows EDR's own seller TIN and VAT number from EIMS config", async () => {
const { service, render } = build(invoiceRow());
await service.document("inv-1");
const model = render.mock.calls[0][0];
expect(model.summary).toContainEqual({ label: "Seller TIN", value: "0053481357" });
expect(model.summary).toContainEqual({
label: "Seller VAT No.",
value: "43256663343256663322",
});
});
it("adds the EIMS IRN to the summary and renders the QR for a registered invoice", async () => {
const { service, render } = build(
invoiceRow({ eimsIrn: "IRN-123", eimsSignedQr: "signed-payload" }),
);
await service.document("inv-1");
const model = render.mock.calls[0][0];
expect(model.summary).toContainEqual({ label: "EIMS IRN", value: "IRN-123" });
expect(model.qrImageUrl).toBe("data:image/png;base64,signed-payload");
});
});