freightdesk/webapp/seed.js
FreightDesk 1a4eaaa040 Initial commit: FreightDesk v1.0
- Express + EJS server-rendered app
- Supabase PostgreSQL database
- Auth: username/password with bcrypt
- Dashboard with business stats
- Load CRUD with filters
- WhatsApp message parser
- Payment tracking
- Shipper & vehicle management
- Reports (monthly, top shippers, routes)
- Government-app aesthetic (tricolor theme)
- Dark mode support
- Docker + Coolify deployment ready
- Seed data from existing business ledger (88 loads, 41 shippers, 70 vehicles)
2026-06-07 18:57:24 +00:00

122 lines
4.2 KiB
JavaScript

#!/usr/bin/env node
/**
* FreightDesk Seed Script
* Reads supabase/seed_data.json and inserts into Supabase
* Also runs the schema migrations
*/
require('dotenv').config();
const { createClient } = require('@supabase/supabase-js');
const fs = require('fs');
const path = require('path');
const supabaseUrl = process.env.SUPABASE_URL;
const supabaseKey = process.env.SUPABASE_SERVICE_KEY || process.env.SUPABASE_KEY;
if (!supabaseUrl || !supabaseKey) {
console.error('Missing SUPABASE_URL or SUPABASE_KEY in .env');
process.exit(1);
}
const supabase = createClient(supabaseUrl, supabaseKey);
async function runMigrations() {
const migrationsDir = path.join(__dirname, '..', 'supabase', 'migrations');
const files = fs.readdirSync(migrationsDir).filter(f => f.endsWith('.sql')).sort();
for (const file of files) {
if (file.includes('seed')) continue; // Skip seed placeholder
console.log(`Running migration: ${file}`);
const sql = fs.readFileSync(path.join(migrationsDir, file), 'utf8');
// Split by semicolons and execute each statement
const statements = sql.split(';').filter(s => s.trim() && !s.trim().startsWith('--'));
for (const stmt of statements) {
if (stmt.trim()) {
const { error } = await supabase.rpc('exec_sql', { sql: stmt.trim() });
if (error && !error.message.includes('already exists')) {
console.warn(` Warning: ${error.message}`);
}
}
}
console.log(` Done.`);
}
}
async function seedData() {
const seedFile = path.join(__dirname, '..', 'supabase', 'seed_data.json');
if (!fs.existsSync(seedFile)) {
console.log('No seed_data.json found, skipping seed.');
return;
}
const seed = JSON.parse(fs.readFileSync(seedFile, 'utf-8'));
// Insert shippers
if (seed.shippers && seed.shippers.length > 0) {
console.log(`Inserting ${seed.shippers.length} shippers...`);
const { error } = await supabase.from('shippers').upsert(seed.shippers, { onConflict: 'id' });
if (error) console.error('Shippers error:', error.message);
else console.log(' Done.');
}
// Insert vehicles
if (seed.vehicles && seed.vehicles.length > 0) {
console.log(`Inserting ${seed.vehicles.length} vehicles...`);
const { error } = await supabase.from('vehicles').upsert(seed.vehicles, { onConflict: 'id' });
if (error) console.error('Vehicles error:', error.message);
else console.log(' Done.');
}
// Insert loads in batches
if (seed.loads && seed.loads.length > 0) {
console.log(`Inserting ${seed.loads.length} loads...`);
const batchSize = 20;
for (let i = 0; i < seed.loads.length; i += batchSize) {
const batch = seed.loads.slice(i, i + batchSize);
const { error } = await supabase.from('loads').upsert(batch, { onConflict: 'id' });
if (error) console.error(`Loads batch error (${i}-${i + batchSize}):`, error.message);
else console.log(` Batch ${Math.floor(i / batchSize) + 1} done.`);
}
}
// Update shipper totals
console.log('Updating shipper totals...');
for (const shipper of seed.shippers) {
const shipperLoads = seed.loads.filter(l => l.shipper_id === shipper.id);
const totals = shipperLoads.reduce((acc, l) => ({
freight: acc.freight + (l.freight_charged || 0),
commission: acc.commission + (l.commission || 0),
pending: acc.pending + (l.pending_from_shipper || 0),
}), { freight: 0, commission: 0, pending: 0 });
await supabase.from('shippers').update({
total_freight: totals.freight,
total_commission: totals.commission,
pending_amount: totals.pending,
}).eq('id', shipper.id);
}
console.log(' Done.');
}
async function main() {
console.log('=== FreightDesk Seeder ===\n');
try {
console.log('Step 1: Running migrations...');
// Note: For actual migration execution, use Supabase CLI or Dashboard SQL editor
// This is a simplified approach - run migrations manually in Supabase SQL Editor
console.log(' Please run the SQL migrations in Supabase SQL Editor first:');
console.log(' - supabase/migrations/001_initial_schema.sql\n');
console.log('Step 2: Seeding data...');
await seedData();
console.log('\n=== Seed complete! ===');
} catch (err) {
console.error('Fatal error:', err);
process.exit(1);
}
}
main();