60 lines
3.7 KiB
SQL
60 lines
3.7 KiB
SQL
-- 2026_08_07_courier_settlement.sql — دورة تسوية أرباح سائقي التوصيل
|
||
--
|
||
-- قرار المالك: الأجرة **تتراكم وتُصرف دورياً مع مقاصّة دَين النقد**، لا
|
||
-- تُصرف فوراً عند كل تسليم.
|
||
--
|
||
-- لماذا المقاصّة ضرورية: في الطلب النقدي يحصّل السائق grand_total كاملاً
|
||
-- من الزبون، فيصير مديناً للمنصة بحصة المطعم والعمولة. صرف أجرته منفصلاً
|
||
-- عن هذا الدَين يعني أن تدفع له بينما هو يحمل مالك.
|
||
--
|
||
-- الصافي = مجموع أجور التوصيل − مجموع ديون النقد
|
||
--
|
||
-- موجب → يُصرف لمحفظة السائق
|
||
-- سالب → يبقى ديناً يُرحَّل للدورة التالية (لا نخصم من محفظته آلياً:
|
||
-- قد تكون فارغة، والخصم القسري يفاجئه ويوقفه عن العمل)
|
||
--
|
||
-- ⚠️ يُنفَّذ على قاعدة الطعام (siro_food) لا primary.
|
||
--
|
||
-- sirodb siro_food < backend/food/migrations/2026_08_07_courier_settlement.sql
|
||
|
||
CREATE TABLE IF NOT EXISTS `food_courier_settlements` (
|
||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||
`courier_id` VARCHAR(100) NOT NULL COMMENT 'معرّف السائق (نفس driver.id)',
|
||
`period_start` DATETIME NOT NULL,
|
||
`period_end` DATETIME NOT NULL,
|
||
|
||
`orders_count` INT UNSIGNED NOT NULL DEFAULT 0,
|
||
`payout_total` BIGINT NOT NULL DEFAULT 0 COMMENT 'مجموع أجور التوصيل المستحقة (أصغر وحدة)',
|
||
`cash_debt_total` BIGINT NOT NULL DEFAULT 0 COMMENT 'مجموع ما حصّله نقداً ويخص المنصة',
|
||
`carried_over` BIGINT NOT NULL DEFAULT 0 COMMENT 'دَين مُرحَّل من دورة سابقة (سالب الصافي)',
|
||
`net_amount` BIGINT NOT NULL DEFAULT 0 COMMENT 'الصافي = payout − debt − carried_over',
|
||
|
||
`currency` VARCHAR(5) NOT NULL DEFAULT 'JOD',
|
||
|
||
`status` VARCHAR(20) NOT NULL DEFAULT 'draft'
|
||
COMMENT 'paid = صُرفت | failed = تعذّر التحويل | carried = سالبة تُرحَّل للدورة القادمة | settled_forward = رُحّلت واستُهلكت في دورة لاحقة | draft',
|
||
`transfer_code` SMALLINT NULL DEFAULT NULL COMMENT 'رمز HTTP من خادم المحفظة',
|
||
`executed_by` VARCHAR(100) NULL DEFAULT NULL,
|
||
`executed_at` DATETIME NULL DEFAULT NULL,
|
||
`note` VARCHAR(500) NULL DEFAULT NULL,
|
||
|
||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
PRIMARY KEY (`id`),
|
||
-- يمنع توليد دورتين لنفس السائق ونفس الفترة — الازدواج هنا يعني صرفاً مضاعفاً
|
||
UNIQUE KEY `uniq_courier_period` (`courier_id`, `period_start`, `period_end`),
|
||
KEY `idx_status` (`status`, `created_at`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||
COMMENT='دورات تسوية سائقي التوصيل — أجور مقاصّةً مع ديون النقد';
|
||
|
||
-- ربط قيود الدفع بدورة التسوية التي ضمّتها: بدونه لا نعرف ما سُوّي وما لم
|
||
-- يُسوَّ، فتُحتسب نفس الأجرة مرتين في دورتين متتاليتين.
|
||
ALTER TABLE `food_order_payments`
|
||
ADD COLUMN `settlement_id` INT UNSIGNED NULL DEFAULT NULL
|
||
COMMENT 'دورة التسوية التي ضمّت هذا القيد. NULL = لم يُسوَّ بعد',
|
||
ADD KEY `idx_settlement` (`settlement_id`, `type`, `status`);
|
||
|
||
-- للتراجع:
|
||
-- DROP TABLE `food_courier_settlements`;
|
||
-- ALTER TABLE `food_order_payments` DROP COLUMN `settlement_id`, DROP KEY `idx_settlement`;
|