All PO attachments are stored as PODocument rows whose lifecycle stage (submission vs delivery) is encoded in the storageKey prefix. The PO details screen previously listed them in a single flat "Attachments" block, giving no indication of which were submission documents (invoice, quotation) versus delivery receipts. Add lib/attachments.ts to derive a user-facing group from the storageKey prefix (submission / payment / delivery / other) and render each non-empty group as a labelled subsection on the PO details screen, in lifecycle order. Unknown prefixes fall back to an "Other" group so nothing is ever hidden. Fixes #10
67 lines
2.3 KiB
TypeScript
67 lines
2.3 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import {
|
|
categorizeAttachment,
|
|
groupAttachments,
|
|
} from "@/lib/attachments";
|
|
|
|
describe("categorizeAttachment", () => {
|
|
it("maps po-document keys to the submission group", () => {
|
|
expect(categorizeAttachment("po-document/po123/1700-invoice.pdf")).toBe("submission");
|
|
});
|
|
|
|
it("maps receipt keys to the delivery group", () => {
|
|
expect(categorizeAttachment("receipt/po123/1700-delivery.pdf")).toBe("delivery");
|
|
});
|
|
|
|
it("maps payment keys to the payment group", () => {
|
|
expect(categorizeAttachment("payment-document/po123/proof.pdf")).toBe("payment");
|
|
expect(categorizeAttachment("payment/po123/proof.pdf")).toBe("payment");
|
|
});
|
|
|
|
it("falls back to other for unknown prefixes", () => {
|
|
expect(categorizeAttachment("something-else/x.pdf")).toBe("other");
|
|
expect(categorizeAttachment("no-slash")).toBe("other");
|
|
});
|
|
});
|
|
|
|
describe("groupAttachments", () => {
|
|
const doc = (id: string, storageKey: string) => ({ id, storageKey });
|
|
|
|
it("groups documents by lifecycle stage in canonical order", () => {
|
|
const groups = groupAttachments([
|
|
doc("a", "receipt/po1/delivery.pdf"),
|
|
doc("b", "po-document/po1/invoice.pdf"),
|
|
doc("c", "po-document/po1/quote.pdf"),
|
|
]);
|
|
|
|
expect(groups.map((g) => g.meta.key)).toEqual(["submission", "delivery"]);
|
|
expect(groups[0].items.map((d) => d.id)).toEqual(["b", "c"]);
|
|
expect(groups[1].items.map((d) => d.id)).toEqual(["a"]);
|
|
});
|
|
|
|
it("omits empty groups", () => {
|
|
const groups = groupAttachments([doc("a", "po-document/po1/invoice.pdf")]);
|
|
expect(groups).toHaveLength(1);
|
|
expect(groups[0].meta.key).toBe("submission");
|
|
});
|
|
|
|
it("returns an empty array when there are no documents", () => {
|
|
expect(groupAttachments([])).toEqual([]);
|
|
});
|
|
|
|
it("preserves input order within a group", () => {
|
|
const groups = groupAttachments([
|
|
doc("first", "receipt/po1/a.pdf"),
|
|
doc("second", "receipt/po1/b.pdf"),
|
|
]);
|
|
expect(groups[0].items.map((d) => d.id)).toEqual(["first", "second"]);
|
|
});
|
|
|
|
it("collects unknown prefixes into the other group last", () => {
|
|
const groups = groupAttachments([
|
|
doc("x", "mystery/po1/file.pdf"),
|
|
doc("y", "po-document/po1/invoice.pdf"),
|
|
]);
|
|
expect(groups.map((g) => g.meta.key)).toEqual(["submission", "other"]);
|
|
});
|
|
});
|