Update db.js
This commit is contained in:
170
server/db.js
170
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 };
|
||||
|
||||
Reference in New Issue
Block a user