Update: 2026-08-07 05:35:52

This commit is contained in:
Hamza-Ayed
2026-08-07 05:35:52 +03:00
parent 0b8b687ce1
commit 7a932580a3
3 changed files with 299 additions and 3 deletions
@@ -0,0 +1,59 @@
-- 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`;