Add missing jira_tickets sync columns migration and improve error messages

- Add add_jira_sync_columns_pg.js migration (jira_id, jira_status, last_synced_at, created_by)
- Register in run-all.js before the flexible creation migration
- Replace all generic 'Internal server error' with actual err.message in jiraTickets routes
- Users and admins can now see the real failure reason instead of a useless generic message
This commit is contained in:
Jordan Ramos
2026-05-22 10:12:35 -06:00
parent e86dd8be15
commit 704432788c
4 changed files with 66 additions and 6 deletions

View File

@@ -28,6 +28,23 @@ async function run() {
await pool.query(`ALTER TABLE jira_tickets ALTER COLUMN vendor DROP NOT NULL`);
console.log('✓ vendor NOT NULL constraint dropped (or was already nullable)');
// Add jira_id, jira_status, last_synced_at, created_by columns
// (originally from SQLite migration add_jira_sync_columns.js — never ported to Postgres run-all)
await pool.query(`ALTER TABLE jira_tickets ADD COLUMN IF NOT EXISTS jira_id TEXT`);
console.log('✓ jira_id column added (or already exists)');
await pool.query(`ALTER TABLE jira_tickets ADD COLUMN IF NOT EXISTS jira_status TEXT`);
console.log('✓ jira_status column added (or already exists)');
await pool.query(`ALTER TABLE jira_tickets ADD COLUMN IF NOT EXISTS last_synced_at TIMESTAMPTZ`);
console.log('✓ last_synced_at column added (or already exists)');
await pool.query(`ALTER TABLE jira_tickets ADD COLUMN IF NOT EXISTS created_by INTEGER`);
console.log('✓ created_by column added (or already exists)');
await pool.query(`CREATE INDEX IF NOT EXISTS idx_jira_tickets_jira_id ON jira_tickets(jira_id)`);
console.log('✓ jira_id index created (or already exists)');
// Add source_context column with default value (IF NOT EXISTS makes it idempotent)
await pool.query(`
ALTER TABLE jira_tickets

View File

@@ -0,0 +1,42 @@
// Migration: Add Jira sync columns to jira_tickets (Postgres version)
// Adds jira_id, jira_status, last_synced_at, and created_by columns.
// These were originally added via a SQLite migration that was never ported to Postgres.
// Idempotent — safe to run multiple times.
const pool = require('../db');
async function run() {
console.log('Adding Jira sync columns to jira_tickets (Postgres)...');
// Verify table exists
const { rows } = await pool.query(`
SELECT 1 FROM information_schema.tables
WHERE table_schema = 'public' AND table_name = 'jira_tickets'
`);
if (rows.length === 0) {
console.error('✗ jira_tickets table does not exist. Cannot proceed.');
process.exit(1);
}
await pool.query(`ALTER TABLE jira_tickets ADD COLUMN IF NOT EXISTS jira_id TEXT`);
console.log('✓ jira_id column added (or already exists)');
await pool.query(`ALTER TABLE jira_tickets ADD COLUMN IF NOT EXISTS jira_status TEXT`);
console.log('✓ jira_status column added (or already exists)');
await pool.query(`ALTER TABLE jira_tickets ADD COLUMN IF NOT EXISTS last_synced_at TIMESTAMPTZ`);
console.log('✓ last_synced_at column added (or already exists)');
await pool.query(`ALTER TABLE jira_tickets ADD COLUMN IF NOT EXISTS created_by INTEGER`);
console.log('✓ created_by column added (or already exists)');
await pool.query(`CREATE INDEX IF NOT EXISTS idx_jira_tickets_jira_id ON jira_tickets(jira_id)`);
console.log('✓ jira_id index created (or already exists)');
console.log('Migration complete.');
process.exit(0);
}
run().catch(err => {
console.error('Migration failed:', err.message);
process.exit(1);
});

View File

@@ -21,6 +21,7 @@ const POSTGRES_MIGRATIONS = [
'add_vcl_vertical_metadata.js',
'add_vcl_multi_vertical.js',
'add_compliance_item_history.js',
'add_jira_sync_columns_pg.js',
'add_flexible_jira_ticket_creation.js',
];

View File

@@ -386,7 +386,7 @@ function createJiraTicketsRouter() {
res.json(results);
} catch (err) {
console.error(err);
return res.status(500).json({ error: 'Internal server error.' });
return res.status(500).json({ error: err.message || 'Internal server error.' });
}
});
@@ -461,7 +461,7 @@ function createJiraTicketsRouter() {
});
} catch (err) {
console.error(err);
return res.status(500).json({ error: 'Internal server error.' });
return res.status(500).json({ error: err.message || 'Internal server error.' });
}
});
@@ -514,7 +514,7 @@ function createJiraTicketsRouter() {
res.json(rows);
} catch (err) {
console.error('Error fetching JIRA tickets:', err);
res.status(500).json({ error: 'Internal server error.' });
res.status(500).json({ error: err.message || 'Internal server error.' });
}
});
@@ -593,7 +593,7 @@ function createJiraTicketsRouter() {
});
} catch (err) {
console.error('Error creating JIRA ticket:', err);
res.status(500).json({ error: 'Internal server error.' });
res.status(500).json({ error: `Failed to save ticket: ${err.message}` });
}
});
@@ -677,7 +677,7 @@ function createJiraTicketsRouter() {
res.json({ message: 'JIRA ticket updated successfully', changes: result.rowCount });
} catch (err) {
console.error('Error updating JIRA ticket:', err);
res.status(500).json({ error: 'Internal server error.' });
res.status(500).json({ error: err.message || 'Internal server error.' });
}
});
@@ -758,7 +758,7 @@ function createJiraTicketsRouter() {
}
} catch (err) {
console.error('Error deleting JIRA ticket:', err);
res.status(500).json({ error: 'Internal server error.' });
res.status(500).json({ error: err.message || 'Internal server error.' });
}
});