fix(buyer-tasks): prefill SendPoModal fields from buyer-tasks page

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
SJCoetz 2026-07-29 20:45:12 +02:00
parent 3cfb2ac00c
commit 76f1d79082
6 changed files with 73 additions and 3 deletions

View file

@ -32,6 +32,8 @@ describe("GET /api/v1/buyer-tasks", () => {
totalCost: 50,
purchaseOrderId: null,
poStatus: null,
poNumber: null,
supplierEmail: null,
step: "needs_po",
},
]);

View file

@ -17,6 +17,8 @@ const baseGroup = {
totalCost: 50,
purchaseOrderId: null,
poStatus: null,
poNumber: null,
supplierEmail: null,
step: "needs_po" as const,
};

View file

@ -17,6 +17,8 @@ const sampleGroup = {
totalCost: 50,
purchaseOrderId: null,
poStatus: null,
poNumber: null,
supplierEmail: null,
step: "needs_po" as const,
};

View file

@ -156,10 +156,18 @@ export function BuyerTasksPage() {
onCancel={() => setMarkReadyFor(null)}
busy={false}
/>
{sendPoFor?.purchaseOrderId && (
{sendPoFor && (
<SendPoModal
open={sendPoFor !== null}
purchaseOrder={{ id: sendPoFor.purchaseOrderId } as never}
purchaseOrder={{
id: sendPoFor.purchaseOrderId ?? "",
po_number: sendPoFor.poNumber ?? "",
expand: {
supplier: {
email: sendPoFor.supplierEmail ?? "",
},
},
} as never}
onClose={() => setSendPoFor(null)}
onSent={() => {
setSendPoFor(null);

View file

@ -227,6 +227,58 @@ describe("listBuyerTasks", () => {
expect(filter).not.toContain(`item_status = "po_generated"`);
});
it("populates poNumber and supplierEmail from the expanded PO", async () => {
const { admin } = makeAdmin([
baseItem({
purchase_order: "po-1",
item_status: "po_generated",
expand: {
order: baseOrder,
supplier: baseSupplier,
purchase_order: {
id: "po-1",
status: "draft",
po_number: "PO-26072901",
expand: {
supplier: {
id: "sup-1",
email: "orders@steelco.example",
},
},
},
},
}),
]);
vi.mocked(getAdminPocketBase).mockResolvedValue(admin as never);
const groups = await listBuyerTasks("po_draft");
expect(groups).toHaveLength(1);
expect(groups[0].poNumber).toBe("PO-26072901");
expect(groups[0].supplierEmail).toBe("orders@steelco.example");
});
it("leaves poNumber and supplierEmail null when the PO has no expand", async () => {
const { admin } = makeAdmin([
baseItem({
purchase_order: "po-1",
item_status: "po_generated",
expand: {
order: baseOrder,
supplier: baseSupplier,
purchase_order: { id: "po-1", status: "draft" },
},
}),
]);
vi.mocked(getAdminPocketBase).mockResolvedValue(admin as never);
const groups = await listBuyerTasks("po_draft");
expect(groups).toHaveLength(1);
expect(groups[0].poNumber).toBeNull();
expect(groups[0].supplierEmail).toBeNull();
});
it("does not include a separate ready_delivery exclusion in po_sent post-filter", async () => {
// The ready_delivery exclusion moved to the PB filter (covered by
// the filter-content assertions above). Verify the service still

View file

@ -21,6 +21,8 @@ export type BuyerTaskGroup = {
totalCost: number;
purchaseOrderId: string | null;
poStatus: "draft" | "sent" | "sending" | "received" | "mail_failed" | "cancelled" | null;
poNumber: string | null;
supplierEmail: string | null;
step: BuyerTaskTab;
};
@ -62,7 +64,7 @@ export async function listBuyerTasks(tab: BuyerTaskTab): Promise<BuyerTaskGroup[
if (!orderId || !supplierId) continue;
const po = item.expand?.purchase_order as
| { id: string; status: BuyerTaskGroup["poStatus"] }
| { id: string; status: BuyerTaskGroup["poStatus"]; po_number?: string; expand?: { supplier?: { email?: string } } }
| undefined;
// Post-filter by PO status (tab-specific). The PB filter can't
@ -95,6 +97,8 @@ export async function listBuyerTasks(tab: BuyerTaskTab): Promise<BuyerTaskGroup[
totalCost: 0,
purchaseOrderId: po?.id ?? null,
poStatus: po?.status ?? null,
poNumber: po && typeof po === "object" && "po_number" in po ? String((po as { po_number?: string }).po_number ?? "") || null : null,
supplierEmail: (po as { expand?: { supplier?: { email?: string } } } | undefined)?.expand?.supplier?.email ?? null,
step: tab,
};
groups.set(groupId, group);