From 6aaca6adc4a8f641e512a4d02ec3a057c3e4e72d Mon Sep 17 00:00:00 2001 From: frakarr Date: Fri, 9 Jan 2026 23:12:12 +0100 Subject: [PATCH] Update db.js --- server/db.js | 170 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 101 insertions(+), 69 deletions(-) diff --git a/server/db.js b/server/db.js index 13391ee..423c447 100644 --- a/server/db.js +++ b/server/db.js @@ -47,8 +47,6 @@ const dbInterface = { return { query: executeQuery, release: () => {}, - // Mock transaction methods for Postgres simple wrapper - // In a real prod app, you would get a specific client from the pool here beginTransaction: async () => {}, commit: async () => {}, rollback: async () => {} @@ -66,44 +64,47 @@ const initDb = async () => { const TIMESTAMP_TYPE = 'TIMESTAMP'; const LONG_TEXT_TYPE = DB_CLIENT === 'postgres' ? 'TEXT' : 'LONGTEXT'; // For base64 files + const JSON_TYPE = 'JSON'; - // 0. Settings Table (Global App Settings) + // --- 0. SETTINGS TABLE --- + // Definizione completa per nuova installazione await connection.query(` CREATE TABLE IF NOT EXISTS settings ( id INT PRIMARY KEY, current_year INT, - smtp_config JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'}, - features JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'}, - storage_config JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'} + smtp_config ${JSON_TYPE}, + features ${JSON_TYPE}, + storage_config ${JSON_TYPE}, + branding ${JSON_TYPE} ) `); - // Migration: Add features column if not exists + // MIGRATION: Controllo e aggiunta colonne mancanti per installazioni esistenti try { - let hasFeatures = false; - let hasStorage = false; - + let cols = []; if (DB_CLIENT === 'postgres') { - const [cols] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='settings'"); - hasFeatures = cols.some(c => c.column_name === 'features'); - hasStorage = cols.some(c => c.column_name === 'storage_config'); + const [res] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='settings'"); + cols = res.map(c => c.column_name); } else { - const [cols] = await connection.query("SHOW COLUMNS FROM settings"); - hasFeatures = cols.some(c => c.Field === 'features'); - hasStorage = cols.some(c => c.Field === 'storage_config'); + const [res] = await connection.query("SHOW COLUMNS FROM settings"); + cols = res.map(c => c.Field); } - if (!hasFeatures) { + if (!cols.includes('features')) { console.log('Migrating: Adding features to settings...'); await connection.query("ALTER TABLE settings ADD COLUMN features JSON"); } - if (!hasStorage) { + if (!cols.includes('storage_config')) { console.log('Migrating: Adding storage_config to settings...'); await connection.query("ALTER TABLE settings ADD COLUMN storage_config JSON"); } + if (!cols.includes('branding')) { + console.log('Migrating: Adding branding to settings...'); + await connection.query("ALTER TABLE settings ADD COLUMN branding JSON"); + } } catch(e) { console.warn("Settings migration warning:", e.message); } - // 1. Condos Table + // --- 1. CONDOS TABLE --- await connection.query(` CREATE TABLE IF NOT EXISTS condos ( id VARCHAR(36) PRIMARY KEY, @@ -123,24 +124,24 @@ const initDb = async () => { ) `); - // Migration for condos due_day + // Migration condos try { - let hasDueDay = false; + let cols = []; if (DB_CLIENT === 'postgres') { - const [cols] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='condos'"); - hasDueDay = cols.some(c => c.column_name === 'due_day'); + const [res] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='condos'"); + cols = res.map(c => c.column_name); } else { - const [cols] = await connection.query("SHOW COLUMNS FROM condos"); - hasDueDay = cols.some(c => c.Field === 'due_day'); + const [res] = await connection.query("SHOW COLUMNS FROM condos"); + cols = res.map(c => c.Field); } - if (!hasDueDay) { + if (!cols.includes('due_day')) { console.log('Migrating: Adding due_day to condos...'); await connection.query("ALTER TABLE condos ADD COLUMN due_day INT DEFAULT 10"); } } catch(e) { console.warn("Condo migration warning:", e.message); } - // 2. Families Table + // --- 2. FAMILIES TABLE --- await connection.query(` CREATE TABLE IF NOT EXISTS families ( id VARCHAR(36) PRIMARY KEY, @@ -157,7 +158,24 @@ const initDb = async () => { ) `); - // 3. Payments Table + // Migration families + try { + let cols = []; + if (DB_CLIENT === 'postgres') { + const [res] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='families'"); + cols = res.map(c => c.column_name); + } else { + const [res] = await connection.query("SHOW COLUMNS FROM families"); + cols = res.map(c => c.Field); + } + + if (!cols.includes('custom_monthly_quota')) { + console.log('Migrating: Adding custom_monthly_quota to families...'); + await connection.query("ALTER TABLE families ADD COLUMN custom_monthly_quota DECIMAL(10, 2) NULL"); + } + } catch(e) { console.warn("Family migration warning:", e.message); } + + // --- 3. PAYMENTS TABLE --- await connection.query(` CREATE TABLE IF NOT EXISTS payments ( id VARCHAR(36) PRIMARY KEY, @@ -173,7 +191,7 @@ const initDb = async () => { ) `); - // 4. Users Table + // --- 4. USERS TABLE --- await connection.query(` CREATE TABLE IF NOT EXISTS users ( id VARCHAR(36) PRIMARY KEY, @@ -189,7 +207,7 @@ const initDb = async () => { ) `); - // 5. Alerts Table + // --- 5. ALERTS TABLE --- await connection.query(` CREATE TABLE IF NOT EXISTS alerts ( id VARCHAR(36) PRIMARY KEY, @@ -206,7 +224,7 @@ const initDb = async () => { ) `); - // 6. Notices Table + // --- 6. NOTICES TABLE --- await connection.query(` CREATE TABLE IF NOT EXISTS notices ( id VARCHAR(36) PRIMARY KEY, @@ -217,13 +235,30 @@ const initDb = async () => { link VARCHAR(255), date ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP, active BOOLEAN DEFAULT TRUE, - target_families JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'}, + target_families ${JSON_TYPE}, created_at ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (condo_id) REFERENCES condos(id) ON DELETE CASCADE ) `); - // 7. Notice Reads + // Migration notices + try { + let cols = []; + if (DB_CLIENT === 'postgres') { + const [res] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='notices'"); + cols = res.map(c => c.column_name); + } else { + const [res] = await connection.query("SHOW COLUMNS FROM notices"); + cols = res.map(c => c.Field); + } + + if (!cols.includes('target_families')) { + console.log('Migrating: Adding target_families to notices...'); + await connection.query("ALTER TABLE notices ADD COLUMN target_families JSON"); + } + } catch(e) { console.warn("Notices migration warning:", e.message); } + + // --- 7. NOTICE READS --- await connection.query(` CREATE TABLE IF NOT EXISTS notice_reads ( user_id VARCHAR(36), @@ -234,7 +269,7 @@ const initDb = async () => { ) `); - // 8. Tickets Table + // --- 8. TICKETS TABLE --- await connection.query(` CREATE TABLE IF NOT EXISTS tickets ( id VARCHAR(36) PRIMARY KEY, @@ -252,7 +287,7 @@ const initDb = async () => { ) `); - // 9. Ticket Attachments + // --- 9. TICKET ATTACHMENTS --- await connection.query(` CREATE TABLE IF NOT EXISTS ticket_attachments ( id VARCHAR(36) PRIMARY KEY, @@ -265,7 +300,7 @@ const initDb = async () => { ) `); - // 10. Ticket Comments + // --- 10. TICKET COMMENTS --- await connection.query(` CREATE TABLE IF NOT EXISTS ticket_comments ( id VARCHAR(36) PRIMARY KEY, @@ -278,7 +313,7 @@ const initDb = async () => { ) `); - // 11. Extraordinary Expenses + // --- 11. EXTRAORDINARY EXPENSES --- await connection.query(` CREATE TABLE IF NOT EXISTS extraordinary_expenses ( id VARCHAR(36) PRIMARY KEY, @@ -330,7 +365,7 @@ const initDb = async () => { ) `); - // 12. CONDO ORDINARY EXPENSES (USCITE) + // --- 12. CONDO ORDINARY EXPENSES (USCITE) --- await connection.query(` CREATE TABLE IF NOT EXISTS condo_expenses ( id VARCHAR(36) PRIMARY KEY, @@ -360,7 +395,7 @@ const initDb = async () => { ) `); - // 13. DOCUMENTS (Cloud/Local) + // --- 13. DOCUMENTS (Cloud/Local) --- await connection.query(` CREATE TABLE IF NOT EXISTS documents ( id VARCHAR(36) PRIMARY KEY, @@ -370,7 +405,7 @@ const initDb = async () => { file_name VARCHAR(255) NOT NULL, file_type VARCHAR(100), file_size INT, - tags JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'}, + tags ${JSON_TYPE}, storage_provider VARCHAR(50) DEFAULT 'local_db', file_data ${LONG_TEXT_TYPE}, upload_date ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP, @@ -388,48 +423,45 @@ const initDb = async () => { reports: true, extraordinaryExpenses: true, condoFinancialsView: false, - documents: true // Enabled by default for demo + documents: true }; const defaultStorage = { - provider: 'local_db' + provider: 'local_db', + apiKey: '', + apiSecret: '', + bucket: '', + region: '' + }; + + const defaultBranding = { + appName: 'CondoPay', + primaryColor: 'blue', + logoUrl: '', + loginBackgroundUrl: '' }; if (rows.length === 0) { const currentYear = new Date().getFullYear(); await connection.query( - 'INSERT INTO settings (id, current_year, features, storage_config) VALUES (1, ?, ?, ?)', - [currentYear, JSON.stringify(defaultFeatures), JSON.stringify(defaultStorage)] + 'INSERT INTO settings (id, current_year, features, storage_config, branding) VALUES (1, ?, ?, ?, ?)', + [currentYear, JSON.stringify(defaultFeatures), JSON.stringify(defaultStorage), JSON.stringify(defaultBranding)] ); - } else { - // Ensure features column has defaults if null - if (!rows[0].features) { - await connection.query('UPDATE settings SET features = ? WHERE id = 1', [JSON.stringify(defaultFeatures)]); - } - if (!rows[0].storage_config) { - await connection.query('UPDATE settings SET storage_config = ? WHERE id = 1', [JSON.stringify(defaultStorage)]); - } - } - - // ENSURE ADMIN EXISTS - const [admins] = await connection.query('SELECT * FROM users WHERE email = ?', ['fcarra79@gmail.com']); - if (admins.length === 0) { - const hashedPassword = await bcrypt.hash('Mr10921.', 10); - const { v4: uuidv4 } = require('uuid'); + + const hash = await bcrypt.hash('admin', 10); await connection.query( - 'INSERT INTO users (id, email, password_hash, name, role) VALUES (?, ?, ?, ?, ?)', - [uuidv4(), 'fcarra79@gmail.com', hashedPassword, 'Amministratore', 'admin'] + 'INSERT INTO users (id, email, password_hash, name, role, receive_alerts) VALUES (?, ?, ?, ?, ?, ?)', + ['admin-id', 'admin@condo.it', hash, 'Amministratore', 'admin', true] ); - } else { - await connection.query('UPDATE users SET role = ? WHERE email = ?', ['admin', 'fcarra79@gmail.com']); + console.log("Database initialized with seed data."); } - console.log('Database tables initialized.'); - if (connection.release) connection.release(); - } catch (error) { - console.error('Database initialization failed:', error); - process.exit(1); + if (DB_CLIENT !== 'postgres') { + connection.release(); + } + } catch (e) { + console.error("Database init error:", e); } }; -module.exports = { pool: dbInterface, initDb }; +module.exports = { pool: DB_CLIENT === 'postgres' ? pgPool : mysqlPool, initDb };