Skip to content

feat: SCO-137 enforce brand order minimums - #399

Merged
scottcarlton merged 2 commits into
devfrom
feat/sco-137-order-minimum
Oct 29, 2026
Merged

scottcarlton merged 2 commits into
devfrom
feat/sco-137-order-minimum

Conversation

@scottcarlton

Copy link
Copy Markdown
Owner

Summary

An order under its brand's minimum can be saved as a draft but not submitted, except by the org that owns the brand, which can accept it and submit anyway.

  • One rule, every submit path. findMinimumViolations (src/lib/server/orders/order-minimum.ts) on top of a pure effectiveOrderMinimum / minimumShortfall (src/lib/utils/order-minimum.ts) guards:
    • rep wizard, buyer checkout, and offline sync (submitOrderPayload)
    • PATCH /api/orders/[id]/status (draft to submitted)
    • note conversion (/orders/[id]?/convert)
    • email-intake approval, plus auto-submit: an under-minimum intake goes to review instead
    • the AI create-order tool (keeps the draft and tells the model why)
  • Brand override. The brand's owning org is never blocked: it sees "This order is $X under your $Y minimum. You can still submit it." Rep drafts are already federated to the brand on insert, so the brand can submit them from the order page.
  • Buyers never override. A legacy buyer's locals.organization is the brand's own org, so every call site passes null as the actor for buyers.
  • Account overrides replace the brand minimum only on accounts the brand's own org owns. Otherwise a rep could set an override of 0 on their own account and get under a connected brand's minimum.
  • Offline-captured orders under the minimum land as drafts with the existing "Order saved as a draft" notification instead of being rejected.
  • UI: the wizard, checkout, and draft order page show an amber notice and disable submit (Save as Draft stays available in the wizard). Copy: "This order is $120.00 under Acme's $500.00 minimum. Only Acme can submit it. Save it as a draft for Acme to review." Buyers see "Add $120.00 to reach Acme's $500.00 minimum."
  • Notes and drafts are never checked.

Why

SCO-137: brands could configure a minimum, see it saved, and still receive orders below it. Decision (29 Oct): warn and allow draft only; the brand can override and submit.

Not in this PR

  • The original ticket's "Under minimum" pill and filter on the brand order list. With submission blocked, under-minimum orders reach the brand as drafts; worth revisiting if the brand wants a filter for them.

Verification

  • bun run lint passes
  • bun run check passes (0 errors)
  • bun run test:run: 2083 pass, including new tests for the pure rule, the server helper (override, buyer, account override, indexes), submit (online block, captured to draft, brand override, buyer copy, notes/drafts skipped), and note conversion. The 10 local recent-searches failures are pre-existing (Node v26 localStorage) and pass in CI.
  • tests/rls/admin-bypass.test.ts updated: the status endpoint now uses the service role for the settings lookup, after RLS has authorized the order read.
  • Not exercised in the browser: needs a brand with a minimum, a connected rep, and a buyer seeded locally.

Test plan

  • Set a $500 minimum on a brand. As a connected rep, build a $200 order: amber notice, Submit & Confirm and Submit as Pending disabled, Save as Draft works.
  • Open that draft as the rep: notice shown, Submit disabled. Open it as the brand admin: override note shown, Submit works.
  • As a buyer, check out $200 for that brand: notice says how much to add, submit disabled.
  • Set an account override of $100 on a brand-owned account: a $200 order submits.

Closes SCO-137

🤖 Generated with Claude Code

Minillama and others added 2 commits October 29, 2026 16:08
Brands could set an order minimum, see it saved, and still receive orders
far below it, because nothing compared it to an order total. An order
under its brand's minimum can now be saved as a draft but not submitted,
except by the org that owns the brand, which can accept it and submit
anyway.

One rule (findMinimumViolations) guards every path that submits an order:
the rep wizard, buyer checkout and offline sync (submitOrderPayload), the
status endpoint, note conversion, email-intake approval, and the AI
create-order tool. An offline-captured order under the minimum lands as a
draft with a notification instead of being rejected, and an email intake
under it goes to review. Buyers never inherit the override, even though a
legacy buyer's org is the brand's own.

Account overrides replace the brand minimum only on accounts the brand's
org owns, so a rep cannot lower a connected brand's minimum through their
own account.

The wizard, checkout, and draft order page warn before submit and disable
the submit control; the brand sees a note that it can still submit.

SCO-137

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

vercel Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadline Ready Ready Preview Oct 29, 2026 10:12pm UTC

@scottcarlton
scottcarlton merged commit f8ff6b7 into dev Oct 29, 2026
8 checks passed
@scottcarlton
scottcarlton deleted the feat/sco-137-order-minimum branch October 29, 2026 22:14

This branch was successfully deployed

1 active deployment
Preview — 10ad91e0 Deployed Oct 29, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant