chore: add standard international tariff seeder script
This commit is contained in:
@@ -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.');
|
||||
Reference in New Issue
Block a user