# 11 — المخزون

## نظرة عامة

نظام مخزون كامل يتتبع المنتجات، المخازن، الحركات، والجرد. القاعدة الحديدية: **لا تعديل مباشر على الكمية — كل تغيير يمر عبر حركة مخزون.**

---

## الشاشات المنفذة

### 1. قائمة المنتجات (`/inventory/products`)

**من يراها:** من لديه صلاحية `inventory.list`

**الفلاتر:**
- بحث بالاسم أو الباركود
- تصفية بالتصنيف
- تصفية بحالة المخزون (متوفر / منخفض / نفذ)

**أعمدة الجدول:**
| العمود | الوصف |
|--------|-------|
| الاسم | name_ar |
| التصنيف | category.name_ar |
| SKU | sku |
| سعر البيع | selling_price (ج.م) |
| الكمية | quantity_on_hand |
| الحد الأدنى | min_stock_level |
| تتبع المخزون | ✓/✗ |
| مفعّل | is_active |
| الإجراءات | تعديل |

---

### 2. إنشاء منتج — ويزارد (`/inventory/products/wizard`)

**خطوات:**
1. البيانات الأساسية (اسم، تصنيف، SKU)
2. التسعير (سعر الشراء، سعر البيع)
3. إعدادات المخزون (تتبع، حد أدنى، مخزن افتراضي)
4. مراجعة

---

### 3. إنشاء/تعديل منتج (`/inventory/products/create`, `/inventory/products/{id}/edit`)

**الحقول:**
| الحقل | النوع | مطلوب | ملاحظات |
|--------|------|-------|---------|
| الاسم بالعربية | text | ✓ | |
| الاسم بالإنجليزية | text | ✗ | |
| التصنيف | select | ✗ | |
| SKU | text | ✗ | فريد |
| الباركود | text | ✗ | |
| الوصف | textarea | ✗ | |
| سعر الشراء | money | ✗ | |
| سعر البيع | money | ✓ | |
| تتبع المخزون | toggle | — | |
| الحد الأدنى | number | ✗ | للتنبيه عند الوصول |
| مفعّل | toggle | — | |

---

### 4. قائمة المخازن (`/inventory/warehouses`)

**أعمدة:**
| العمود | الوصف |
|--------|-------|
| الاسم | name_ar |
| النوع | main, branch, temporary, transit |
| الفرع | branch.name_ar |
| الحالة | active/inactive |

**إنشاء/تعديل (`/inventory/warehouses/create`, `/inventory/warehouses/{id}/edit`):**
| الحقل | النوع | مطلوب |
|--------|------|-------|
| الاسم بالعربية | text | ✓ |
| الاسم بالإنجليزية | text | ✗ |
| النوع | select | ✓ |
| الفرع | select | ✗ |
| العنوان | text | ✗ |
| مفعّل | toggle | — |

---

### 5. حركات المخزون (`/inventory/movements`)

**من يراها:** من لديه صلاحية `inventory.list`

**الفلاتر:**
- المنتج
- المخزن
- نوع الحركة
- الاتجاه (in/out)
- الفترة

**أعمدة الجدول:**
| العمود | الوصف |
|--------|-------|
| التاريخ | created_at |
| المنتج | product.name_ar |
| المخزن | warehouse.name_ar |
| النوع | movement_type |
| الاتجاه | in/out |
| الكمية | quantity |
| قبل | quantity_before |
| بعد | quantity_after |
| المرجع | reference |
| المستخدم | created_by |

---

### 6. تعديل مخزون (`/inventory/adjustments`)

**من يراها:** من لديه صلاحية `inventory.adjust`

**الحقول:**
| الحقل | النوع | مطلوب |
|--------|------|-------|
| المنتج | select | ✓ |
| المخزن | select | ✓ |
| النوع | select | ✓ | adjustment_up, adjustment_down, damage, loss |
| الكمية | number | ✓ |
| السبب | textarea | ✓ |

---

### 7. ويزارد تعديل المخزون (`/inventory/adjustments/wizard`)

**خطوات:**
1. اختيار المنتج والمخزن
2. تحديد نوع التعديل والكمية
3. إدخال السبب
4. مراجعة وتأكيد

---

## أنواع حركات المخزون

| النوع | الاتجاه | المعنى |
|-------|---------|--------|
| purchase_received | in | استلام مشتريات |
| sale | out | بيع منتج |
| transfer_out | out | نقل لمخزن آخر |
| transfer_in | in | استلام من مخزن آخر |
| return_to_stock | in | مرتجع من عميل |
| return_to_supplier | out | مرتجع للمورد |
| adjustment_up | in | تعديل بالزيادة |
| adjustment_down | out | تعديل بالنقص |
| damage | out | تالف |
| loss | out | مفقود |
| consumption | out | استهلاك داخلي |
| kit_assembly | out | تجميع طقم |
| kit_disassembly | in | تفكيك طقم |
| initial_stock | in | رصيد افتتاحي |
| count_adjustment_up | in | فرق جرد بالزيادة |
| count_adjustment_down | out | فرق جرد بالنقص |

---

## قاعدة إنشاء الحركة

```mermaid
flowchart TD
    A[طلب حركة] --> B[قفل سجل المخزون - lockForUpdate]
    B --> C[تسجيل quantity_before]
    C --> D{الاتجاه}
    D -->|in| E[إضافة للكمية]
    D -->|out| F{الكمية كافية؟}
    F -->|نعم| G[خصم من الكمية]
    F -->|لا| H[✗ InsufficientStockException]
    E --> I[تسجيل quantity_after]
    G --> I
    I --> J[إنشاء سجل الحركة]
```

---

## تنبيه المخزون المنخفض

**المهمة المجدولة:** `inventory:notify-low-stock` (يومياً 09:00)

**الشرط:**
- `quantity_on_hand ≤ min_stock_level`
- المنتج مفعّل + تتبع المخزون مفعّل

**النتيجة:** إشعار للإدارة بقائمة المنتجات التي تحتاج إعادة طلب.

---

## المصالحة الأسبوعية

**الفحص:**
```
مجموع حركات (in) - مجموع حركات (out) = الكمية الحالية
```
إذا لا تتطابق → تحذير للإدارة (لا يُصلح تلقائياً).

---

## أمثلة عملية

### مثال 1: بيع منتج عبر POS
> 1. عميل يشتري 2 تيشيرت
> 2. POS يُنشئ حركة: type=sale, direction=out, quantity=2
> 3. المخزون: 50 → 48
> 4. الحركة تُسجّل: before=50, after=48

### مثال 2: استلام مشتريات
> 1. المخزن يستلم شحنة 100 كرة
> 2. حركة: type=purchase_received, direction=in, quantity=100
> 3. المخزون: 20 → 120

### مثال 3: جرد ووجود فرق
> 1. الجرد الفعلي: 47 تيشيرت
> 2. النظام يقول: 50 تيشيرت
> 3. تعديل: type=count_adjustment_down, quantity=3, reason="فرق جرد"
> 4. المخزون: 50 → 47

### مثال 4: منتج بدون تتبع مخزون
> - "خدمة تصوير" — سعرها 50 ج.م
> - track_inventory = false
> - عند البيع: لا تُنشأ حركة مخزون
> - مناسب للخدمات

### مثال 5: تنبيه مخزون منخفض
> - "كرة قدم" — الحد الأدنى: 10
> - الكمية الحالية: 8
> - المهمة المجدولة: إشعار "كرة قدم وصلت للحد الأدنى — أعد الطلب"

---

## لماذا يحتاج عملك هذا

| الميزة | الفائدة |
|--------|---------|
| تتبع الحركات | تعرف أين ذهبت كل قطعة |
| القفل (lockForUpdate) | لا race conditions — بيعين متزامنين لا يفسدان الكمية |
| التنبيه | لا تنفذ البضاعة بدون علمك |
| المخازن المتعددة | فرعين بمخازن مختلفة |
| المصالحة | يكشف السرقة أو الأخطاء |
| عدم التعديل المباشر | كل تغيير موثّق — audit trail كامل |

---

## التكاملات

| الوحدة | العلاقة |
|--------|---------|
| نقطة البيع | بيع منتج → حركة خروج |
| المالية | مشتريات → فاتورة مورد + حركة دخول |
| التنبيهات | مخزون منخفض → إشعار |
| التقارير | تقرير حركة المخزون |
