diff --git a/backend/src/db.js b/backend/src/db.js new file mode 100644 index 0000000..236ce57 --- /dev/null +++ b/backend/src/db.js @@ -0,0 +1,118 @@ +import Database from 'better-sqlite3'; +import fs from 'fs'; +import path from 'path'; +import dotenv from 'dotenv'; + +dotenv.config(); + +const dbPath = process.env.DATABASE_PATH || './data/vk_hub.sqlite'; +const dir = path.dirname(dbPath); +if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }); + +export const db = new Database(dbPath); +db.pragma('journal_mode = WAL'); +db.pragma('foreign_keys = ON'); + +export function migrate() { + db.exec(` + CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + vk_user_id TEXT UNIQUE NOT NULL, + first_name TEXT, + last_name TEXT, + avatar_url TEXT, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE IF NOT EXISTS groups ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + vk_group_id TEXT UNIQUE NOT NULL, + title TEXT NOT NULL, + screen_name TEXT, + telegram_chat_id TEXT, + plan TEXT NOT NULL DEFAULT 'free', + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE IF NOT EXISTS group_members ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + group_id INTEGER NOT NULL REFERENCES groups(id) ON DELETE CASCADE, + user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, + role TEXT NOT NULL DEFAULT 'client', + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + UNIQUE(group_id, user_id) + ); + + CREATE TABLE IF NOT EXISTS services ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + group_id INTEGER NOT NULL REFERENCES groups(id) ON DELETE CASCADE, + title TEXT NOT NULL, + description TEXT, + price INTEGER NOT NULL DEFAULT 0, + duration_minutes INTEGER, + is_active INTEGER NOT NULL DEFAULT 1, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE IF NOT EXISTS clients ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + group_id INTEGER NOT NULL REFERENCES groups(id) ON DELETE CASCADE, + user_id INTEGER REFERENCES users(id) ON DELETE SET NULL, + name TEXT NOT NULL, + phone TEXT, + note TEXT, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE IF NOT EXISTS leads ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + group_id INTEGER NOT NULL REFERENCES groups(id) ON DELETE CASCADE, + client_id INTEGER REFERENCES clients(id) ON DELETE SET NULL, + service_id INTEGER REFERENCES services(id) ON DELETE SET NULL, + title TEXT NOT NULL, + name TEXT NOT NULL, + phone TEXT, + comment TEXT, + status TEXT NOT NULL DEFAULT 'new', + source TEXT NOT NULL DEFAULT 'vk_mini_app', + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE IF NOT EXISTS lead_comments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + lead_id INTEGER NOT NULL REFERENCES leads(id) ON DELETE CASCADE, + user_id INTEGER REFERENCES users(id) ON DELETE SET NULL, + body TEXT NOT NULL, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE IF NOT EXISTS faq_items ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + group_id INTEGER NOT NULL REFERENCES groups(id) ON DELETE CASCADE, + question TEXT NOT NULL, + answer TEXT NOT NULL, + sort_order INTEGER NOT NULL DEFAULT 100, + is_active INTEGER NOT NULL DEFAULT 1, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + + CREATE TABLE IF NOT EXISTS audit_logs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + group_id INTEGER REFERENCES groups(id) ON DELETE SET NULL, + user_id INTEGER REFERENCES users(id) ON DELETE SET NULL, + action TEXT NOT NULL, + payload TEXT, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + `); +} + +migrate(); + +if (process.argv.includes('--migrate')) { + console.log('Database migrated:', dbPath); +}