# تحليل جدول سندات القبض (receipts_voucher) والجداول المرتبطة

## 1. هيكل جدول `receipts_voucher`

### الحقول الأساسية:
- `id` - معرف السند الأساسي (Primary Key)
- `bill_number` - رقم السند الفريد
- `bill_category` - فئة السند (rental, rent_collection, commission, maintenance, deposit, utility, insurance, legal, renovation, cleaning, security, other)
- `from_party_type` - نوع الطرف الدافع (owner, office, tenant, company)
- `from_party_id` - معرف الطرف الدافع
- `to_party_type` - نوع الطرف المستلم (owner, office, tenant, company)
- `to_party_id` - معرف الطرف المستلم
- `amount` - المبلغ الأساسي
- `tax_amount` - مبلغ الضريبة
- `total_amount` - المبلغ الإجمالي شامل الضريبة
- `currency` - العملة (افتراضي: SAR)
- `payment_method` - طريقة الدفع (cash, bank_transfer, check, online, other)
- `payment_reference` - رقم المرجع أو الشيك
- `bank_name` - اسم البنك
- `account_number` - رقم الحساب
- `issue_date` - تاريخ إصدار السند
- `due_date` - تاريخ الاستحقاق
- `payment_date` - تاريخ التحصيل الفعلي
- `description` - وصف السند
- `notes` - ملاحظات إضافية
- `status` - حالة السند (draft, pending, approved, paid, cancelled)
- `approval_status` - حالة الموافقة (pending, approved, rejected)
- `approved_by` - معرف المستخدم الموافق
- `approval_date` - تاريخ الموافقة
- `rejection_reason` - سبب الرفض
- `contract_id` - رقم العقد المرتبط (Foreign Key → contracts.id)
- `property_id` - رقم العقار المرتبط (Foreign Key → properties.id)
- `created_by` - منشئ السند (Foreign Key → users.usercode)
- `office_id` - رقم المكتب العقاري (Foreign Key → office.id)
- `created_at` - تاريخ الإنشاء
- `updated_by` - آخر مُحدِّث
- `updated_at` - تاريخ آخر تحديث

## 2. الجداول المرتبطة (Child Tables)

### أ) جدول `receipt_voucher_documents`
**العلاقة:** One-to-Many (سند واحد → عدة مستندات)

**الحقول:**
- `id` - معرف المستند
- `receipt_voucher_id` - معرف السند (Foreign Key → receipts_voucher.id)
- `document_name` - اسم المستند
- `document_path` - مسار المستند
- `document_type` - نوع المستند (image, pdf, other)
- `file_size` - حجم الملف بالبايت
- `mime_type` - نوع MIME
- `uploaded_by` - من رفع المستند
- `uploaded_at` - تاريخ الرفع

**تأثير الحذف:** عند حذف سند القبض، يجب حذف جميع المستندات المرتبطة به.

### ب) جدول `receipt_voucher_log`
**العلاقة:** One-to-Many (سند واحد → عدة سجلات)

**الحقول:**
- `id` - معرف السجل
- `receipt_voucher_id` - معرف السند (Foreign Key → receipts_voucher.id)
- `action` - نوع العملية (insert, update, delete)
- `changed_by` - من قام بالتغيير
- `change_details` - تفاصيل التغيير
- `changed_at` - تاريخ التغيير

**تأثير الحذف:** عند حذف سند القبض، يجب حذف جميع السجلات المرتبطة به (أو الاحتفاظ بها كسجل تاريخي).

## 3. الجداول المرتبطة (Parent Tables - References)

### أ) جدول `contracts`
**العلاقة:** Many-to-One (عدة سندات → عقد واحد)
- `receipts_voucher.contract_id` → `contracts.id`

**تأثير الحذف:** عند حذف عقد، قد تحتاج إلى:
- حذف جميع سندات القبض المرتبطة به
- أو تعيين `contract_id` إلى NULL

### ب) جدول `properties`
**العلاقة:** Many-to-One (عدة سندات → عقار واحد)
- `receipts_voucher.property_id` → `properties.id`

**تأثير الحذف:** عند حذف عقار، قد تحتاج إلى:
- حذف جميع سندات القبض المرتبطة به
- أو تعيين `property_id` إلى NULL

### ج) جدول `users`
**العلاقة:** Many-to-One (عدة سندات → مستخدم واحد)
- `receipts_voucher.created_by` → `users.usercode`
- `receipts_voucher.approved_by` → `users.usercode`
- `receipts_voucher.from_party_id` → `users.usercode` (إذا كان from_party_type = 'owner' أو 'tenant')
- `receipts_voucher.to_party_id` → `users.usercode` (إذا كان to_party_type = 'owner' أو 'tenant')

**تأثير الحذف:** عند حذف مستخدم، قد تحتاج إلى:
- تعيين `created_by` و `approved_by` إلى NULL
- أو منع الحذف إذا كان المستخدم مرتبطاً بسندات

### د) جدول `office`
**العلاقة:** Many-to-One (عدة سندات → مكتب واحد)
- `receipts_voucher.office_id` → `office.id`

