# إدارة الباقات والخدمات

## نظرة عامة

نظام لإدارة **Packages** و **Services** بحيث:

* الـPackage يحتوي على مجموعة من الـServices وله سعر خاص به.
* الـService يمكن أن ينتمي إلى أكثر من Package.
* الـProject ينتمي إلى Package واحدة.
* عند إنشاء Project يتم نسخ خدمات الـPackage إلى `project_service`.
* يمكن إضافة Additional Services للمشروع.
* يتم تمييز Additional Services من خلال `package_id = NULL`.
* يتم إنشاء Quotation تلقائيًا عند إنشاء المشروع.
* الـQuotation يحتفظ بسعر الـPackage كـSnapshot.
* الـPayment يعتمد على الـQuotation وليس الأسعار الحالية.

---

# Database

```text
packages
- id
- name_en
- name_ar
- price
- timestamps

services
- id
- name_en
- name_ar
- price
- timestamps

package_service
- package_id
- service_id

projects
- id
- package_id
- ...

project_service
- id
- project_id
- service_id
- package_id nullable
- price
- timestamps

quotations
- id
- project_id
- package_id
- package_price
- total
- timestamps
```

---

# Project Services

الـ`project_service` يمثل الخدمات الفعلية المرتبطة بالمشروع.

```text
project_service

project_id | service_id | package_id | price
-----------|------------|------------|------
1          | A          | 1          | 100
1          | B          | 1          | 200
1          | C          | 1          | 150
1          | D          | 1          | 250
1          | E          | 1          | 300
1          | X          | NULL       | 500
```

### تحديد نوع الخدمة

```text
package_id != NULL
→ Package Service

package_id = NULL
→ Additional Service
```

وبالتالي لا نحتاج إلى تخزين `additional_services` داخل الـQuotation.

للحصول على Additional Services:

```php
$project->services()
    ->wherePivotNull('package_id')
    ->get();
```

---

# Package Pricing

**سعر الـPackage يشمل جميع الخدمات الموجودة بداخله.**

لذلك لا يتم إضافة أسعار Package Services إلى الـTotal مرة أخرى.

مثال:

```text
Package:
Basic = 1,000

Included Services:
A
B
C
D
E

Additional Service:
X = 500

Total = 1,500
```

المعادلة:

```text
Total =
    Package Price
    +
    Additional Services Prices
```

---

# Quotation

الـQuotation هو **Financial Snapshot**.

لا نحتاج إلى:

```text
quotation_services
additional_services
```

ويكون جدول الـQuotation:

```text
quotations

id
project_id
package_id
package_price
total
created_at
updated_at
```

مثال:

```text
Package Price = 1,000
Additional Services = 500
Total = 1,500
```

الـAdditional Services يتم الحصول عليها من:

```text
project_service
WHERE package_id IS NULL
```

ولا يتم تخزينها مرة أخرى في الـQuotation.

---

# Price Snapshot

عند إنشاء المشروع:

```text
Package = 1,000

Additional Service X = 500

Quotation:
package_price = 1,000
total = 1,500
```

إذا تغيرت الأسعار لاحقًا:

```text
Package = 1,500
Service X = 700
```

الـQuotation القديم يظل:

```text
package_price = 1,000
total = 1,500
```

---

# Project Creation Flow

```text
Create Project
      ↓
Validate Package
      ↓
Get Package Services
      ↓
Create Project
      ↓
Create Package Services
      ↓
Create Additional Services
      ↓
Calculate Total
      ↓
Create Quotation
      ↓
Snapshot Package Price
      ↓
Snapshot Total
```

كل العمليات تتم داخل:

```php
DB::transaction()
```

---

# Payment

الـPayment يعتمد على:

```php
$quotation->package_price;
$quotation->total;
```

ولا يعتمد على:

```php
$package->price;
$service->price;
```

لأن الأسعار الحالية قد تختلف عن الأسعار وقت إنشاء الـQuotation.

---

# العلاقات

### Package

```text
Package
 ├── belongsToMany Services
 └── hasMany Projects
```

### Service

```text
Service
 ├── belongsToMany Packages
 └── belongsToMany Projects
```

### Project

```text
Project
 ├── belongsTo Package
 ├── belongsToMany Services
 └── hasMany Quotations
```

### Quotation

```text
Quotation
 ├── belongsTo Project
 └── belongsTo Package
```

---

# Business Rules

1. الـPackage له سعر مستقل.
2. سعر الـPackage يشمل Package Services.
3. Package ↔ Service علاقة Many-to-Many.
4. Project ينتمي إلى Package واحدة.
5. خدمات الـPackage يتم نسخها إلى `project_service` عند إنشاء المشروع.
6. Additional Services يتم تخزينها في `project_service` مع `package_id = NULL`.
7. تغيير خدمات الـPackage لا يؤثر على المشاريع القديمة.
8. تغيير سعر الـPackage لا يؤثر على الـQuotations القديمة.
9. تغيير سعر الـService لا يؤثر على الـQuotations القديمة.
10. لا يوجد `quotation_services`.
11. لا يوجد `additional_services` في `quotations`.
12. الـQuotation يخزن `package_price` و`total` كـSnapshot.
13. Additional Services يتم تحديدها من `project_service`.
14. الـPayment يعتمد على الـQuotation.
15. إنشاء Project وServices وQuotation يتم داخل Transaction.

---

# Acceptance Criteria

* [ ] Package له Price.
* [ ] Package يحتوي على Services.
* [ ] Service يمكن أن ينتمي إلى عدة Packages.
* [ ] Project ينتمي إلى Package واحدة.
* [ ] Package Services يتم نسخها إلى `project_service`.
* [ ] Additional Services يتم تخزينها في `project_service` مع `package_id = NULL`.
* [ ] يتم إنشاء Quotation تلقائيًا.
* [ ] Quotation يحتوي على `package_price`.
* [ ] Quotation يحتوي على `total`.
* [ ] تغيير الأسعار لا يؤثر على الـQuotation القديم.
* [ ] Payment يستخدم أسعار الـQuotation.
* [ ] العملية بالكامل داخل Database Transaction.
