Buying Policies

🧩 Overview

Buying Policies govern whether an order can be placed under business rules like credit exposure, quotas, and explicit holds/overrides. This page orients Operators and Customer Admins to the concepts, scope, and how evaluation works.

Keep in mind

  • Policies are tenant-level features toggled per policy family (Credit Control, Quotas).
  • Evaluation is deterministic and ordered (credit → quotas → holds/overrides), producing consistent blocking reasons.
  • Operators configure global defaults; Customer Admins may add account-level rules (where allowed).
  • Visibility & reporting are built-in: you can fetch blocking reasons and see unblock history.

🎯 Goals & audience

Who it’s for

  • Operator: sets global defaults, enables/disables each policy, audits blocked orders.
  • Customer Admin: manages account-specific limits (e.g., grace amounts, quota rules), monitors blocks.
  • Buyer: sees a clear message when a policy blocks their order (front experience is read-only).

What it solves

  • Prevent overspending with credit exposure checks.
  • Ensure purchase discipline with minimum quota thresholds.
  • Support temporary freezes with manual Credit Holds.
  • Allow controlled override via a forced validation workflow (with audit trail).

🔧 Concepts & relationships

graph LR
  %% ---------- Nodes ----------
  POL[Buying Policies<br>family: Credit Control, Quotas]
  CFG[Policy settings<br>toggles, defaults]
  RULE[Rules<br>per account / supplier]
  HOLD[Credit Hold<br>manual blocks]
  GRACE[Grace Amount<br>per account tolerance]
  ORDER[Order under check]
  REASON[Blocking reasons<br>codes and messages]
  AUDIT[Audit trail<br>forced validation history]
  ACCT[Account]
  SUP[Supplier]
  STORE[Store]

  %% ---------- Relations ----------
  POL --> CFG
  POL --> RULE
  POL --> HOLD
  POL --> GRACE
  ORDER -->|evaluated by| POL
  ORDER -->|produces| REASON
  REASON --> AUDIT
  RULE --> ACCT
  RULE --> SUP
  RULE --> STORE

  %% ---------- Styles ----------
  classDef total fill:#e8f1ff,stroke:#2f6feb,stroke-width:2px,color:#0b3d91;
  classDef op fill:#e0f7fa,stroke:#06b6d4,stroke-width:2px,color:#065f46;
  classDef diff fill:#fff4e5,stroke:#f59e0b,stroke-width:2px,color:#7a3e00;
  classDef visible fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef resp fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;

  class POL,CFG,RULE,HOLD,GRACE op;
  class ORDER total;
  class REASON diff;
  class AUDIT resp;
  class ACCT,SUP,STORE visible;

  style POL rx:8,ry:8
  style CFG rx:8,ry:8
  style RULE rx:8,ry:8
  style HOLD rx:8,ry:8
  style GRACE rx:8,ry:8
  style ORDER rx:8,ry:8
  style REASON rx:8,ry:8
  style AUDIT rx:8,ry:8
  style ACCT rx:8,ry:8
  style SUP rx:8,ry:8
  style STORE rx:8,ry:8

  %% Accent key edges
  linkStyle 4 stroke:#ef4444,stroke-width:2px
  linkStyle 5 stroke:#475569,stroke-width:2px

🧪 Evaluation pipeline

graph LR
  IN[Incoming order] --> T[Policies enabled?<br>Credit, Quotas]
  T -->|No| PASS[Pass through<br>no policy checks]
  T -->|Yes| CRED[Credit Control<br>exposure limits, holds, grace]
  CRED -->|Block| R1[Collect reasons]
  CRED -->|OK| QUO[Quotas<br>min thresholds, per scope]
  QUO -->|Block| R2[Collect reasons]
  QUO -->|OK| OK[Allow order]
  R1 --> OUT[Result: Blocked<br>with reasons]
  R2 --> OUT

  %% 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,T total;
  class CRED,QUO diff;
  class R1,R2,OUT inter;
  class OK visible; class PASS visible;

  style IN rx:8,ry:8
  style T rx:8,ry:8
  style PASS rx:8,ry:8
  style CRED rx:8,ry:8
  style QUO rx:8,ry:8
  style R1 rx:8,ry:8
  style R2 rx:8,ry:8
  style OK rx:8,ry:8
  style OUT rx:8,ry:8

  linkStyle 2 stroke:#ef4444,stroke-width:2px
  linkStyle 4 stroke:#ef4444,stroke-width:2px

Order of checks

  1. Credit Control: exposure vs limits, Credit Holds, Grace Amount tolerance.
  2. Quotas: minimums per configured scope (global default + account/supplier/store-specific rules).
  3. If any policy blocks, the order is blocked with reasons that can be retrieved and audited; otherwise it’s allowed.

🧭 Scoping & defaults

  • Global toggles per policy family (Credit Control, Quotas).
  • Defaults: credit limit default, quota minimum default.
  • Overrides: account-specific Grace Amount and Quota rules (including per supplier, per store).
  • Co-validation groups: sum or coordination of multiple configurations (e.g., shared quota bucket).

🔍 Visibility & reporting

  • Blocked orders view for operators/admins.
  • Blocking reasons retrieval API for one or more orders.
  • Forced validation (unblock) workflow records an audit history.

🔗 API quicklinks

Credit Control — toggles & settings

  • GET /v1/buying-policies/credit-control — ADM-BUYING-POLICY-500
  • PATCH /v1/buying-policies/credit-control — ADM-BUYING-POLICY-200
  • PATCH /v1/buying-policies/credit-control/credit-limit — ADM-BUYING-POLICY-201

Credit Holds & Grace Amount

  • GET /v1/buying-policies/credit-control/holds — ADM-BUYING-POLICY-550
  • POST /v1/buying-policies/credit-control/holds — ADM-BUYING-POLICY-150
  • PUT /v1/buying-policies/credit-control/holds/:creditHoldId — ADM-BUYING-POLICY-202
  • DELETE /v1/buying-policies/credit-control/holds/:creditHoldId — ADM-BUYING-POLICY-300
  • GET /v1/buying-policies/credit-control/grace-amounts — ADM-BUYING-POLICY-551
  • POST /v1/buying-policies/credit-control/grace-amounts — ADM-BUYING-POLICY-151
  • PUT /v1/buying-policies/credit-control/grace-amounts/:graceAmountId — ADM-BUYING-POLICY-203
  • DELETE /v1/buying-policies/credit-control/grace-amounts/:graceAmountId — ADM-BUYING-POLICY-301

Quotas — toggles, defaults, rules

  • GET /v1/buying-policies/quotas — ADM-BUYING-POLICY-501
  • PATCH /v1/buying-policies/quotas — ADM-BUYING-POLICY-204
  • PATCH /v1/buying-policies/quotas/min-value — ADM-BUYING-POLICY-205
  • POST /v1/buying-policies/quotas/rules — ADM-BUYING-POLICY-152
  • GET /v1/buying-policies/quotas/rules — ADM-BUYING-POLICY-553
  • PUT /v1/buying-policies/quotas/rules/:ruleId — ADM-BUYING-POLICY-206
  • DELETE /v1/buying-policies/quotas/rules/:ruleId — ADM-BUYING-POLICY-302

Quotas — co-validation groups

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

Blocking reasons & overrides

  • GET /v1/buying-policies/blocking-reasons — ADM-BUYING-POLICY-552
  • POST /v1/logistic-orders/unblock — ADM-ORDER-150
  • GET /v1/logistic-orders/:logisticOrderId/unblock-history — ADM-ORDER-550