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:
parent
2cb6491654
commit
f7b5f3677e
2 changed files with 62 additions and 4 deletions
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue