feat(orders): persist company and rep from review-modal cascade

Extends updateOrderReviewFields' patch type to accept company
(relation id) and rep (free-text snapshot) in addition to the
existing order_number and customer. The modal cascade writes these
when the operator changes the customer; the service now carries
them through to the PB update.

The order_number collision check is unchanged — it only runs for
order_number changes, so the new fields are unaffected.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
SJCoetz 2026-07-31 15:29:10 +02:00
parent 2cb6491654
commit f7b5f3677e
2 changed files with 62 additions and 4 deletions

View file

@ -143,6 +143,55 @@ describe("updateOrderReviewFields", () => {
expect(result.customer).toBe("cust-new");
});
it("updates company when cascaded from a customer change", async () => {
const order = await pbMock.collection("orders").create({
order_number: "ORD-2026-07-001",
customer: "cust-old",
company: "co-old",
});
const result = await updateOrderReviewFields(order.id, {
company: "co-new",
});
expect(result.company).toBe("co-new");
});
it("updates rep when cascaded from a customer change", async () => {
const order = await pbMock.collection("orders").create({
order_number: "ORD-2026-07-001",
customer: "cust-old",
rep: "Old Rep",
});
const result = await updateOrderReviewFields(order.id, {
rep: "Jane Smith",
});
expect(result.rep).toBe("Jane Smith");
});
it("updates company and rep together with customer and order_number", async () => {
const order = await pbMock.collection("orders").create({
order_number: "ORD-2026-07-001",
customer: "cust-old",
company: "co-old",
rep: "Old Rep",
});
const result = await updateOrderReviewFields(order.id, {
order_number: "ORD-2026-07-014",
customer: "cust-new",
company: "co-new",
rep: "Jane Smith",
});
expect(result.order_number).toBe("ORD-2026-07-014");
expect(result.customer).toBe("cust-new");
expect(result.company).toBe("co-new");
expect(result.rep).toBe("Jane Smith");
});
it("throws OrderNumberCollisionError when another order owns the number", async () => {
await pbMock.collection("orders").create({
order_number: "ORD-2026-07-001",

View file

@ -287,14 +287,21 @@ export class OrderNumberCollisionError extends Error {
/**
* Patches the order header fields editable from the review modal.
* Currently supports `order_number` and `customer`. Validates
* `order_number` uniqueness against the `orders` collection
* (excluding self) before write; throws
* Supports `order_number`, `customer`, `company` (relation id), and
* `rep` (free-text snapshot of the rep's name). The `company` and
* `rep` fields are cascaded from the selected customer by the modal
* (see `orders-review-modal.tsx`). Validates `order_number` uniqueness
* against the `orders` collection (excluding self) before write; throws
* `OrderNumberCollisionError` on collision.
*/
export async function updateOrderReviewFields(
orderId: string,
patch: { order_number?: string; customer?: string },
patch: {
order_number?: string;
customer?: string;
company?: string;
rep?: string;
},
) {
const pb = await getAdminPocketBase();
@ -331,6 +338,8 @@ export async function updateOrderReviewFields(
const cleanPatch: Record<string, unknown> = {};
if (patch.order_number !== undefined) cleanPatch.order_number = patch.order_number;
if (patch.customer !== undefined) cleanPatch.customer = patch.customer;
if (patch.company !== undefined) cleanPatch.company = patch.company;
if (patch.rep !== undefined) cleanPatch.rep = patch.rep;
if (Object.keys(cleanPatch).length === 0) {
// No-op — just re-fetch and return.