{
  "openapi": "3.0.3",
  "info": {
    "title": "SoftPro API",
    "version": "1.0.0",
    "description": "واجهة REST تتيح لكل زبون مشترك في SOFTPRO الوصول إلى بيانات برنامجه: الأصناف، الأسعار، الكميات، الزبائن، الفواتير، التقارير، وإنشاء الطلبيات.\n\nالمفتاح وحده يحدّد قاعدة البيانات المستهدفة."
  },
  "servers": [
    { "url": "https://api.softpro-lb.com", "description": "الإنتاج" }
  ],
  "security": [{ "bearerAuth": [] }],
  "tags": [
    { "name": "system", "description": "الفحص وهوية المفتاح" },
    { "name": "meta", "description": "البيانات المرجعية" },
    { "name": "catalog", "description": "الأصناف والتصنيفات" },
    { "name": "inventory", "description": "المخزون" },
    { "name": "customers", "description": "الزبائن" },
    { "name": "invoices", "description": "الفواتير" },
    { "name": "orders", "description": "الطلبيات" },
    { "name": "reports", "description": "التقارير" }
  ],
  "paths": {
    "/v1/ping": {
      "get": {
        "tags": ["system"], "summary": "فحص الخدمة", "security": [],
        "responses": { "200": { "description": "الخدمة تعمل" } }
      }
    },
    "/v1/me": {
      "get": {
        "tags": ["system"], "summary": "معلومات المفتاح الحالي وصلاحياته",
        "responses": {
          "200": { "description": "نجاح" },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/scopes": {
      "get": { "tags": ["system"], "summary": "الصلاحيات المتاحة وأيها ممنوح",
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/meta/units":      { "get": { "tags": ["meta"], "summary": "الوحدات", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/meta/warehouses": { "get": { "tags": ["meta"], "summary": "المستودعات", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/meta/branches":   { "get": { "tags": ["meta"], "summary": "الفروع", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/meta/currencies": { "get": { "tags": ["meta"], "summary": "العملات وأسعار الصرف", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/meta/regions":    { "get": { "tags": ["meta"], "summary": "المناطق وكلفة التوصيل", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/meta/salesmen":   { "get": { "tags": ["meta"], "summary": "المندوبون", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/meta/areas":      { "get": { "tags": ["meta"], "summary": "المناطق الجغرافية", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/meta/company":    { "get": { "tags": ["meta"], "summary": "بيانات الشركة", "responses": { "200": { "description": "نجاح" } } } },

    "/v1/categories": {
      "get": { "tags": ["catalog"], "summary": "التصنيفات",
        "parameters": [{ "name": "with_counts", "in": "query", "schema": { "type": "boolean" } }],
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/brands":   { "get": { "tags": ["catalog"], "summary": "الماركات", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/sections": { "get": { "tags": ["catalog"], "summary": "الأقسام", "responses": { "200": { "description": "نجاح" } } } },
    "/v1/lists":    { "get": { "tags": ["catalog"], "summary": "قوائم الأصناف", "responses": { "200": { "description": "نجاح" } } } },

    "/v1/items": {
      "get": {
        "tags": ["catalog"],
        "summary": "قائمة الأصناف",
        "description": "لا يوجد فلتر افتراضي — تُعاد كل الأصناف ما لم تحدّد فلتراً.",
        "parameters": [
          { "name": "search", "in": "query", "schema": { "type": "string" }, "description": "الاسم أو الكود أو الباركود" },
          { "name": "ids", "in": "query", "schema": { "type": "string" }, "description": "أرقام مفصولة بفاصلة" },
          { "name": "category", "in": "query", "schema": { "type": "string" } },
          { "name": "brand", "in": "query", "schema": { "type": "string" } },
          { "name": "list", "in": "query", "schema": { "type": "string" } },
          { "name": "price_list", "in": "query", "schema": { "type": "integer", "enum": [1, 2, 3] } },
          { "name": "warehouse", "in": "query", "schema": { "type": "string" }, "description": "رقم المستودع أو all" },
          { "name": "in_stock", "in": "query", "schema": { "type": "boolean" } },
          { "name": "min_price", "in": "query", "schema": { "type": "number" } },
          { "name": "max_price", "in": "query", "schema": { "type": "number" } },
          { "name": "active", "in": "query", "schema": { "type": "boolean" } },
          { "name": "visible", "in": "query", "schema": { "type": "boolean" } },
          { "name": "display_in_pos", "in": "query", "schema": { "type": "boolean" } },
          { "name": "updated_since", "in": "query", "schema": { "type": "string" }, "example": "2026-08-01 00:00" },
          { "name": "include", "in": "query", "schema": { "type": "string" }, "example": "units,barcodes,stock_by_warehouse" },
          { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["name", "code", "price", "stock", "updated", "id"] } },
          { "$ref": "#/components/parameters/Order" },
          { "$ref": "#/components/parameters/Page" },
          { "$ref": "#/components/parameters/PerPage" }
        ],
        "responses": {
          "200": {
            "description": "نجاح",
            "content": { "application/json": { "schema": {
              "allOf": [
                { "$ref": "#/components/schemas/Envelope" },
                { "type": "object", "properties": {
                    "data": { "type": "array", "items": { "$ref": "#/components/schemas/Item" } } } }
              ] } } }
          },
          "403": { "$ref": "#/components/responses/Forbidden" }
        }
      }
    },
    "/v1/items/{id}": {
      "get": { "tags": ["catalog"], "summary": "صنف واحد",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }],
        "responses": { "200": { "description": "نجاح" }, "404": { "$ref": "#/components/responses/NotFound" } } }
    },
    "/v1/items/barcode/{barcode}": {
      "get": { "tags": ["catalog"], "summary": "البحث بالباركود",
        "parameters": [{ "name": "barcode", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "نجاح" }, "404": { "$ref": "#/components/responses/NotFound" } } }
    },
    "/v1/items/{id}/stock": {
      "get": { "tags": ["inventory"], "summary": "كميات صنف في كل المستودعات",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }],
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/inventory": {
      "get": { "tags": ["inventory"], "summary": "جرد عام",
        "parameters": [
          { "name": "warehouse", "in": "query", "schema": { "type": "integer" } },
          { "name": "non_zero", "in": "query", "schema": { "type": "boolean" } },
          { "name": "search", "in": "query", "schema": { "type": "string" } },
          { "$ref": "#/components/parameters/Page" },
          { "$ref": "#/components/parameters/PerPage" }
        ],
        "responses": { "200": { "description": "نجاح" } } }
    },

    "/v1/customers": {
      "get": { "tags": ["customers"], "summary": "قائمة الزبائن",
        "parameters": [
          { "name": "search", "in": "query", "schema": { "type": "string" } },
          { "name": "region", "in": "query", "schema": { "type": "string" } },
          { "name": "salesman", "in": "query", "schema": { "type": "string" } },
          { "name": "active", "in": "query", "schema": { "type": "boolean" } },
          { "name": "sort", "in": "query", "schema": { "type": "string", "enum": ["name", "code", "balance", "id"] } },
          { "$ref": "#/components/parameters/Page" },
          { "$ref": "#/components/parameters/PerPage" }
        ],
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/customers/{id}": {
      "get": { "tags": ["customers"], "summary": "زبون واحد",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } }],
        "responses": { "200": { "description": "نجاح" }, "404": { "$ref": "#/components/responses/NotFound" } } }
    },
    "/v1/customers/{id}/statement": {
      "get": { "tags": ["customers"], "summary": "كشف حساب",
        "parameters": [
          { "name": "id", "in": "path", "required": true, "schema": { "type": "integer" } },
          { "$ref": "#/components/parameters/From" },
          { "$ref": "#/components/parameters/To" },
          { "$ref": "#/components/parameters/Page" }
        ],
        "responses": { "200": { "description": "نجاح" } } }
    },

    "/v1/invoices": {
      "get": { "tags": ["invoices"], "summary": "قائمة الفواتير",
        "parameters": [
          { "$ref": "#/components/parameters/From" },
          { "$ref": "#/components/parameters/To" },
          { "name": "customer", "in": "query", "schema": { "type": "string" } },
          { "name": "typedoc", "in": "query", "schema": { "type": "string" } },
          { "name": "warehouse", "in": "query", "schema": { "type": "string" } },
          { "name": "branch", "in": "query", "schema": { "type": "string" } },
          { "name": "salesman", "in": "query", "schema": { "type": "string" } },
          { "name": "closed", "in": "query", "schema": { "type": "boolean" } },
          { "name": "with_lines", "in": "query", "schema": { "type": "boolean" } },
          { "$ref": "#/components/parameters/Page" },
          { "$ref": "#/components/parameters/PerPage" }
        ],
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/invoices/{id}": {
      "get": { "tags": ["invoices"], "summary": "فاتورة واحدة مع سطورها",
        "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" },
          "description": "IDAUTO أو SyncID" }],
        "responses": { "200": { "description": "نجاح" }, "404": { "$ref": "#/components/responses/NotFound" } } }
    },

    "/v1/orders": {
      "get": { "tags": ["orders"], "summary": "قائمة الطلبيات",
        "parameters": [
          { "name": "status", "in": "query", "schema": { "type": "string" } },
          { "$ref": "#/components/parameters/From" },
          { "$ref": "#/components/parameters/To" },
          { "name": "customer", "in": "query", "schema": { "type": "string" } },
          { "name": "search", "in": "query", "schema": { "type": "string" } },
          { "name": "with_lines", "in": "query", "schema": { "type": "boolean" } },
          { "$ref": "#/components/parameters/Page" },
          { "$ref": "#/components/parameters/PerPage" }
        ],
        "responses": { "200": { "description": "نجاح" } } },
      "post": {
        "tags": ["orders"],
        "summary": "إنشاء طلبية",
        "description": "الأسعار تُحسب على الخادم من قاعدة البيانات؛ أي سعر يرسله العميل يُتجاهل. الطلبية لا تخصم المخزون.",
        "parameters": [{
          "name": "Idempotency-Key", "in": "header", "schema": { "type": "string" },
          "description": "يمنع التكرار عند إعادة الإرسال"
        }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OrderInput" } } }
        },
        "responses": {
          "201": { "description": "أُنشئت" },
          "200": { "description": "طلبية سابقة بنفس Idempotency-Key" },
          "422": { "$ref": "#/components/responses/Validation" }
        }
      }
    },
    "/v1/orders/{uid}": {
      "get": { "tags": ["orders"], "summary": "طلبية واحدة",
        "parameters": [{ "name": "uid", "in": "path", "required": true, "schema": { "type": "string" } }],
        "responses": { "200": { "description": "نجاح" }, "404": { "$ref": "#/components/responses/NotFound" } } },
      "patch": { "tags": ["orders"], "summary": "تحديث حالة الطلبية",
        "parameters": [{ "name": "uid", "in": "path", "required": true, "schema": { "type": "string" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": {
          "type": "object", "required": ["status"], "properties": {
            "status": { "type": "string", "enum": ["pending", "confirmed", "preparing", "delivered", "cancelled", "rejected"] },
            "status_note": { "type": "string" } } } } } },
        "responses": { "200": { "description": "نجاح" } } }
    },

    "/v1/reports/sales-summary": {
      "get": { "tags": ["reports"], "summary": "ملخّص المبيعات",
        "parameters": [
          { "$ref": "#/components/parameters/From" },
          { "$ref": "#/components/parameters/To" },
          { "name": "group_by", "in": "query", "schema": { "type": "string",
            "enum": ["day", "month", "customer", "salesman", "warehouse", "typedoc"] } },
          { "name": "typedoc", "in": "query", "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/reports/top-items": {
      "get": { "tags": ["reports"], "summary": "الأصناف الأكثر مبيعاً",
        "parameters": [
          { "$ref": "#/components/parameters/From" },
          { "$ref": "#/components/parameters/To" },
          { "name": "metric", "in": "query", "schema": { "type": "string", "enum": ["amount", "qty"] } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20 } }
        ],
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/reports/top-customers": {
      "get": { "tags": ["reports"], "summary": "الزبائن الأكثر شراءً",
        "parameters": [
          { "$ref": "#/components/parameters/From" },
          { "$ref": "#/components/parameters/To" },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 20 } }
        ],
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/reports/inventory-value": {
      "get": { "tags": ["reports"], "summary": "قيمة المخزون",
        "parameters": [{ "name": "warehouse", "in": "query", "schema": { "type": "integer" } }],
        "responses": { "200": { "description": "نجاح" } } }
    },
    "/v1/reports/low-stock": {
      "get": { "tags": ["reports"], "summary": "الأصناف تحت حد التنبيه",
        "parameters": [
          { "name": "warehouse", "in": "query", "schema": { "type": "integer" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 100 } }
        ],
        "responses": { "200": { "description": "نجاح" } } }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": { "type": "http", "scheme": "bearer", "description": "المفتاح بصيغة sp_live_... أو sp_test_..." }
    },
    "parameters": {
      "Page":    { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1, "minimum": 1 } },
      "PerPage": { "name": "per_page", "in": "query", "schema": { "type": "integer", "default": 50, "maximum": 200 } },
      "Order":   { "name": "order", "in": "query", "schema": { "type": "string", "enum": ["asc", "desc"] } },
      "From":    { "name": "from", "in": "query", "schema": { "type": "string", "format": "date" }, "example": "2026-08-01" },
      "To":      { "name": "to", "in": "query", "schema": { "type": "string", "format": "date" }, "example": "2026-08-26" }
    },
    "responses": {
      "Unauthorized": { "description": "مفتاح مفقود أو غير صالح",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Forbidden": { "description": "صلاحية ناقصة أو اشتراك منتهٍ",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "NotFound": { "description": "غير موجود",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Validation": { "description": "بيانات غير صحيحة",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": true },
          "data": {},
          "meta": { "$ref": "#/components/schemas/Meta" },
          "request_id": { "type": "string", "format": "uuid" }
        }
      },
      "Meta": {
        "type": "object",
        "properties": {
          "page": { "type": "integer" },
          "per_page": { "type": "integer" },
          "total": { "type": "integer" },
          "total_pages": { "type": "integer" },
          "has_more": { "type": "boolean" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": false },
          "error": {
            "type": "object",
            "properties": {
              "code": { "type": "string", "example": "insufficient_scope" },
              "message": { "type": "string" },
              "details": { "type": "object", "additionalProperties": true }
            }
          },
          "request_id": { "type": "string", "format": "uuid" }
        }
      },
      "Item": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "code": { "type": "string", "nullable": true },
          "name": { "type": "string", "nullable": true },
          "category": { "$ref": "#/components/schemas/Ref" },
          "brand": { "$ref": "#/components/schemas/Ref" },
          "currency": {
            "type": "object",
            "properties": {
              "id": { "type": "integer", "nullable": true },
              "code": { "type": "string", "nullable": true },
              "name": { "type": "string", "nullable": true },
              "decimals": { "type": "integer" }
            }
          },
          "sales_unit": {
            "type": "object",
            "properties": {
              "id": { "type": "integer", "nullable": true },
              "name": { "type": "string", "nullable": true },
              "abbreviation": { "type": "string", "nullable": true },
              "factor": { "type": "number" }
            }
          },
          "base_unit_id": { "type": "integer", "nullable": true },
          "price": { "type": "number" },
          "price_list": { "type": "integer" },
          "barcode": { "type": "string", "nullable": true },
          "stock": {
            "type": "object",
            "properties": {
              "warehouse_id": { "type": "integer", "nullable": true },
              "qty": { "type": "number" },
              "total_qty": { "type": "number" },
              "in_stock": { "type": "boolean" },
              "min_warning": { "type": "integer", "nullable": true }
            }
          },
          "flags": {
            "type": "object",
            "properties": {
              "is_service": { "type": "boolean" },
              "is_scale": { "type": "boolean" },
              "has_serial": { "type": "boolean" },
              "is_double": { "type": "boolean" },
              "display_in_pos": { "type": "boolean" },
              "visible": { "type": "boolean" },
              "active": { "type": "boolean" },
              "price_from_base_unit": { "type": "boolean" }
            }
          },
          "cost": {
            "type": "object",
            "description": "يظهر فقط للمفاتيح التي تملك reports:read",
            "properties": {
              "cost": { "type": "number" },
              "last_cost": { "type": "number" },
              "avg_cost": { "type": "number" }
            }
          },
          "units": { "type": "array", "items": { "$ref": "#/components/schemas/ItemUnit" } },
          "barcodes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "barcode": { "type": "string" },
                "unit_id": { "type": "integer" }
              }
            }
          },
          "updated_at": { "type": "string", "format": "date-time", "nullable": true }
        }
      },
      "ItemUnit": {
        "type": "object",
        "properties": {
          "unit_id": { "type": "integer" },
          "name": { "type": "string", "nullable": true },
          "abbreviation": { "type": "string", "nullable": true },
          "factor": { "type": "number" },
          "barcode": { "type": "string", "nullable": true },
          "prices": {
            "type": "object",
            "properties": {
              "1": { "type": "number" },
              "2": { "type": "number" },
              "3": { "type": "number" }
            }
          }
        }
      },
      "Ref": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "nullable": true },
          "name": { "type": "string", "nullable": true }
        }
      },
      "OrderInput": {
        "type": "object",
        "required": ["items"],
        "properties": {
          "customer_id": { "type": "integer", "nullable": true },
          "customer": {
            "type": "object",
            "properties": {
              "name": { "type": "string" },
              "phone": { "type": "string" },
              "email": { "type": "string" },
              "address": { "type": "string" },
              "region_id": { "type": "integer" }
            }
          },
          "warehouse_id": { "type": "integer" },
          "branch_id": { "type": "integer" },
          "salesman_id": { "type": "integer" },
          "price_list": { "type": "integer", "enum": [1, 2, 3] },
          "payment_method": { "type": "string", "enum": ["cash", "card", "transfer", "on_delivery", "credit"] },
          "delivery_fee": { "type": "number" },
          "discount": { "type": "number" },
          "vat_percent": { "type": "number" },
          "check_stock": { "type": "boolean", "default": false },
          "notes": { "type": "string" },
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 300,
            "items": {
              "type": "object",
              "required": ["qty"],
              "properties": {
                "item_id": { "type": "integer" },
                "barcode": { "type": "string" },
                "unit_id": { "type": "integer" },
                "qty": { "type": "number", "minimum": 0.0001 },
                "discount": { "type": "number" },
                "vat_percent": { "type": "number" },
                "notes": { "type": "string" }
              }
            }
          }
        }
      }
    }
  }
}
