feat: implement rewards module with referral/coupon systems, update tariff seeding, and add trip distance service for improved billing accuracy.
This commit is contained in:
@@ -44,6 +44,45 @@ export class DriverCreditService {
|
||||
return this.apply(tenantId, driverId, amount, 'promo_bonus', { ref });
|
||||
}
|
||||
|
||||
/**
|
||||
* مكافأة إحالة للسائق (المجموعة L) — **مرة واحدة لكل إحالة**.
|
||||
*
|
||||
* `ref` هو معرّف الإحالة، ويحرسه فهرس فريد جزئي على القاعدة
|
||||
* (`IDX_tripz_credit_txns_referral_once`) بنفس منطق J6: الماسح والمسار
|
||||
* الحدثي قد يصرفان معاً، والقيد وحده هو ما يمنع الصرف مرتين.
|
||||
*
|
||||
* يعيد `false` إذا كانت مصروفة سلفاً — فيعرف المنادي ألّا يعلّمها مدفوعة
|
||||
* بناءً على نجاحٍ لم يحدث.
|
||||
*/
|
||||
async grantReferralBonus(
|
||||
tenantId: string,
|
||||
driverId: string,
|
||||
amount: number,
|
||||
referralId: string,
|
||||
currency = 'JOD',
|
||||
): Promise<boolean> {
|
||||
if (!(amount > 0)) return false;
|
||||
|
||||
// حارسان مثل J6: فحص تطبيقي للحالة الشائعة (الماسح يعيد المحاولة)،
|
||||
// وفهرس فريد جزئي على القاعدة للسباق الحقيقي. الفحص وحده يسقط تحت
|
||||
// التزامن، والفهرس وحده يجعل الحالة الشائعة استثناءً — فكلاهما.
|
||||
const already = await this.txns.findOne({
|
||||
where: { tenant_id: tenantId, type: 'referral_bonus', ref: referralId },
|
||||
});
|
||||
if (already) return false;
|
||||
|
||||
try {
|
||||
await this.apply(tenantId, driverId, amount, 'referral_bonus', { ref: referralId }, currency);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
if (e?.code === '23505' || e?.driverError?.code === '23505') {
|
||||
this.logger.debug(`referral bonus already granted for ${referralId}`);
|
||||
return false;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* خصم عمولة رحلة (docs/18 §5.2).
|
||||
* **لا يفشل أبداً** — ولو صار الرصيد سالباً. الرحلة تمّت فالعمولة استُحقّت؛
|
||||
|
||||
@@ -15,6 +15,7 @@ export type CreditTxnType =
|
||||
| 'topup' // شحن مدفوع — إيراد
|
||||
| 'signup_bonus' // مكافأة تسجيل — تكلفة تجنيد
|
||||
| 'promo_bonus' // حافز باقة («اشحن 50 خذ 55») — تكلفة تسويق
|
||||
| 'referral_bonus'// مكافأة إحالة — تكلفة تجنيد، منفصلة عن حافز الباقة
|
||||
| 'commission' // خصم عمولة رحلة
|
||||
| 'adjustment'; // تسوية يدوية من الأدمن
|
||||
|
||||
|
||||
Reference in New Issue
Block a user