import { describe, it, expect } from "vitest"; import { vatFromGross } from "../routes/admin/received-invoices"; // `amount` on a received invoice is the GROSS total (VAT included). The VAT is // the portion contained within it: gross * rate / (100 + rate). describe("vatFromGross (VAT contained in a gross total)", () => { it("derives VAT from a real gross total at 21%", () => { // 22 542,91 @ 21% → 3 912,41 (base 18 630,50). User-confirmed figures. expect(vatFromGross(22542.91, 21)).toBeCloseTo(3912.41, 2); expect(22542.91 - vatFromGross(22542.91, 21)).toBeCloseTo(18630.5, 2); }); it("derives VAT at other rates", () => { expect(vatFromGross(1210, 21)).toBeCloseTo(210, 2); // base 1000 expect(vatFromGross(1100, 10)).toBeCloseTo(100, 2); // base 1000 expect(vatFromGross(1150, 15)).toBeCloseTo(150, 2); // base 1000 }); it("returns 0 when there is no VAT", () => { expect(vatFromGross(5000, 0)).toBe(0); }); it("returns 0 for a zero amount", () => { expect(vatFromGross(0, 21)).toBe(0); }); it("rounds the cent UP when the raw VAT's third decimal forces a carry", () => { // 115.50 @ 21% -> raw 20.045454... the third decimal (5) rounds the cent // up to 20.05. Pinned EXACTLY (not toBeCloseTo) so a truncate-instead-of- // round regression (which would yield 20.04) fails. expect(vatFromGross(115.5, 21)).toBe(20.05); // 95.70 @ 21% -> raw 16.609090... rounds up to 16.61. expect(vatFromGross(95.7, 21)).toBe(16.61); }); it("rounds the cent DOWN when below the half-cent", () => { // 100.40 @ 21% -> raw 17.424793... rounds down to 17.42. expect(vatFromGross(100.4, 21)).toBe(17.42); }); it("pins the result to the exact stored 2-dp value (not just close)", () => { // The DB column is Decimal(_, 2). vatFromGross must already return a value // with no third-decimal float drift. Strict equality + a 2-dp self-check, // NOT toBeCloseTo, so a 3-dp regression (e.g. 210.0000001) would fail. const v = vatFromGross(1210, 21); expect(v).toBe(210); // exact, not ~210 expect(v).toBe(Math.round(v * 100) / 100); // genuinely 2-dp clean // The real-world figure too: pinned exactly, replacing the toBeCloseTo above. expect(vatFromGross(22542.91, 21)).toBe(3912.41); }); });