117 lines
7.4 KiB
SQL
117 lines
7.4 KiB
SQL
-- ============================================================
|
||
-- التأمين للسائق — بند 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;
|