Update: 2026-08-02 17:52:28

This commit is contained in:
Hamza-Ayed
2026-08-02 17:52:28 +03:00
parent b78a6797d5
commit 4620e84d34
96 changed files with 6250 additions and 476 deletions
+289
View File
@@ -0,0 +1,289 @@
-- =============================================================
-- 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}
-- -----------------------------------------------------------------