{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.surinder.design/saga/ds/schema/order.schema.json",
  "title": "Order",
  "description": "The 1 order object. Every channel renders from it and nothing else. Mirrors src/case/types.ts.",
  "type": "object",
  "required": ["id", "merchant", "buyer", "approver", "subject", "lines", "total", "approval", "status"],
  "properties": {
    "id": { "type": "string", "examples": ["DP-20418"] },
    "merchant": {
      "type": "object",
      "required": ["name", "template"],
      "properties": {
        "name": { "type": "string", "examples": ["Delta Parts"] },
        "template": { "type": "string", "description": "The trade template. Any trade Saga builds from the 3 rule types", "examples": ["autoparts", "food", "labsupplies"] },
        "brand": { "type": "string", "description": "color.brand.base, the 1 primitive a merchant changes" }
      }
    },
    "buyer": {
      "type": "object",
      "required": ["company", "role"],
      "properties": {
        "company": { "type": "string" },
        "role": { "type": "string", "description": "A role, never a person's name", "examples": ["Workshop lead"] }
      }
    },
    "approver": {
      "type": "object",
      "required": ["role", "limit"],
      "properties": {
        "role": { "type": "string", "examples": ["Workshop owner"] },
        "limit": { "type": "number", "description": "Spend limit in the order's currency, set by the buyer's company" }
      }
    },
    "subject": {
      "type": "object",
      "description": "The vehicle or venue the order is for",
      "required": ["kind", "title", "id", "foundBy"],
      "properties": {
        "kind": { "type": "string", "description": "What the order is for", "examples": ["vehicle", "venue", "ward"] },
        "title": { "type": "string" },
        "detail": { "type": "string" },
        "id": { "type": "string", "description": "Plate, or the account" },
        "id2": { "type": "string", "description": "VIN, or the delivery point" },
        "foundBy": { "type": "string", "description": "Plate, VIN photo or past orders. Never the job card" }
      }
    },
    "lines": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/line" }
    },
    "total": { "type": "number" },
    "currency": { "type": "string", "pattern": "^[A-Z]{3}$", "description": "ISO 4217 code", "examples": ["EUR", "GBP", "USD"] },
    "approval": { "enum": ["none", "waiting", "reminded", "approved", "declined"] },
    "status": { "enum": ["open", "placed", "undone", "returned", "delivered"] },
    "undoUntil": { "type": ["string", "null"], "description": "Clock time undo closes, or until the van leaves, whichever comes first" },
    "log": { "type": "array", "items": { "$ref": "#/$defs/logEntry" } }
  },
  "$defs": {
    "source": {
      "type": "object",
      "description": "Where a number came from and how old it is. Every number carries 1",
      "required": ["system", "ageMin"],
      "properties": {
        "system": { "type": "string", "examples": ["ERP", "Catalog"] },
        "ageMin": { "type": "number", "minimum": 0 }
      }
    },
    "fitPart": {
      "type": "object",
      "required": ["label", "points", "max"],
      "properties": {
        "label": { "type": "string", "examples": ["Part cross-reference", "Fits this VIN", "Key specs match", "Exact OE part"] },
        "points": { "type": "number" },
        "max": { "type": "number" },
        "required": { "type": "boolean", "description": "With 0 points here the part can never act alone, whatever the threshold. For a vehicle: a part not listed for the VIN" }
      }
    },
    "stock": {
      "type": "object",
      "required": ["location", "qty", "arrives", "source"],
      "properties": {
        "location": { "type": "string" },
        "kind": { "enum": ["main", "branch"] },
        "qty": { "type": "integer", "minimum": 0 },
        "arrives": { "type": "string" },
        "source": { "$ref": "#/$defs/source" }
      }
    },
    "pick": {
      "type": "object",
      "description": "The part the agent ordered, proposes, or a sales rep confirmed",
      "required": ["sku", "name", "brand", "partNo", "price", "fit", "score", "stock"],
      "properties": {
        "sku": { "type": "string" },
        "name": { "type": "string" },
        "brand": { "type": "string" },
        "partNo": { "type": "string" },
        "price": { "type": ["number", "null"], "description": "Contract price per unit. null means no contract price, a hard rule" },
        "fit": { "type": "array", "items": { "$ref": "#/$defs/fitPart" } },
        "score": { "type": "number", "minimum": 0, "maximum": 100 },
        "stock": { "$ref": "#/$defs/stock" },
        "note": { "type": "string" }
      }
    },
    "line": {
      "type": "object",
      "required": ["category", "asked", "qty", "unit", "state", "band", "threshold", "why"],
      "properties": {
        "category": { "type": "string", "examples": ["cooling", "dairy"] },
        "safety": { "type": "boolean", "description": "Safety category: no action button, a person decides" },
        "asked": { "type": "string", "description": "What the buyer asked for, in their words" },
        "qty": { "type": "number" },
        "unit": { "type": "string" },
        "pick": { "oneOf": [{ "$ref": "#/$defs/pick" }, { "type": "null" }] },
        "state": { "enum": ["acted", "asked", "handed"] },
        "band": { "enum": ["high", "mid", "low", "rule"] },
        "hardRule": { "type": ["string", "null"] },
        "threshold": { "type": "number", "minimum": 70, "maximum": 100 },
        "why": { "type": "string", "description": "Plain English. Never a score without a why" },
        "resolvedBy": { "enum": ["agent", "buyer", "rep", null] }
      }
    },
    "logEntry": {
      "type": "object",
      "required": ["at", "actor", "channel", "text"],
      "properties": {
        "at": { "type": "string" },
        "actor": { "enum": ["ordering", "fulfilment", "review", "setup", "buyerAgent", "buyer", "approver", "rep", "admin"] },
        "channel": { "enum": ["voice", "whatsapp", "chat", "webshop", "email", "erp", "settings"] },
        "text": { "type": "string" },
        "source": { "$ref": "#/$defs/source" },
        "state": { "enum": ["acted", "asked", "handed"] }
      }
    }
  }
}
