-- ============================================================= -- schema_food.sql — قاعدة بيانات وحدة طلبات الطعام (siro_food) -- عزل كامل عن main/ride/transit — ممنوع أي JOIN خارجي -- الربط بالنظام الرئيسي عبر passenger_id / courier_id (main driver id) فقط -- ============================================================= SET FOREIGN_KEY_CHECKS = 0; SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; -- ----------------------------------------------------------------- -- 1. food_merchants — المطاعم/المتاجر -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_merchants` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `name_ar` VARCHAR(150) NOT NULL, `name_en` VARCHAR(150) DEFAULT NULL, `logo_url` VARCHAR(500) DEFAULT NULL, `cover_url` VARCHAR(500) DEFAULT NULL, `description_ar` VARCHAR(500) DEFAULT NULL, `city` VARCHAR(80) NOT NULL, `address` VARCHAR(300) DEFAULT NULL, `latitude` DECIMAL(10,7) NOT NULL, `longitude` DECIMAL(10,7) NOT NULL, `category` VARCHAR(60) DEFAULT NULL COMMENT 'مطبخ عربي، بيتزا، حلويات...', `commission_percent` DECIMAL(5,2) NOT NULL DEFAULT 15.00, `min_order_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'أصغر وحدة نقدية', `avg_prep_minutes` SMALLINT UNSIGNED NOT NULL DEFAULT 20, `rating_avg` DECIMAL(3,2) NOT NULL DEFAULT 0.00, `rating_count` INT UNSIGNED NOT NULL DEFAULT 0, `status` ENUM('pending_approval','active','paused','suspended','rejected') NOT NULL DEFAULT 'pending_approval', `is_open_override` TINYINT(1) DEFAULT NULL COMMENT 'NULL=يتبع working_hours، 0/1=إغلاق/فتح يدوي فوري', `working_hours` JSON DEFAULT NULL COMMENT '{"sun":[["09:00","23:00"]], ...}', `approved_by` INT UNSIGNED DEFAULT NULL COMMENT 'admin id من النظام الرئيسي', `approved_at` TIMESTAMP 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`), KEY `idx_city_status` (`city`, `status`), KEY `idx_location` (`latitude`, `longitude`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 2. food_merchant_users — حسابات دخول أصحاب المطاعم (دور merchant، هوية منفصلة عن الراكب) -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_merchant_users` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `merchant_id` INT UNSIGNED NOT NULL, `name` VARCHAR(120) NOT NULL, `phone` VARCHAR(25) NOT NULL COMMENT 'مشفّر بنفس EncryptionHelper', `role` ENUM('owner','staff') NOT NULL DEFAULT 'owner', `password_hash` VARCHAR(255) NOT NULL, `is_active` TINYINT(1) NOT NULL DEFAULT 1, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uq_phone` (`phone`), KEY `idx_merchant` (`merchant_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 3. food_menu_categories — أقسام قائمة المطعم -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_menu_categories` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `merchant_id` INT UNSIGNED NOT NULL, `name_ar` VARCHAR(100) NOT NULL, `name_en` VARCHAR(100) DEFAULT NULL, `sort_order` SMALLINT NOT NULL DEFAULT 0, `is_active` TINYINT(1) NOT NULL DEFAULT 1, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_merchant_sort` (`merchant_id`, `sort_order`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 4. food_menu_items — أصناف القائمة -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_menu_items` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `merchant_id` INT UNSIGNED NOT NULL, `category_id` INT UNSIGNED NOT NULL, `name_ar` VARCHAR(150) NOT NULL, `name_en` VARCHAR(150) DEFAULT NULL, `description_ar` VARCHAR(500) DEFAULT NULL, `image_url` VARCHAR(500) DEFAULT NULL, `price` BIGINT UNSIGNED NOT NULL COMMENT 'أصغر وحدة نقدية', `is_available` TINYINT(1) NOT NULL DEFAULT 1, `prep_minutes` SMALLINT UNSIGNED DEFAULT NULL COMMENT 'NULL = يستخدم avg_prep_minutes للمطعم', `sort_order` SMALLINT NOT NULL DEFAULT 0, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_merchant_available` (`merchant_id`, `is_available`), KEY `idx_category` (`category_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 5. food_item_options — مجموعات خيارات الصنف (حجم، إضافات...) -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_item_options` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `item_id` INT UNSIGNED NOT NULL, `group_name_ar` VARCHAR(100) NOT NULL COMMENT 'مثال: الحجم، الإضافات', `is_required` TINYINT(1) NOT NULL DEFAULT 0, `max_select` TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1=اختيار واحد، أكثر=متعدد', `choices` JSON NOT NULL COMMENT '[{"id":"lg","label_ar":"كبير","price":500}]', `sort_order` SMALLINT NOT NULL DEFAULT 0, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_item` (`item_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 6. food_orders — الطلب -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_orders` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `client_order_uuid` CHAR(36) NOT NULL COMMENT 'idempotency — يمنع الضغط المزدوج من إنشاء طلبين', `passenger_id` VARCHAR(100) NOT NULL COMMENT 'مرجع منطقي فقط — لا FK خارجي', `merchant_id` INT UNSIGNED NOT NULL, `courier_id` VARCHAR(100) DEFAULT NULL COMMENT 'main driver id بعد الإسناد', `status` ENUM( 'pending','merchant_accepted','preparing','ready', 'courier_assigned','picked_up','delivered', 'rejected','cancelled_by_customer','cancelled_by_merchant','cancelled_system' ) NOT NULL DEFAULT 'pending', `items_total` BIGINT UNSIGNED NOT NULL COMMENT 'مجموع أصناف الطلب — أصغر وحدة نقدية', `delivery_fee` BIGINT UNSIGNED NOT NULL DEFAULT 0, `service_fee` BIGINT UNSIGNED NOT NULL DEFAULT 0, `discount` BIGINT UNSIGNED NOT NULL DEFAULT 0, `grand_total` BIGINT UNSIGNED NOT NULL COMMENT 'items_total+delivery_fee+service_fee-discount', `commission_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'نصيب المنصة من items_total', `payment_method` ENUM('wallet','cash') NOT NULL DEFAULT 'wallet', `payment_hold_ref` VARCHAR(100) DEFAULT NULL COMMENT 'مرجع حجز المحفظة في payment_server/v2', `delivery_address` VARCHAR(300) NOT NULL, `delivery_lat` DECIMAL(10,7) NOT NULL, `delivery_lng` DECIMAL(10,7) NOT NULL, `customer_note` VARCHAR(300) DEFAULT NULL, `promo_code` VARCHAR(40) DEFAULT NULL, `rating` TINYINT UNSIGNED DEFAULT NULL, `rating_comment` VARCHAR(300) DEFAULT NULL, `merchant_accepted_at` TIMESTAMP DEFAULT NULL, `ready_at` TIMESTAMP DEFAULT NULL, `courier_assigned_at` TIMESTAMP DEFAULT NULL, `picked_up_at` TIMESTAMP DEFAULT NULL, `delivered_at` TIMESTAMP DEFAULT NULL, `cancelled_at` TIMESTAMP DEFAULT NULL, `cancel_reason` VARCHAR(300) 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`), UNIQUE KEY `uq_client_uuid` (`client_order_uuid`), KEY `idx_passenger_created` (`passenger_id`, `created_at`), KEY `idx_merchant_status` (`merchant_id`, `status`), KEY `idx_courier_status` (`courier_id`, `status`), KEY `idx_status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 7. food_order_items — أصناف الطلب بسعر مجمّد وقت الطلب -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_order_items` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `order_id` INT UNSIGNED NOT NULL, `item_id` INT UNSIGNED NOT NULL COMMENT 'مرجع فقط — لا JOIN للسعر', `name_ar_snapshot` VARCHAR(150) NOT NULL, `unit_price` BIGINT UNSIGNED NOT NULL COMMENT 'سعر الوحدة وقت الطلب — مجمّد', `quantity` SMALLINT UNSIGNED NOT NULL DEFAULT 1, `option_price_json` JSON DEFAULT NULL COMMENT 'الخيارات المختارة وأسعارها وقت الطلب', `line_total` BIGINT UNSIGNED NOT NULL COMMENT '(unit_price+مجموع الخيارات)×quantity', `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 8. food_order_status_log — كل انتقال حالة — مصدر الحقيقة للنزاعات -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_order_status_log` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `order_id` INT UNSIGNED NOT NULL, `from_status` VARCHAR(30) DEFAULT NULL, `to_status` VARCHAR(30) NOT NULL, `actor_type` ENUM('customer','merchant','courier','admin','system') NOT NULL, `actor_id` VARCHAR(100) DEFAULT NULL, `note` VARCHAR(300) DEFAULT NULL, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 9. food_order_payments — مرجع معاملة المحفظة/الدفع + التسوية -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_order_payments` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `order_id` INT UNSIGNED NOT NULL, `type` ENUM('hold','capture','release','cash_settlement','courier_payout') NOT NULL, `amount` BIGINT UNSIGNED NOT NULL, `wallet_ref` VARCHAR(100) DEFAULT NULL COMMENT 'مرجع من payment_server/v2', `status` ENUM('pending','success','failed') NOT NULL DEFAULT 'pending', `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_order` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 10. food_courier_assignments — محاولات إسناد الطلب لسائق -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_courier_assignments` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `order_id` INT UNSIGNED NOT NULL, `courier_id` VARCHAR(100) NOT NULL COMMENT 'main driver id', `status` ENUM('offered','accepted','rejected','timed_out') NOT NULL DEFAULT 'offered', `offered_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `responded_at` TIMESTAMP DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_order` (`order_id`), KEY `idx_courier` (`courier_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 11. food_merchant_payouts — مستحقات المطاعم ودورات التسوية -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_merchant_payouts` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `merchant_id` INT UNSIGNED NOT NULL, `period_start` DATE NOT NULL, `period_end` DATE NOT NULL, `orders_count` INT UNSIGNED NOT NULL DEFAULT 0, `gross_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0, `commission_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0, `net_payout` BIGINT UNSIGNED NOT NULL DEFAULT 0, `status` ENUM('pending','paid') NOT NULL DEFAULT 'pending', `paid_at` TIMESTAMP DEFAULT NULL, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_merchant_period` (`merchant_id`, `period_start`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 12. food_promo_codes — أكواد خصم خاصة بالطعام (منفصلة عن أكواد الرحلات) -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_promo_codes` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `code` VARCHAR(40) NOT NULL, `discount_type` ENUM('percent','fixed') NOT NULL DEFAULT 'fixed', `discount_value` INT UNSIGNED NOT NULL, `max_discount` BIGINT UNSIGNED DEFAULT NULL, `min_order_amount` BIGINT UNSIGNED NOT NULL DEFAULT 0, `usage_limit` INT UNSIGNED DEFAULT NULL, `usage_count` INT UNSIGNED NOT NULL DEFAULT 0, `valid_from` TIMESTAMP DEFAULT NULL, `valid_until` TIMESTAMP DEFAULT NULL, `is_active` TINYINT(1) NOT NULL DEFAULT 1, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uq_code` (`code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- ----------------------------------------------------------------- -- 13. food_merchant_sessions — جلسات دخول لوحة المطعم (هاتف+كلمة مرور، -- session token مستقل عن JWT — نفس نمط transit_sessions، لأن لوحة -- المطعم ويب متجاوب لا يملك device fingerprint كتطبيق الجوال) -- ----------------------------------------------------------------- CREATE TABLE IF NOT EXISTS `food_merchant_sessions` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `merchant_user_id` INT UNSIGNED NOT NULL, `merchant_id` INT UNSIGNED NOT NULL, `token_hash` VARCHAR(64) NOT NULL COMMENT 'sha256 للـ session token', `ip` VARCHAR(45) DEFAULT NULL, `user_agent` VARCHAR(300) DEFAULT NULL, `expires_at` TIMESTAMP NOT NULL, `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uq_token` (`token_hash`), KEY `idx_merchant_user` (`merchant_user_id`), KEY `idx_expires` (`expires_at`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; SET FOREIGN_KEY_CHECKS = 1; -- ----------------------------------------------------------------- -- ملاحظات Redis (مفاتيح تُكتب من PHP — ليست في SQL): -- food:order:{id}:lock → SET NX EX 20 عند قبول سائق (يمنع سباق القبول) -- geo:couriers:available → مجموعة جغرافية للسائقين can_deliver=1 المتفرغين -- food:merchant:{id}:cache → كاش بيانات مطعم للقراءة السريعة (اختياري لاحقاً) -- Redis channels للسوكيت: food:order:{id} / food:merchant:{id} / food:courier:{id} -- -----------------------------------------------------------------