# Ohda API v1

Base URL:

```text
https://api.example.com/api/v1
```

كل الطلبات والردود JSON. كل المسارات ماعدا `auth/login` و`health` تحتاج:

```text
Authorization: Bearer TOKEN
```

## المصادقة

### `POST /auth/login`

```json
{
  "identifier": "01000000000",
  "password": "strong-password",
  "device_name": "Ahmed Windows"
}
```

### `GET /me`

بيانات المستخدم الحالي ودوره وحالة تغيير كلمة المرور.

### `POST /auth/change-password`

```json
{
  "current_password": "temporary-password",
  "new_password": "new-strong-password"
}
```

## الموظفون — المدير فقط

- `GET /users`
- `POST /users`
- `PATCH /users/{id}/status`
- `POST /users/{id}/reset-password`

إنشاء موظف:

```json
{
  "name": "أحمد",
  "phone": "01011111111",
  "email": "ahmed@example.com",
  "temporary_password": "TempPass-2026",
  "role": "employee"
}
```

لا يوجد endpoint تسجيل ذاتي.

## البيعات والبنود والدفعات

### `POST /deals` — المدير

```json
{
  "name": "بيعة بنك",
  "source": "مزاد البنك الأهلي",
  "purchase_cost": 100000,
  "transport_cost": 5000,
  "items": [
    {"name": "لابتوبات"},
    {"name": "مكاتب"},
    {"name": "كراسي"}
  ]
}
```

- `GET /deals`: المدير يرى الجميع، والموظف يرى المسند له فقط.
- `GET /deals/{id}`
- `POST /deals/{id}/items`

### `POST /deal-items/{id}/batches` — إضافة دفعة لنفس البيعة

```json
{
  "expected_quantity": 50,
  "purchase_cost": 250000,
  "transport_cost": 3500,
  "notes": "دفعة إضافية من نفس البيعة"
}
```

### `POST /assignments`

إسناد البيعة كلها: اترك `deal_item_id` و`batch_id` بدون إرسال.

```json
{
  "deal_id": 1,
  "deal_item_id": 2,
  "batch_id": 4,
  "employee_ids": [2, 3],
  "is_shared": true
}
```

## الاستلام والجرد

### `POST /batches/{id}/receive`

```json
{"decision":"accepted","notes":"تم الاستلام"}
```

### `POST /batches/{id}/inventory`

```json
{
  "lines": [
    {
      "name": "Laptop Dell Latitude 5420",
      "quantity": 40,
      "unit": "piece",
      "condition_label": "سليم",
      "suggested_price": 14500,
      "unit_cost": 11200
    },
    {
      "name": "Laptop Lenovo",
      "quantity": 10,
      "condition_label": "يحتاج صيانة",
      "suggested_price": 0
    }
  ]
}
```

- `POST /inventories/{id}/submit`
- `POST /inventories/{id}/approve` — المدير
- `POST /inventories/{id}/request-changes` — المدير، body يحتوي `reason`.
- `GET /stock?search=Dell`

المخزون لا يصبح متاحًا للبيع إلا بعد اعتماد الجرد.

## العملاء

- `GET /customers`
- `POST /customers`
- `GET /customers/{id}`
- `GET /customers/{id}/statement`

الموظف يضيف العميل لحسابه تلقائيًا. المدير يرسل `owner_employee_id`.

```json
{
  "name": "محمود السيد",
  "phone": "01001234567",
  "address": "القاهرة"
}
```

## المبيعات

### `POST /sales`

بيع مختلط، جزء الآن والباقي آجل:

```json
{
  "customer_id": 1,
  "payment_type": "mixed",
  "payment_method": "cash",
  "paid_now": 10000,
  "due_at": "2026-08-30",
  "lines": [
    {"product_id": 1, "quantity": 2, "unit_price": 14000}
  ]
}
```

في طلب المدير يجب إضافة `employee_id`. في بيع الكاش يحسب السيرفر `paid_now` مساويًا للإجمالي. السعر المستخدم هو السعر الفعلي في الطلب، وليس السعر المقترح.

- `GET /sales`
- `GET /sales/{id}`
- `POST /sales/{id}/reverse` — المدير فقط:

```json
{
  "reason": "إلغاء العملية وإرجاع البضاعة",
  "refund_account": "employee"
}
```

## التحصيل

### `POST /collections`

```json
{
  "customer_id": 1,
  "amount": 7000,
  "payment_method": "cash",
  "notes": "دفعة من الحساب"
}
```

يقل دين العميل ويزيد المبلغ في عهدة الموظف. إذا سجل المدير التحصيل بنفسه يدخل المبلغ خزينة الشركة.

- `GET /collections`
- `POST /collections/{id}/reverse` — المدير فقط، مع `reason`.

## التوريد

### `POST /remittances`

```json
{
  "amount": 7000,
  "payment_method": "cash",
  "notes": "توريد اليوم"
}
```

### `POST /remittances/{id}/receive` — المدير

```json
{"amount":6000,"notes":"استلام جزئي"}
```

الاستلام الجزئي مدعوم، ولا ينتقل المبلغ لخزينة الشركة إلا بعد هذا الطلب.

- `GET /remittances/{id}` يعرض دفعات الاستلام الجزئية.
- `POST /remittances/{id}/reject` — المدير فقط، مع `reason`، وقبل استلام أي جزء.

## مبلغ غير مفصل

### `POST /unallocated-amounts`

```json
{
  "amount": 20000,
  "payment_method": "cash",
  "notes": "الموظف قال إن المبلغ معه ولم يرسل تفاصيل البيع"
}
```

بعد تسجيل تفاصيل البيع، اربط المبلغ حتى لا يُحسب مرتين:

### `POST /unallocated-amounts/{id}/settle`

```json
{"sale_id":10,"amount":20000}
```

## الإشعارات ولوحة التحكم

- `GET /dashboard`
- `GET /notifications?unread_only=true`
- `POST /notifications/read`
- `GET /audit-logs?user_id=2&type=sale` — المدير فقط.
- `GET /reports/summary?from=2026-08-01&to=2026-08-31` — المبيعات والتكلفة والربح والسيولة.
- `GET /reports/deals/{id}` — تكلفة وربح ومخزون وموظفو كل بيعة.

```json
{"ids":[1,2,3]}
```

## الأخطاء

```json
{
  "message": "وصف واضح للمشكلة",
  "errors": {
    "field": ["سبب الخطأ"]
  }
}
```

أهم الأكواد: `401` جلسة، `403` صلاحية، `404` غير موجود، `409` تعارض حالة أو مخزون، `422` مدخلات، `429` محاولات دخول كثيرة.