**تأثير الحذف:** عند حذف مكتب، قد تحتاج إلى:
- حذف جميع سندات القبض المرتبطة به
- أو تعيين `office_id` إلى NULL

## 4. الجداول المرتبطة الأخرى (Indirect Relations)

### أ) جدول `voucher_staging`
**العلاقة:** قد يحتوي على مسودات لسندات القبض
- `voucher_staging.target_table` = 'receipts_voucher'
- `voucher_staging.final_voucher_id` → `receipts_voucher.id`

**تأثير الحذف:** عند حذف سند القبض، قد تحتاج إلى:
- تحديث `voucher_staging.final_voucher_id` إلى NULL
- أو حذف المسودات المرتبطة

## 5. ترتيب الحذف الآمن

عند حذف سند قبض (`receipts_voucher`)، يجب اتباع الترتيب التالي:

### المرحلة 1: حذف الجداول الفرعية (Child Tables)
1. **حذف المستندات:**
   ```sql
   DELETE FROM receipt_voucher_documents WHERE receipt_voucher_id = ?
   ```
   - يجب حذف الملفات الفعلية من النظام أيضاً

2. **حذف السجلات (أو الاحتفاظ بها كسجل تاريخي):**
   ```sql
   DELETE FROM receipt_voucher_log WHERE receipt_voucher_id = ?
   ```
   - **ملاحظة:** قد ترغب في الاحتفاظ بسجلات الحذف كسجل تاريخي

### المرحلة 2: تحديث الجداول المرتبطة (إذا لزم الأمر)
3. **تحديث voucher_staging:**
   ```sql
   UPDATE voucher_staging 
   SET final_voucher_id = NULL 
   WHERE final_voucher_id = ? AND target_table = 'receipts_voucher'
   ```

### المرحلة 3: حذف السند نفسه
4. **حذف سند القبض:**
   ```sql
   DELETE FROM receipts_voucher WHERE id = ?
   ```

## 6. قائمة الجداول المتأثرة بالحذف

### جداول حرجة (يجب حذفها قبل حذف السند):
1. ✅ `receipt_voucher_documents` - مستندات السند
2. ⚠️ `receipt_voucher_log` - سجل السند (قد ترغب في الاحتفاظ به)

### جداول قد تحتاج تحديث:
3. ⚠️ `voucher_staging` - مسودات السندات (تحديث `final_voucher_id`)

### جداول مرجعية (لا يجب حذفها):
4. ❌ `contracts` - العقد المرتبط (يجب التحقق من وجوده)
5. ❌ `properties` - العقار المرتبط (يجب التحقق من وجوده)
6. ❌ `users` - المستخدمون المرتبطون (يجب التحقق من وجودهم)
7. ❌ `office` - المكتب المرتبط (يجب التحقق من وجوده)

## 7. ملاحظات مهمة

1. **التحقق من الملكية:** قبل الحذف، يجب التحقق من أن السند يخص المكتب الحالي:
   ```sql
   SELECT * FROM receipts_voucher 
   WHERE id = ? AND office_id = ?
   ```

2. **حذف الملفات:** عند حذف المستندات، يجب حذف الملفات الفعلية من النظام:
   ```php
   if (file_exists($document_path)) {
       unlink($document_path);
   }
   ```

3. **السجلات التاريخية:** قد ترغب في الاحتفاظ بسجلات الحذف في `receipt_voucher_log` قبل حذف السند.

4. **المعاملات (Transactions):** يجب تنفيذ جميع عمليات الحذف داخل معاملة (transaction) لضمان التكامل:
   ```php
   $connect->beginTransaction();
   try {
       // حذف المستندات
       // حذف السجلات
       // حذف السند
       $connect->commit();
   } catch (Exception $e) {
       $connect->rollBack();
       throw $e;
   }
   ```

5. **الصلاحيات:** يجب التحقق من صلاحيات المستخدم قبل السماح بالحذف.

## 8. مثال على استعلام فحص التبعيات

```sql
-- فحص المستندات المرتبطة
SELECT COUNT(*) as documents_count 
FROM receipt_voucher_documents 
WHERE receipt_voucher_id = ?;

-- فحص السجلات المرتبطة
SELECT COUNT(*) as logs_count 
FROM receipt_voucher_log 
WHERE receipt_voucher_id = ?;

-- فحص المسودات المرتبطة
SELECT COUNT(*) as staging_count 
FROM voucher_staging 
WHERE final_voucher_id = ? AND target_table = 'receipts_voucher';
```

## 9. ملخص الجداول المتأثرة

| الجدول | نوع العلاقة | الإجراء المطلوب | حرج |
|--------|-------------|-----------------|-----|
| `receipt_voucher_documents` | Child | حذف | ✅ نعم |
| `receipt_voucher_log` | Child | حذف/احتفاظ | ⚠️ اختياري |
| `voucher_staging` | Reference | تحديث | ⚠️ اختياري |
| `contracts` | Parent | التحقق | ❌ لا |
| `properties` | Parent | التحقق | ❌ لا |
| `users` | Parent | التحقق | ❌ لا |
| `office` | Parent | التحقق | ❌ لا |

