# إصلاح مشكلة Foreign Key Constraint عند حذف العقار

## المشكلة

```
SQLSTATE[23000]: Integrity constraint violation: 1451 
Cannot delete or update a parent row: a foreign key constraint fails 
(`faradjwb_farsak`.`contracts`, CONSTRAINT `contracts_ibfk_1` 
FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`))
```

### السبب:
- جدول `contracts` له Foreign Key على `property_id` بدون `ON DELETE CASCADE`
- لا يمكن حذف العقار إذا كان لديه عقود مرتبطة
- قاعدة البيانات تمنع الحذف لحماية سلامة البيانات

## الحلول المطبقة

### 1. إصلاح `delete_property.php`

#### التحقق من العقود قبل الحذف:
```php
// التحقق من وجود عقود مرتبطة
$contracts_check = $connect->prepare("SELECT COUNT(*) as count FROM contracts WHERE property_id = ?");
$contracts_check->execute([$property_id]);
$contracts_result = $contracts_check->fetch(PDO::FETCH_ASSOC);
$contracts_count = (int)$contracts_result['count'];

if ($contracts_count > 0) {
    // توجيه المستخدم لاستخدام الملف الآمن
    header('Location: delete_property_safe.php?id=' . $property_id . '&mode=check&warning=has_contracts');
    exit();
}
```

#### استخدام المعاملات (Transactions):
```php
$connect->beginTransaction();
try {
    // حذف الجداول المرتبطة
    // ...
    $connect->commit();
} catch (Exception $e) {
    $connect->rollBack();
    throw $e;
}
```

#### معالجة أخطاء Foreign Key:
```php
if ($error_code == 23000 || strpos($error_message, 'foreign key constraint') !== false) {
    // توجيه المستخدم لاستخدام الملف الآمن
    header('Location: delete_property_safe.php?id=' . $property_id . '&mode=check&error=has_related_data');
    exit();
}
```

### 2. إصلاح `delete_property_safe.php`

#### حذف الجداول المرتبطة بالعقود أولاً:
```php
// 1. حذف الجداول المرتبطة بالعقود
$contract_related_tables = [
    'contract_installments' => 'contract_id',
    'contract_docment' => 'contract_id',
    'contract_history' => 'original_contract_id',
    'contract_notifications' => 'contract_id',
    'contract_owner_requests' => 'contract_id',
    'contract_requests' => 'contract_id',
    'contract_settings' => 'contract_id',
    'contract_analytics' => 'contract_id',
    'contractmovements' => 'contract_id'
];

// جلب جميع عقود العقار
$contracts_stmt = $connect->prepare("SELECT id FROM contracts WHERE property_id = ?");
$contracts_stmt->execute([$property_id]);
$contracts = $contracts_stmt->fetchAll(PDO::FETCH_COLUMN);

// حذف الجداول المرتبطة بكل عقد
foreach ($contracts as $contract_id) {
    foreach ($contract_related_tables as $table => $field) {
        $delete_stmt = $connect->prepare("DELETE FROM `{$table}` WHERE `{$field}` = ?");
        $delete_stmt->execute([$contract_id]);
    }
}

// 2. حذف العقود نفسها
$delete_contracts_stmt = $connect->prepare("DELETE FROM contracts WHERE property_id = ?");
$delete_contracts_stmt->execute([$property_id]);

// 3. حذف باقي الجداول الحرجة
// ...
```

#### تحذير خاص للعقود:
```php
<?php if (isset($related_data['contracts'])): ?>
<div style="background: #fff3cd; padding: 15px; margin-top: 15px; border-radius: 5px; border: 2px solid #ffc107;">
    <h4 style="color: #856404; margin-bottom: 10px;">🚨 تحذير خاص: العقود المرتبطة</h4>
    <p style="color: #856404; margin: 0;">
        يوجد <strong><?= $related_data['contracts']['count'] ?></strong> عقد مرتبط بهذا العقار.
        <br>حذف العقار سيحذف جميع العقود المرتبطة به بشكل دائم!
        <br><strong>هذا الإجراء لا يمكن التراجع عنه!</strong>
    </p>
</div>
<?php endif; ?>
```

## ترتيب الحذف الصحيح

### المستوى 1: الجداول المرتبطة بالعقود
1. `contract_installments` - دفعات العقود
2. `contract_docment` - مستندات العقود
3. `contract_history` - تاريخ العقود
4. `contract_notifications` - إشعارات العقود
5. `contract_owner_requests` - طلبات المالك
6. `contract_requests` - طلبات العقود
7. `contract_settings` - إعدادات العقود
8. `contract_analytics` - تحليلات العقود
9. `contractmovements` - حركات العقود

### المستوى 2: العقود نفسها
10. `contracts` - العقود

### المستوى 3: الجداول الأخرى المرتبطة بالعقار
11. `maintenance_requests` - طلبات الصيانة
12. `maintenance_tenders` - مناقصات الصيانة
13. `bill_of_exchange` - سندات الصرف والقبض
14. `payment_voucher` - سندات الدفع
15. `receipts_voucher` - سندات القبض
16. وغيرها...

### المستوى 4: العقار نفسه
17. `properties` - العقار

## الجداول التي لها Foreign Key على property_id

### مع ON DELETE CASCADE (يتم حذفها تلقائياً):
- `property_media`
- `property_analytics`
- `property_predictive_analytics`
- `advanced_property_analytics`
- `favorites_properties`
- `ad_licenses`
- `contract_analytics` (property_id)
- `tenant_analytics`
- `tenant_behavior_analytics`
- `tenant_property_inspection`

### مع ON DELETE SET NULL (يتم تعيينها إلى NULL):
- `brokerage_contracts`
- `property_request_offers`
- `office_rating`
- `system_alerts`

### بدون ON DELETE (يجب حذفها يدوياً):
- `contracts` ⚠️ **هذا هو السبب الرئيسي للمشكلة**
- `maintenance_requests`
- `maintenance_tenders`
- `cleaning_requests`
- `bill_of_exchange`
- `payment_voucher`
- `receipts_voucher`
- `evaluations`
- `tenant_complaints`
- `tenant_reports`

## التوصيات

### للمستخدم:
1. ✅ استخدم `delete_property_safe.php` دائماً للحذف
2. ✅ راجع التقرير المفصل قبل الحذف
3. ✅ تأكد من عدم وجود عقود نشطة مهمة
4. ✅ احتفظ بنسخة احتياطية قبل الحذف

### للمطور:
1. ✅ استخدم المعاملات (Transactions) دائماً
2. ✅ احذف الجداول المرتبطة بالعقود أولاً
3. ✅ تحقق من وجود بيانات مرتبطة قبل الحذف
4. ✅ سجل الأخطاء بشكل مفصل

## الاختبار

للتحقق من الإصلاح:
1. جرب حذف عقار بدون عقود - يجب أن يعمل
2. جرب حذف عقار مع عقود - يجب أن يوجهك لـ `delete_property_safe.php`
3. راجع `error.log` للتأكد من عدم وجود أخطاء جديدة

---

**تاريخ الإصلاح:** 2025-11-19

