Quotas — Co-validation Groups

Co-validation Groups let you evaluate several quota configurations together under a shared rule. They are useful when a single order must meet one collective minimum across multiple scopes, instead of picking only one most-specific rule.

Key points

  • A Group contains member rules that share a group minimum.
  • If a Group matches, the engine uses the group effective minimum for the order.
  • If no Group matches, the engine falls back to individual rule precedence.
  • Groups are admin-managed; creation and updates do not invent new fields.

🧭 What a Group is

A Co-validation Group defines:

  • Members: references to existing quota rules that target Account, Supplier, optionally Store.
  • Group minimum: the collective threshold to be met when the Group applies.
  • Resolution policy: how to compute the effective minimum when both Group and individual rules apply.

Typical intent: “These rules must co-validate together, the order must meet at least this shared minimum.”


🔗 Concepts and relationships

graph LR
  %% ---------- Nodes ----------
  GRP[Co-validation Group<br>group minimum]
  R1[Member rule<br>account plus supplier]
  R2[Member rule<br>account only]
  R3[Member rule<br>supplier only]
  ACCT[Account]
  SUP[Supplier]
  STORE[Store optional]
  ORD[Order<br>under quota check]

  %% ---------- Relations ----------
  GRP --> R1
  GRP --> R2
  GRP --> R3
  R1 --> ACCT
  R1 --> SUP
  R2 --> ACCT
  R3 --> SUP
  GRP --> ORD

  %% ---------- Styles ----------
  classDef op fill:#e0f7fa,stroke:#06b6d4,stroke-width:2px,color:#065f46;
  classDef total fill:#e8f1ff,stroke:#2f6feb,stroke-width:2px,color:#0b3d91;
  classDef visible fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;

  class GRP op;
  class R1,R2,R3 total;
  class ACCT,SUP,STORE,ORD visible;

  style GRP rx:8,ry:8
  style R1 rx:8,ry:8
  style R2 rx:8,ry:8
  style R3 rx:8,ry:8
  style ACCT rx:8,ry:8
  style SUP rx:8,ry:8
  style STORE rx:8,ry:8
  style ORD rx:8,ry:8

🧮 Evaluation with Groups

graph LR
  %% ---------- Flow ----------
  IN[Order enters quota check] --> G{Any matching group}
  G -->|No| FALL[Fallback to individual rules<br>most specific precedence]
  G -->|Yes| RES[Resolve group effective minimum<br>based on policy]
  RES --> CMP[Compare order metrics<br>to effective minimum]
  FALL --> CMP
  CMP -->|Below min| BLK[Block<br>reason: quota_min_not_met]
  CMP -->|Meets min| OK[Allow]

  %% ---------- Styles ----------
  classDef total fill:#e8f1ff,stroke:#2f6feb,stroke-width:2px,color:#0b3d91;
  classDef diff fill:#fff4e5,stroke:#f59e0b,stroke-width:2px,color:#7a3e00;
  classDef inter fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;
  classDef visible fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;

  class IN,G,RES,FALL,CMP diff;
  class BLK inter;
  class OK visible;

  style IN rx:8,ry:8
  style G rx:8,ry:8
  style RES rx:8,ry:8
  style FALL rx:8,ry:8
  style CMP rx:8,ry:8
  style BLK rx:8,ry:8
  style OK rx:8,ry:8

Resolution policy

  • If the Group defines a group minimum, the engine uses that value as the effective minimum.
  • If the Group has no explicit minimum, the engine uses the most restrictive member for the order context.
  • If multiple groups match, the engine uses the most restrictive among their effective minimums.

“Most restrictive” means the highest minimum when the metric is an amount or quantity.


✅ When to use Groups

  • You want one shared threshold to apply across several Accounts or Suppliers.
  • You want to avoid picking a single rule when several should co-validate.
  • You need a coordination bucket in multi-store setups, while still honoring store scoping.

🧩 CRUD and scoping

graph LR
  %% ---------- Nodes ----------
  ADM[Admin UI or API]
  GRP[Co-validation Group]
  RLS[Member rules]
  EVAL[Quota evaluation<br>uses group if matched]

  %% ---------- Relations ----------
  ADM --> GRP
  GRP --> RLS
  GRP --> EVAL

  %% ---------- Styles ----------
  classDef op fill:#e0f7fa,stroke:#06b6d4,stroke-width:2px,color:#065f46;
  classDef total fill:#e8f1ff,stroke:#2f6feb,stroke-width:2px,color:#0b3d91;
  classDef visible fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;

  class ADM op;
  class GRP total;
  class RLS,EVAL visible;

  style ADM rx:8,ry:8
  style GRP rx:8,ry:8
  style RLS rx:8,ry:8
  style EVAL rx:8,ry:8

Good practices

  • Keep memberships explicit and minimal to avoid overlap.
  • Use group minimum when you need a clear target across all members.
  • Document a short business label for each Group so operators understand its purpose.

🧾 Admin endpoints

  • Create group: POST /v1/buying-policies/quotas/groups — ADM-BUYING-POLICY-153
  • List groups: GET /v1/buying-policies/quotas/groups — ADM-BUYING-POLICY-554
  • Update group: PUT /v1/buying-policies/quotas/groups/groupId — ADM-BUYING-POLICY-207
  • Delete group: DELETE /v1/buying-policies/quotas/groups/groupId — ADM-BUYING-POLICY-303

🔗 API quicklinks

  • Create group: POST /v1/buying-policies/quotas/groups — ADM-BUYING-POLICY-153
  • List groups: GET /v1/buying-policies/quotas/groups — ADM-BUYING-POLICY-554
  • Update group: PUT /v1/buying-policies/quotas/groups/groupId — ADM-BUYING-POLICY-207
  • Delete group: DELETE /v1/buying-policies/quotas/groups/groupId — ADM-BUYING-POLICY-303