import { describe, it, expect } from "vitest"; import { buildDuplicatePrefill, toDateInputValue } from "@/lib/duplicate-po"; import type { DuplicateSourcePo } from "@/lib/duplicate-po"; // A Prisma Decimal stand-in: just needs a toNumber(). const dec = (n: number) => ({ toNumber: () => n }); function makeSource(overrides: Partial = {}): DuplicateSourcePo { return { title: "Spare parts for HNR1", vesselId: "vsl_1", accountId: "acc_1", companyId: "co_1", vendorId: "ven_1", projectCode: "Haldia Reach", placeOfDelivery: "Pelagia — Cochin yard", dateRequired: new Date("2026-07-15T00:00:00.000Z"), piQuotationNo: "INV-001", piQuotationDate: new Date("2026-06-01T00:00:00.000Z"), requisitionNo: "REQ-42", requisitionDate: new Date("2026-05-20T00:00:00.000Z"), terms: [{ category: "Delivery", text: "Within 4 to 5 days" }], lineItems: [ { name: "Gasket", description: "Rubber gasket", quantity: dec(3), unit: "pc", size: "M", unitPrice: dec(120.5), gstRate: dec(0.18), productId: "prod_1", accountId: null, }, ], ...overrides, }; } describe("buildDuplicatePrefill", () => { it("copies the editable order fields onto the new draft", () => { const r = buildDuplicatePrefill(makeSource()); expect(r.initialTitle).toBe("Spare parts for HNR1"); expect(r.initialVesselId).toBe("vsl_1"); expect(r.initialAccountId).toBe("acc_1"); expect(r.initialCompanyId).toBe("co_1"); expect(r.initialVendorId).toBe("ven_1"); expect(r.initialProjectCode).toBe("Haldia Reach"); expect(r.initialPlaceOfDelivery).toBe("Pelagia — Cochin yard"); expect(r.initialPiQuotationNo).toBe("INV-001"); expect(r.initialRequisitionNo).toBe("REQ-42"); }); it("formats dates as yyyy-MM-dd for native date inputs", () => { const r = buildDuplicatePrefill(makeSource()); expect(r.initialDateRequired).toBe("2026-07-15"); expect(r.initialPiQuotationDate).toBe("2026-06-01"); expect(r.initialRequisitionDate).toBe("2026-05-20"); }); it("maps line items to the editor shape, converting Decimals to numbers", () => { const r = buildDuplicatePrefill(makeSource()); expect(r.initialLineItems).toEqual([ { name: "Gasket", description: "Rubber gasket", quantity: 3, unit: "pc", size: "M", unitPrice: 120.5, gstRate: 0.18, productId: "prod_1", accountId: undefined, }, ]); }); it("enables per-item accounting codes only when a line item carries one", () => { expect(buildDuplicatePrefill(makeSource()).initialMultiAccount).toBe(false); const multi = makeSource({ lineItems: [ { name: "A", quantity: dec(1), unit: "pc", unitPrice: dec(10), accountId: "acc_2" }, ], }); const r = buildDuplicatePrefill(multi); expect(r.initialMultiAccount).toBe(true); expect(r.initialLineItems[0].accountId).toBe("acc_2"); }); it("defaults a missing gstRate to 0.18", () => { const src = makeSource({ lineItems: [{ name: "A", quantity: dec(2), unit: "pc", unitPrice: dec(5) }], }); expect(buildDuplicatePrefill(src).initialLineItems[0].gstRate).toBe(0.18); }); it("uses the saved terms snapshot when present", () => { const r = buildDuplicatePrefill(makeSource()); expect(r.initialTerms).toEqual([{ category: "Delivery", text: "Within 4 to 5 days" }]); }); it("falls back to legacy tc* terms when no JSON snapshot exists", () => { const src = makeSource({ terms: null, tcDelivery: "Next day", tcPaymentTerms: "Net 15", }); const r = buildDuplicatePrefill(src); expect(r.initialTerms).toEqual( expect.arrayContaining([ { category: "Delivery", text: "Next day" }, { category: "Payment Terms", text: "Net 15" }, ]) ); }); it("normalises absent optional fields to undefined/null", () => { const src = makeSource({ companyId: null, vendorId: null, projectCode: null, placeOfDelivery: null, dateRequired: null, piQuotationNo: null, piQuotationDate: null, requisitionNo: null, requisitionDate: null, }); const r = buildDuplicatePrefill(src); expect(r.initialCompanyId).toBeUndefined(); expect(r.initialVendorId).toBeUndefined(); expect(r.initialDateRequired).toBeUndefined(); expect(r.initialPiQuotationNo).toBeUndefined(); expect(r.initialProjectCode).toBeNull(); expect(r.initialPlaceOfDelivery).toBeNull(); }); }); describe("toDateInputValue", () => { it("returns yyyy-MM-dd for a date and undefined for null", () => { expect(toDateInputValue(new Date("2026-01-09T12:00:00.000Z"))).toBe("2026-01-09"); expect(toDateInputValue(null)).toBeUndefined(); expect(toDateInputValue(undefined)).toBeUndefined(); }); });