{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://partuvo.local/schema/partuvo-sales-v1.schema.json",
  "title": "partuvo-sales v1",
  "description": "Verkaufsdatei für Partuvo (Import und Export). Der Betrieb steht nicht in der Datei. Siehe docs/SALES-FILES.md.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "format",
    "version",
    "orders"
  ],
  "properties": {
    "format": {
      "const": "partuvo-sales"
    },
    "version": {
      "const": 1
    },
    "exportedAt": {
      "type": "string",
      "format": "date-time"
    },
    "timezone": {
      "const": "UTC"
    },
    "count": {
      "type": "integer"
    },
    "source": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "channel": {
          "type": "string"
        },
        "account": {
          "type": "string"
        }
      },
      "description": "Vorgabe für channel/account, wenn eine Bestellung sie nicht nennt."
    },
    "filters": {
      "type": "object"
    },
    "snapshot": {
      "type": "object"
    },
    "orders": {
      "type": "array",
      "maxItems": 2000,
      "items": {
        "$ref": "#/$defs/order"
      }
    }
  },
  "$defs": {
    "order": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "orderId",
        "channel",
        "account",
        "orderedAt",
        "orderStatus",
        "currency",
        "priceBasis",
        "buyerName",
        "lines"
      ],
      "properties": {
        "orderId": {
          "description": "Bestellnummer im Quellsystem",
          "type": "string",
          "maxLength": 100
        },
        "channel": {
          "description": "Quelle/Kanal, z. B. ebay, shop; partuvo = eigene Aufträge im Export",
          "type": "string",
          "maxLength": 80,
          "pattern": "^[a-z0-9][a-z0-9._-]{0,79}$"
        },
        "account": {
          "description": "Verkäuferkonto in der Quelle (ohne Groß-/Kleinschreibung)",
          "type": "string",
          "maxLength": 80
        },
        "orderedAt": {
          "description": "Bestellzeitpunkt",
          "type": "string",
          "format": "date-time"
        },
        "orderStatus": {
          "description": "Auftragsstatus",
          "enum": [
            "draft",
            "confirmed",
            "cancelled"
          ]
        },
        "fulfillmentStatus": {
          "description": "Versandstatus",
          "enum": [
            "unfulfilled",
            "shipped"
          ]
        },
        "shippedAt": {
          "description": "Versandzeitpunkt",
          "type": "string",
          "format": "date-time"
        },
        "carrier": {
          "description": "Versanddienstleister",
          "type": "string",
          "maxLength": 120
        },
        "trackingNumber": {
          "description": "Sendungsnummer",
          "type": "string",
          "maxLength": 200
        },
        "paymentStatus": {
          "description": "Gemeldeter Zahlungsstatus (nur Dokumentation)",
          "enum": [
            "unknown",
            "pending",
            "paid",
            "partially_refunded",
            "refunded"
          ]
        },
        "cancelledAt": {
          "description": "Stornozeitpunkt",
          "type": "string",
          "format": "date-time"
        },
        "cancelReason": {
          "description": "Stornogrund",
          "type": "string",
          "maxLength": 200
        },
        "currency": {
          "description": "Währung (ISO 4217)",
          "type": "string",
          "pattern": "^[A-Z]{3}$"
        },
        "exchangeRate": {
          "description": "EUR je Einheit der Währung; Pflicht außer bei EUR",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,15}(\\.\\d{1,8})?$"
        },
        "priceBasis": {
          "description": "Preisbasis",
          "enum": [
            "net",
            "gross"
          ]
        },
        "shippingAmount": {
          "description": "Dezimalzahl mit Punkt, nicht negativ; als Text empfohlen.",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,15}(\\.\\d{1,4})?$"
        },
        "orderDiscountAmount": {
          "description": "Dezimalzahl mit Punkt, nicht negativ; als Text empfohlen.",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,15}(\\.\\d{1,4})?$"
        },
        "totalAmount": {
          "description": "Dezimalzahl mit Punkt, nicht negativ; als Text empfohlen.",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,15}(\\.\\d{1,4})?$"
        },
        "buyerName": {
          "description": "Käufer",
          "type": "string",
          "maxLength": 160
        },
        "buyerEmail": {
          "description": "E-Mail des Käufers",
          "type": "string",
          "maxLength": 254
        },
        "buyerPhone": {
          "description": "Telefon des Käufers",
          "type": "string",
          "maxLength": 80
        },
        "buyerVatId": {
          "description": "USt-IdNr. des Käufers",
          "type": "string",
          "maxLength": 80
        },
        "buyerAddress": {
          "description": "Rechnungsadresse",
          "type": "string",
          "maxLength": 1000
        },
        "shipToName": {
          "description": "Lieferempfänger",
          "type": "string",
          "maxLength": 160
        },
        "shipToAddress": {
          "description": "Lieferadresse",
          "type": "string",
          "maxLength": 1000
        },
        "customerNumber": {
          "description": "Vorhandene Partuvo-Kundennummer (K-…), exakt",
          "type": "string",
          "maxLength": 40
        },
        "notes": {
          "description": "Notiz zur Bestellung",
          "type": "string",
          "maxLength": 2000
        },
        "lines": {
          "type": "array",
          "minItems": 1,
          "maxItems": 100,
          "items": {
            "$ref": "#/$defs/line"
          }
        },
        "partuvo": {
          "type": "object",
          "description": "Nur im Partuvo-Export; der Import liest es nicht."
        }
      }
    },
    "line": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "lineItemId",
        "sku",
        "quantity",
        "unitPrice"
      ],
      "properties": {
        "lineItemId": {
          "description": "Positionskennung im Quellsystem",
          "type": "string",
          "maxLength": 100
        },
        "sku": {
          "description": "SKU des Partuvo-Teils",
          "type": "string",
          "maxLength": 80
        },
        "title": {
          "description": "Bezeichnung laut Quelle",
          "type": "string",
          "maxLength": 300
        },
        "quantity": {
          "description": "Menge in Stück",
          "type": "integer",
          "minimum": 1,
          "maximum": 1000000
        },
        "unitPrice": {
          "description": "Dezimalzahl mit Punkt, nicht negativ; als Text empfohlen.",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,15}(\\.\\d{1,4})?$"
        },
        "discountAmount": {
          "description": "Dezimalzahl mit Punkt, nicht negativ; als Text empfohlen.",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,15}(\\.\\d{1,4})?$"
        },
        "taxRate": {
          "description": "Steuersatz in Prozent; Pflicht bei Bruttopreisen",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,3}(\\.\\d{1,2})?$"
        },
        "taxAmount": {
          "description": "Dezimalzahl mit Punkt, nicht negativ; als Text empfohlen.",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,15}(\\.\\d{1,4})?$"
        },
        "lineTotal": {
          "description": "Dezimalzahl mit Punkt, nicht negativ; als Text empfohlen.",
          "type": [
            "string",
            "number"
          ],
          "pattern": "^\\d{1,15}(\\.\\d{1,4})?$"
        },
        "returnedQuantity": {
          "description": "Gemeldete Retourenmenge",
          "type": "integer",
          "minimum": 0,
          "maximum": 1000000
        },
        "partuvo": {
          "type": "object"
        }
      }
    }
  }
}
