Add data import export functions
This commit is contained in:
@@ -26,6 +26,51 @@ async function insertItems(client, serviceOrderId, items) {
|
||||
app.use(express.json());
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
const dataTables = [
|
||||
{ name: 'customers', columns: ['customer_id', 'first_name', 'last_name', 'email', 'phone', 'created_at'] },
|
||||
{ name: 'employees', columns: ['employee_id', 'first_name', 'last_name', 'role', 'email', 'active'] },
|
||||
{ name: 'vehicles', columns: ['vehicle_id', 'customer_id', 'registration_number', 'make', 'model', 'model_year', 'engine', 'transmission', 'fuel_type', 'color', 'vin', 'mileage', 'created_at'] },
|
||||
{ name: 'appointments', columns: ['appointment_id', 'vehicle_id', 'employee_id', 'scheduled_at', 'reason', 'status', 'created_at'] },
|
||||
{ name: 'service_orders', columns: ['service_order_id', 'vehicle_id', 'assigned_employee_id', 'opened_at', 'closed_at', 'complaint', 'service_date', 'diagnosis', 'status'] },
|
||||
{ name: 'service_order_items', columns: ['item_id', 'service_order_id', 'item_type', 'description', 'part_number', 'labor_time_minutes', 'quantity', 'unit_price', 'created_at'] },
|
||||
{ name: 'invoices', columns: ['invoice_id', 'service_order_id', 'issued_at', 'due_at', 'status', 'tax_rate'] },
|
||||
{ name: 'app_users', columns: ['user_id', 'username', 'display_name', 'email', 'role', 'can_read', 'can_add', 'can_delete', 'created_at'] }
|
||||
];
|
||||
|
||||
app.get('/api/data/export', async (_request, response) => {
|
||||
try {
|
||||
const tables = {};
|
||||
for (const table of dataTables) {
|
||||
const result = await pool.query(`SELECT ${table.columns.join(', ')} FROM ${table.name} ORDER BY 1`);
|
||||
tables[table.name] = result.rows;
|
||||
}
|
||||
response.json({ format: 'car-service-database', version: 1, exportedAt: new Date().toISOString(), tables });
|
||||
} catch (error) { response.status(500).json({ error: 'Unable to export database data.' }); }
|
||||
});
|
||||
|
||||
app.post('/api/data/import', async (request, response) => {
|
||||
const snapshot = request.body;
|
||||
if (!snapshot || snapshot.format !== 'car-service-database' || snapshot.version !== 1 || !snapshot.tables || typeof snapshot.tables !== 'object') return response.status(400).json({ error: 'Invalid backup file.' });
|
||||
for (const table of dataTables) if (!Array.isArray(snapshot.tables[table.name])) return response.status(400).json({ error: `Backup is missing the ${table.name} table.` });
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
await client.query('TRUNCATE TABLE invoices, service_order_items, service_orders, appointments, vehicles, employees, customers, app_users RESTART IDENTITY CASCADE');
|
||||
for (const table of dataTables) {
|
||||
for (const row of snapshot.tables[table.name]) {
|
||||
const values = table.columns.map((column) => row[column] === undefined ? null : row[column]);
|
||||
const placeholders = values.map((_value, index) => `$${index + 1}`).join(', ');
|
||||
await client.query(`INSERT INTO ${table.name} (${table.columns.join(', ')}) VALUES (${placeholders})`, values);
|
||||
}
|
||||
}
|
||||
await client.query('COMMIT');
|
||||
response.json({ imported: dataTables.reduce((total, table) => total + snapshot.tables[table.name].length, 0) });
|
||||
} catch (error) {
|
||||
await client.query('ROLLBACK');
|
||||
response.status(400).json({ error: 'Import failed. No existing data was changed.' });
|
||||
} finally { client.release(); }
|
||||
});
|
||||
|
||||
app.get('/api/summary', async (_request, response) => {
|
||||
try {
|
||||
const result = await pool.query(`SELECT (SELECT COUNT(*)::int FROM customers) AS customers, (SELECT COUNT(*)::int FROM vehicles) AS vehicles, (SELECT COUNT(*)::int FROM service_orders WHERE status NOT IN ('closed', 'cancelled')) AS active_orders, (SELECT COUNT(*)::int FROM appointments WHERE scheduled_at >= CURRENT_DATE AND scheduled_at < CURRENT_DATE + INTERVAL '1 day' AND status NOT IN ('cancelled', 'no_show')) AS today_appointments`);
|
||||
|
||||
Reference in New Issue
Block a user