stagingbackend / src /db /migrate8.js
Antaram's picture
Upload 31 files
291a4ef verified
Raw
History Blame Contribute Delete
4.47 kB
const pool = require('./config');
const MIGRATION_KEY = 'migrate8_single_global_bill_counter';
const migrate8 = async () => {
const client = await pool.connect();
try {
console.log('Starting database migration (migrate8)...');
await client.query('BEGIN');
// Ensure migration_history table exists
await client.query(`
CREATE TABLE IF NOT EXISTS migration_history (
key VARCHAR(120) PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`);
const already = await client.query(
'SELECT key FROM migration_history WHERE key = $1',
[MIGRATION_KEY]
);
if (already.rows.length > 0) {
await client.query('COMMIT');
console.log('migrate8 already applied. Skipping.');
return;
}
// Problem: Previously there were 8+ separate counters per bill type (J, A, P-J, P-A, etc.)
// plus orphaned migration prefixes (JAWAAK, AWAAK, etc.).
// Bills were NOT globally sequential — each type had its own sequence.
//
// Fix: Replace all separate counters with ONE global counter ('BILL').
// Seed it with the MAX bill number found across ALL tables and ALL existing counters.
// 1. Find max last_number from ALL existing bill_counters rows
const counterMax = await client.query(
'SELECT COALESCE(MAX(last_number), 0) as max_num FROM bill_counters'
);
const maxFromCounters = parseInt(counterMax.rows[0].max_num) || 0;
console.log(` Max from existing counters: ${maxFromCounters}`);
// 2. Find max numeric bill number from transactions table
// Filter out Date.now() timestamps (13+ digits) — those were from the old broken fallback
const txMax = await client.query(`
SELECT COALESCE(MAX(
CASE
WHEN bill_number ~ '^[0-9]+$' AND LENGTH(bill_number) <= 6 THEN CAST(bill_number AS INTEGER)
WHEN bill_number ~ '-[0-9]+$' AND LENGTH(substring(bill_number from '-([0-9]+)$')) <= 6 THEN CAST(substring(bill_number from '-([0-9]+)$') AS INTEGER)
ELSE 0
END
), 0) as max_num
FROM transactions
`);
const maxFromTx = parseInt(txMax.rows[0].max_num) || 0;
console.log(` Max from transactions table: ${maxFromTx}`);
// 3. Find max numeric bill number from patti_transactions table
const pattiMax = await client.query(`
SELECT COALESCE(MAX(
CASE
WHEN bill_number ~ '^[0-9]+$' AND LENGTH(bill_number) <= 6 THEN CAST(bill_number AS INTEGER)
WHEN bill_number ~ '-[0-9]+$' AND LENGTH(substring(bill_number from '-([0-9]+)$')) <= 6 THEN CAST(substring(bill_number from '-([0-9]+)$') AS INTEGER)
ELSE 0
END
), 0) as max_num
FROM patti_transactions
`);
const maxFromPatti = parseInt(pattiMax.rows[0].max_num) || 0;
console.log(` Max from patti_transactions table: ${maxFromPatti}`);
// 4. Take the overall maximum
const globalMax = Math.max(maxFromCounters, maxFromTx, maxFromPatti);
console.log(` Global max bill number: ${globalMax}`);
// 5. Delete ALL old counter rows (they're no longer needed)
await client.query('DELETE FROM bill_counters');
console.log(' Deleted all old counter rows');
// 6. Insert the single global counter
await client.query(
`INSERT INTO bill_counters (prefix, last_number, updated_at) VALUES ('BILL', $1, CURRENT_TIMESTAMP)`,
[globalMax]
);
console.log(` Created global counter 'BILL' starting at: ${globalMax}`);
console.log(` Next bill number will be: ${globalMax + 1}`);
// Record migration
await client.query(
'INSERT INTO migration_history(key) VALUES ($1)',
[MIGRATION_KEY]
);
await client.query('COMMIT');
console.log('migrate8 completed successfully!');
} catch (error) {
await client.query('ROLLBACK');
console.error('migrate8 failed:', error);
throw error;
} finally {
client.release();
await pool.end();
}
};
migrate8().catch(err => {
console.error('Fatal error:', err);
process.exit(1);
});