Update: 2026-08-07 16:25:34

This commit is contained in:
Hamza-Ayed
2026-08-07 16:25:34 +03:00
parent 9338e76894
commit cdd36d4777
16 changed files with 744 additions and 13 deletions
@@ -0,0 +1,116 @@
-- ============================================================
-- التأمين للسائق — بند 3.5 من دراسة الفرص
--
-- ‏ما كان موجوداً قبل هذا: جدول `driver_health_assurance` فيه بوليان
-- ‏`assured` واسم شركة نصّاً، وملف add.php وحيد بلا حارس مصادقة —
-- ‏و get.php و update.php **فارغان تماماً** (صفر بايت). أي أن الفكرة
-- ‏لم "تبدأ وتتوقف" كما تقول الدراسة، بل لم تبدأ.
--
-- ‏قرار المالك: شريك مرخّص (ميتلايف وآخر في مصر)، قسط يومي أو شهري
-- ‏يُخصم من أرباح السائق، وأهلية مشروطة بعدد رحلات وتقييم — التأمين
-- ‏مكافأة استمرار لا خدمة تُمنح لكل من سجّل.
--
-- ‏لا نلمس driver_health_assurance: يبقى كما هو لمن سُجّل فيه سابقاً،
-- ‏والجداول هنا هي المسار الجديد.
-- ============================================================
-- ── ١) شركات التأمين ────────────────────────────────────────
CREATE TABLE IF NOT EXISTS `insurance_providers` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(120) NOT NULL COMMENT 'MetLife وغيرها',
`name_ar` VARCHAR(120) DEFAULT NULL,
`country` VARCHAR(60) NOT NULL DEFAULT 'Egypt',
`contact` VARCHAR(255) DEFAULT NULL,
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_country_active` (`country`, `is_active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── ٢) الخطط ────────────────────────────────────────────────
-- ‏شروط الأهلية تُخزَّن مع الخطة لا في الكود: الشريك سيغيّرها، والسوق
-- ‏المصري يختلف عن الأردني، وتغيير رقم في صف أرخص من نشر إصدار.
CREATE TABLE IF NOT EXISTS `insurance_plans` (
`id` INT NOT NULL AUTO_INCREMENT,
`provider_id` INT NOT NULL,
`code` VARCHAR(60) NOT NULL COMMENT 'معرّف ثابت يُستعمل في الكود',
`name_ar` VARCHAR(160) NOT NULL,
`description_ar` TEXT DEFAULT NULL,
`billing_cycle` ENUM('daily','monthly') NOT NULL DEFAULT 'daily',
`premium` DECIMAL(10,3) NOT NULL COMMENT 'قسط الدورة الواحدة',
`currency` VARCHAR(10) NOT NULL DEFAULT 'EGP',
`coverage_summary` TEXT DEFAULT NULL,
-- ── شروط الأهلية ──
-- ‏قرار المالك: لا تأمين قبل ~٢٠٠ رحلة بتقييم جيد. المنطق سليم —
-- ‏التأمين كلفة متكررة على الشركة، ومنحه لمن قد يختفي بعد أسبوع
-- ‏يحوّله من أداة ولاء إلى نزيف.
`min_completed_rides` INT NOT NULL DEFAULT 200,
`min_rating` DECIMAL(3,2) NOT NULL DEFAULT 4.50,
`min_account_days` INT NOT NULL DEFAULT 30,
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uq_code` (`code`),
KEY `idx_provider_active` (`provider_id`, `is_active`),
CONSTRAINT `fk_plan_provider` FOREIGN KEY (`provider_id`)
REFERENCES `insurance_providers` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── ٣) وثائق السائقين ───────────────────────────────────────
CREATE TABLE IF NOT EXISTS `driver_insurance_policies` (
`id` INT NOT NULL AUTO_INCREMENT,
`driver_id` VARCHAR(100) NOT NULL,
`plan_id` INT NOT NULL,
`policy_number` VARCHAR(120) DEFAULT NULL COMMENT 'رقم الوثيقة من الشريك',
`status` ENUM('active','suspended','cancelled','expired')
NOT NULL DEFAULT 'active',
`started_at` DATE NOT NULL,
`ended_at` DATE DEFAULT NULL,
-- ‏لقطة الأهلية لحظة الاشتراك. بدونها لا يمكن الإجابة لاحقاً على
-- ‏«لماذا قُبل هذا السائق؟» حين تتغيّر شروط الخطة أو ينخفض تقييمه.
`rides_at_signup` INT NOT NULL DEFAULT 0,
`rating_at_signup` DECIMAL(3,2) NOT NULL DEFAULT 0,
-- ‏آخر يوم حُسب عنه قسط. هذا العمود — لا التاريخ الحالي — هو ما
-- ‏يمنع الاحتساب المزدوج لو عمل الكرون مرتين في اليوم نفسه.
`last_charged_on` DATE DEFAULT NULL,
`cancel_reason` VARCHAR(255) DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
-- ‏وثيقة واحدة نشطة لكل سائق. المفتاح الفريد على (driver_id, status)
-- ‏لا يصلح — يمنع وثيقتين ملغيتين. نمنعه في الكود ونكشفه بفهرس.
KEY `idx_driver_status` (`driver_id`, `status`),
KEY `idx_charge_sweep` (`status`, `last_charged_on`),
CONSTRAINT `fk_policy_plan` FOREIGN KEY (`plan_id`)
REFERENCES `insurance_plans` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── ٤) دفتر الأقساط ─────────────────────────────────────────
-- ‏دفتر لا خصم مباشر. رصيد السائق يعيش في payment_server لا هنا،
-- ‏فالكرون يقيّد استحقاقاً والتسوية تقرأه. الفصل مقصود أيضاً لسبب
-- ‏محاسبي: القيد سجلّ دائم قابل للمراجعة، بينما الخصم المباشر يترك
-- ‏رقماً متغيّراً بلا أثر يشرح كيف صار كذلك.
CREATE TABLE IF NOT EXISTS `insurance_premium_ledger` (
`id` INT NOT NULL AUTO_INCREMENT,
`policy_id` INT NOT NULL,
`driver_id` VARCHAR(100) NOT NULL,
`charge_date` DATE NOT NULL COMMENT 'اليوم أو أول الشهر المحتسَب',
`amount` DECIMAL(10,3) NOT NULL,
`currency` VARCHAR(10) NOT NULL DEFAULT 'EGP',
`status` ENUM('pending','settled','waived','failed')
NOT NULL DEFAULT 'pending',
`settled_at` DATETIME DEFAULT NULL,
`note` VARCHAR(255) DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
-- ‏الحارس الحقيقي ضد الاحتساب المزدوج: قسط واحد لكل وثيقة في اليوم
-- ‏الواحد مهما تكرّر تشغيل الكرون أو تزامنت نسختان منه.
UNIQUE KEY `uq_policy_date` (`policy_id`, `charge_date`),
KEY `idx_driver_status` (`driver_id`, `status`),
CONSTRAINT `fk_ledger_policy` FOREIGN KEY (`policy_id`)
REFERENCES `driver_insurance_policies` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;