From 22d18f32fed79da9ac92b99471ad26e309ecfbb2 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Sat, 18 Jul 2026 23:31:55 +0300 Subject: [PATCH] chore: add standard international tariff seeder script --- backend/e2e-tester/seed-tariffs.js | 165 +++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 backend/e2e-tester/seed-tariffs.js diff --git a/backend/e2e-tester/seed-tariffs.js b/backend/e2e-tester/seed-tariffs.js new file mode 100644 index 0000000..67ba040 --- /dev/null +++ b/backend/e2e-tester/seed-tariffs.js @@ -0,0 +1,165 @@ +/** + * Tripz - Global Tariffs Seed Script + * + * This script seeds the `tripz_tariffs` table with internationally recognized + * service classes (e.g. Economy, Comfort, XL/Van, Saver) and standard time windows. + * + * It maps legacy flat pricing models into the modern Tripz JSON-based TariffDefinition. + */ + +const fs = require('fs'); + +// Standard, internationally recognized service classes +const ServiceClasses = { + ECONOMY: 'economy', // Standard, affordable everyday rides (formerly 'speed') + COMFORT: 'comfort', // Newer, more spacious vehicles + LADY: 'lady', // Female drivers for female riders + ELECTRIC: 'electric', // EV/Green vehicles + VAN: 'van', // High capacity (XL) vehicles + DELIVERY: 'delivery', // Package / courier delivery + VIP: 'vip', // Premium / Luxury rides (formerly 'mishwarVip') + FIXED: 'fixed', // Fixed route/fare rides + SAVER: 'saver' // Discounted / shared rides (formerly 'awfar') +}; + +// Global pricing configurations per country +const countryConfigs = [ + { + country: 'jordan', + currency: 'JOD', + commissionPercent: 14.0, + baseFare: 0.0, + // Note: In the legacy system, Jordan's per-minute and per-km values were structurally swapped. + // We have normalized them here to follow standard logic (perKm is higher than perMin). + serviceRates: { + [ServiceClasses.ECONOMY]: { perKm: 0.184, perMin: 0.043 }, + [ServiceClasses.COMFORT]: { perKm: 0.212, perMin: 0.056 }, + [ServiceClasses.LADY]: { perKm: 0.184, perMin: 0.047 }, + [ServiceClasses.ELECTRIC]: { perKm: 0.184, perMin: 0.052 }, + [ServiceClasses.VAN]: { perKm: 0.250, perMin: 0.065 }, // Adjusted perKm for Van proportionality + [ServiceClasses.DELIVERY]: { perKm: 0.150, perMin: 0.039 }, + [ServiceClasses.VIP]: { perKm: 0.300, perMin: 0.060 }, + [ServiceClasses.FIXED]: { perKm: 0.184, perMin: 0.043 }, + [ServiceClasses.SAVER]: { perKm: 0.150, perMin: 0.037 }, + }, + timeMultipliers: { + normal: 1.0, // 08:00 - 16:00 + peak: 1.15, // 16:00 - 22:00 (15% surge) + late: 1.0 // 22:00 - 08:00 + } + }, + { + country: 'egypt', + currency: 'EGP', + commissionPercent: 12.0, + baseFare: 0.0, + serviceRates: { + [ServiceClasses.ECONOMY]: { perKm: 3.5, perMin: 0.8 }, + [ServiceClasses.COMFORT]: { perKm: 5.0, perMin: 0.9 }, + [ServiceClasses.LADY]: { perKm: 9.0, perMin: 1.0 }, + [ServiceClasses.ELECTRIC]: { perKm: 0.8, perMin: 0.5 }, + [ServiceClasses.VAN]: { perKm: 1.4, perMin: 1.0 }, + [ServiceClasses.DELIVERY]: { perKm: 1.3, perMin: 0.8 }, + [ServiceClasses.VIP]: { perKm: 5.5, perMin: 1.2 }, + [ServiceClasses.FIXED]: { perKm: 5.5, perMin: 1.0 }, + [ServiceClasses.SAVER]: { perKm: 3.0, perMin: 0.7 }, + }, + timeMultipliers: { + normal: 1.0, + peak: 1.75, // 1.4 EGP peak / 0.8 EGP normal = 1.75x + late: 1.87 // 1.5 EGP late / 0.8 EGP normal = 1.87x + } + }, + { + country: 'syria', + currency: 'SYP', + commissionPercent: 11.0, + baseFare: 0.0, + serviceRates: { + [ServiceClasses.ECONOMY]: { perKm: 40, perMin: 9 }, + [ServiceClasses.COMFORT]: { perKm: 44, perMin: 10 }, + [ServiceClasses.LADY]: { perKm: 63, perMin: 12 }, + [ServiceClasses.ELECTRIC]: { perKm: 9, perMin: 5 }, + [ServiceClasses.VAN]: { perKm: 10, perMin: 8 }, + [ServiceClasses.DELIVERY]: { perKm: 20, perMin: 9 }, + [ServiceClasses.VIP]: { perKm: 26, perMin: 12 }, + [ServiceClasses.FIXED]: { perKm: 26, perMin: 10 }, + [ServiceClasses.SAVER]: { perKm: 36, perMin: 8 }, + }, + timeMultipliers: { + normal: 1.0, + peak: 1.11, // 10 peak / 9 normal = 1.11x + late: 1.22 // 11 late / 9 normal = 1.22x + } + } +]; + +function generateSql() { + let sql = `-- Tripz Standard Tariffs Seed Script\n`; + sql += `-- Generated with international ride-hailing naming conventions.\n\n`; + + for (const config of countryConfigs) { + const city = config.country; + + for (const [serviceClass, rates] of Object.entries(config.serviceRates)) { + + const definition = { + currency: config.currency, + mode: 'time_and_distance', + booking_fee: config.baseFare, + min_fare: config.baseFare > 0 ? config.baseFare : (rates.perKm * 2), // Min fare = 2 KMs default + windows: [ + { + name: 'normal', + from: '08:00', + to: '16:00', + flag: config.baseFare, + per_km: rates.perKm, + per_min: rates.perMin, + per_min_waiting: Number((rates.perMin * 1.5).toFixed(3)) + }, + { + name: 'peak', + from: '16:00', + to: '22:00', + flag: config.baseFare, + per_km: Number((rates.perKm * config.timeMultipliers.peak).toFixed(3)), + per_min: Number((rates.perMin * config.timeMultipliers.peak).toFixed(3)), + per_min_waiting: Number((rates.perMin * config.timeMultipliers.peak * 1.5).toFixed(3)) + }, + { + name: 'late', + from: '22:00', + to: '08:00', + flag: config.baseFare, + per_km: Number((rates.perKm * config.timeMultipliers.late).toFixed(3)), + per_min: Number((rates.perMin * config.timeMultipliers.late).toFixed(3)), + per_min_waiting: Number((rates.perMin * config.timeMultipliers.late * 1.5).toFixed(3)) + } + ], + commission: { + percent: config.commissionPercent + } + }; + + const defJson = JSON.stringify(definition).replace(/'/g, "''"); // Escape single quotes for SQL + + sql += `INSERT INTO tripz_tariffs (id, tenant_id, city, service_class, version, active, definition)\n`; + sql += `VALUES (\n`; + sql += ` gen_random_uuid(),\n`; + sql += ` (SELECT id FROM tripz_tenants WHERE slug = 'siro' LIMIT 1),\n`; + sql += ` '${city}',\n`; + sql += ` '${serviceClass}',\n`; + sql += ` 1,\n`; + sql += ` true,\n`; + sql += ` '${defJson}'::jsonb\n`; + sql += `);\n\n`; + } + } + + return sql; +} + +const sqlOutput = generateSql(); +fs.writeFileSync(__dirname + '/seed-tariffs.sql', sqlOutput); +console.log('✅ Generated seed-tariffs.sql successfully with international naming standards.');