Update db.js
This commit is contained in:
168
server/db.js
168
server/db.js
@@ -47,8 +47,6 @@ const dbInterface = {
|
|||||||
return {
|
return {
|
||||||
query: executeQuery,
|
query: executeQuery,
|
||||||
release: () => {},
|
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 () => {},
|
beginTransaction: async () => {},
|
||||||
commit: async () => {},
|
commit: async () => {},
|
||||||
rollback: async () => {}
|
rollback: async () => {}
|
||||||
@@ -66,44 +64,47 @@ const initDb = async () => {
|
|||||||
|
|
||||||
const TIMESTAMP_TYPE = 'TIMESTAMP';
|
const TIMESTAMP_TYPE = 'TIMESTAMP';
|
||||||
const LONG_TEXT_TYPE = DB_CLIENT === 'postgres' ? 'TEXT' : 'LONGTEXT'; // For base64 files
|
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(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS settings (
|
CREATE TABLE IF NOT EXISTS settings (
|
||||||
id INT PRIMARY KEY,
|
id INT PRIMARY KEY,
|
||||||
current_year INT,
|
current_year INT,
|
||||||
smtp_config JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'},
|
smtp_config ${JSON_TYPE},
|
||||||
features JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'},
|
features ${JSON_TYPE},
|
||||||
storage_config JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'}
|
storage_config ${JSON_TYPE},
|
||||||
|
branding ${JSON_TYPE}
|
||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// Migration: Add features column if not exists
|
// MIGRATION: Controllo e aggiunta colonne mancanti per installazioni esistenti
|
||||||
try {
|
try {
|
||||||
let hasFeatures = false;
|
let cols = [];
|
||||||
let hasStorage = false;
|
|
||||||
|
|
||||||
if (DB_CLIENT === 'postgres') {
|
if (DB_CLIENT === 'postgres') {
|
||||||
const [cols] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='settings'");
|
const [res] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='settings'");
|
||||||
hasFeatures = cols.some(c => c.column_name === 'features');
|
cols = res.map(c => c.column_name);
|
||||||
hasStorage = cols.some(c => c.column_name === 'storage_config');
|
|
||||||
} else {
|
} else {
|
||||||
const [cols] = await connection.query("SHOW COLUMNS FROM settings");
|
const [res] = await connection.query("SHOW COLUMNS FROM settings");
|
||||||
hasFeatures = cols.some(c => c.Field === 'features');
|
cols = res.map(c => c.Field);
|
||||||
hasStorage = cols.some(c => c.Field === 'storage_config');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasFeatures) {
|
if (!cols.includes('features')) {
|
||||||
console.log('Migrating: Adding features to settings...');
|
console.log('Migrating: Adding features to settings...');
|
||||||
await connection.query("ALTER TABLE settings ADD COLUMN features JSON");
|
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...');
|
console.log('Migrating: Adding storage_config to settings...');
|
||||||
await connection.query("ALTER TABLE settings ADD COLUMN storage_config JSON");
|
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); }
|
} catch(e) { console.warn("Settings migration warning:", e.message); }
|
||||||
|
|
||||||
// 1. Condos Table
|
// --- 1. CONDOS TABLE ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS condos (
|
CREATE TABLE IF NOT EXISTS condos (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -123,24 +124,24 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// Migration for condos due_day
|
// Migration condos
|
||||||
try {
|
try {
|
||||||
let hasDueDay = false;
|
let cols = [];
|
||||||
if (DB_CLIENT === 'postgres') {
|
if (DB_CLIENT === 'postgres') {
|
||||||
const [cols] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='condos'");
|
const [res] = await connection.query("SELECT column_name FROM information_schema.columns WHERE table_name='condos'");
|
||||||
hasDueDay = cols.some(c => c.column_name === 'due_day');
|
cols = res.map(c => c.column_name);
|
||||||
} else {
|
} else {
|
||||||
const [cols] = await connection.query("SHOW COLUMNS FROM condos");
|
const [res] = await connection.query("SHOW COLUMNS FROM condos");
|
||||||
hasDueDay = cols.some(c => c.Field === 'due_day');
|
cols = res.map(c => c.Field);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasDueDay) {
|
if (!cols.includes('due_day')) {
|
||||||
console.log('Migrating: Adding due_day to condos...');
|
console.log('Migrating: Adding due_day to condos...');
|
||||||
await connection.query("ALTER TABLE condos ADD COLUMN due_day INT DEFAULT 10");
|
await connection.query("ALTER TABLE condos ADD COLUMN due_day INT DEFAULT 10");
|
||||||
}
|
}
|
||||||
} catch(e) { console.warn("Condo migration warning:", e.message); }
|
} catch(e) { console.warn("Condo migration warning:", e.message); }
|
||||||
|
|
||||||
// 2. Families Table
|
// --- 2. FAMILIES TABLE ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS families (
|
CREATE TABLE IF NOT EXISTS families (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
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(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS payments (
|
CREATE TABLE IF NOT EXISTS payments (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -173,7 +191,7 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 4. Users Table
|
// --- 4. USERS TABLE ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -189,7 +207,7 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 5. Alerts Table
|
// --- 5. ALERTS TABLE ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS alerts (
|
CREATE TABLE IF NOT EXISTS alerts (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -206,7 +224,7 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 6. Notices Table
|
// --- 6. NOTICES TABLE ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS notices (
|
CREATE TABLE IF NOT EXISTS notices (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -217,13 +235,30 @@ const initDb = async () => {
|
|||||||
link VARCHAR(255),
|
link VARCHAR(255),
|
||||||
date ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP,
|
date ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP,
|
||||||
active BOOLEAN DEFAULT TRUE,
|
active BOOLEAN DEFAULT TRUE,
|
||||||
target_families JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'},
|
target_families ${JSON_TYPE},
|
||||||
created_at ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP,
|
created_at ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (condo_id) REFERENCES condos(id) ON DELETE CASCADE
|
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(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS notice_reads (
|
CREATE TABLE IF NOT EXISTS notice_reads (
|
||||||
user_id VARCHAR(36),
|
user_id VARCHAR(36),
|
||||||
@@ -234,7 +269,7 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 8. Tickets Table
|
// --- 8. TICKETS TABLE ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS tickets (
|
CREATE TABLE IF NOT EXISTS tickets (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -252,7 +287,7 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 9. Ticket Attachments
|
// --- 9. TICKET ATTACHMENTS ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS ticket_attachments (
|
CREATE TABLE IF NOT EXISTS ticket_attachments (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -265,7 +300,7 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 10. Ticket Comments
|
// --- 10. TICKET COMMENTS ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS ticket_comments (
|
CREATE TABLE IF NOT EXISTS ticket_comments (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -278,7 +313,7 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 11. Extraordinary Expenses
|
// --- 11. EXTRAORDINARY EXPENSES ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS extraordinary_expenses (
|
CREATE TABLE IF NOT EXISTS extraordinary_expenses (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
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(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS condo_expenses (
|
CREATE TABLE IF NOT EXISTS condo_expenses (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -360,7 +395,7 @@ const initDb = async () => {
|
|||||||
)
|
)
|
||||||
`);
|
`);
|
||||||
|
|
||||||
// 13. DOCUMENTS (Cloud/Local)
|
// --- 13. DOCUMENTS (Cloud/Local) ---
|
||||||
await connection.query(`
|
await connection.query(`
|
||||||
CREATE TABLE IF NOT EXISTS documents (
|
CREATE TABLE IF NOT EXISTS documents (
|
||||||
id VARCHAR(36) PRIMARY KEY,
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
@@ -370,7 +405,7 @@ const initDb = async () => {
|
|||||||
file_name VARCHAR(255) NOT NULL,
|
file_name VARCHAR(255) NOT NULL,
|
||||||
file_type VARCHAR(100),
|
file_type VARCHAR(100),
|
||||||
file_size INT,
|
file_size INT,
|
||||||
tags JSON ${DB_CLIENT === 'postgres' ? 'NULL' : 'NULL'},
|
tags ${JSON_TYPE},
|
||||||
storage_provider VARCHAR(50) DEFAULT 'local_db',
|
storage_provider VARCHAR(50) DEFAULT 'local_db',
|
||||||
file_data ${LONG_TEXT_TYPE},
|
file_data ${LONG_TEXT_TYPE},
|
||||||
upload_date ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP,
|
upload_date ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP,
|
||||||
@@ -388,48 +423,45 @@ const initDb = async () => {
|
|||||||
reports: true,
|
reports: true,
|
||||||
extraordinaryExpenses: true,
|
extraordinaryExpenses: true,
|
||||||
condoFinancialsView: false,
|
condoFinancialsView: false,
|
||||||
documents: true // Enabled by default for demo
|
documents: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultStorage = {
|
const defaultStorage = {
|
||||||
provider: 'local_db'
|
provider: 'local_db',
|
||||||
|
apiKey: '',
|
||||||
|
apiSecret: '',
|
||||||
|
bucket: '',
|
||||||
|
region: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultBranding = {
|
||||||
|
appName: 'CondoPay',
|
||||||
|
primaryColor: 'blue',
|
||||||
|
logoUrl: '',
|
||||||
|
loginBackgroundUrl: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
if (rows.length === 0) {
|
if (rows.length === 0) {
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
await connection.query(
|
await connection.query(
|
||||||
'INSERT INTO settings (id, current_year, features, storage_config) VALUES (1, ?, ?, ?)',
|
'INSERT INTO settings (id, current_year, features, storage_config, branding) VALUES (1, ?, ?, ?, ?)',
|
||||||
[currentYear, JSON.stringify(defaultFeatures), JSON.stringify(defaultStorage)]
|
[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 hash = await bcrypt.hash('admin', 10);
|
||||||
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');
|
|
||||||
await connection.query(
|
await connection.query(
|
||||||
'INSERT INTO users (id, email, password_hash, name, role) VALUES (?, ?, ?, ?, ?)',
|
'INSERT INTO users (id, email, password_hash, name, role, receive_alerts) VALUES (?, ?, ?, ?, ?, ?)',
|
||||||
[uuidv4(), 'fcarra79@gmail.com', hashedPassword, 'Amministratore', 'admin']
|
['admin-id', 'admin@condo.it', hash, 'Amministratore', 'admin', true]
|
||||||
);
|
);
|
||||||
} else {
|
console.log("Database initialized with seed data.");
|
||||||
await connection.query('UPDATE users SET role = ? WHERE email = ?', ['admin', 'fcarra79@gmail.com']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Database tables initialized.');
|
if (DB_CLIENT !== 'postgres') {
|
||||||
if (connection.release) connection.release();
|
connection.release();
|
||||||
} catch (error) {
|
}
|
||||||
console.error('Database initialization failed:', error);
|
} catch (e) {
|
||||||
process.exit(1);
|
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