Venus / src /db /schema.py
Amir
Venus Hotel Front Desk – initial HF deploy
9d9d2a1
import sqlite3
SCHEMA_SQL = """
CREATE TABLE IF NOT EXISTS meta (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
role TEXT NOT NULL CHECK(role IN ('staff','admin')),
password_hash TEXT NOT NULL,
is_active INTEGER NOT NULL DEFAULT 1,
created_at_utc TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS rooms (
room_no INTEGER PRIMARY KEY,
room_type TEXT NOT NULL,
sellable INTEGER NOT NULL DEFAULT 1,
status TEXT NOT NULL CHECK(status IN ('free','occupied','need_cleaning','out_of_service')),
created_at_utc TEXT NOT NULL,
updated_at_utc TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS room_problems (
id INTEGER PRIMARY KEY AUTOINCREMENT,
room_no INTEGER NOT NULL,
problem_type TEXT NOT NULL CHECK(problem_type IN ('heater','ac','bed','other')),
description TEXT,
is_active INTEGER NOT NULL DEFAULT 1,
created_at_utc TEXT NOT NULL,
updated_at_utc TEXT NOT NULL,
FOREIGN KEY(room_no) REFERENCES rooms(room_no)
);
-- Immutable history: room status changes
CREATE TABLE IF NOT EXISTS room_status_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
room_no INTEGER NOT NULL,
from_status TEXT,
to_status TEXT NOT NULL,
note TEXT NOT NULL,
changed_by TEXT NOT NULL,
changed_at_utc TEXT NOT NULL,
FOREIGN KEY(room_no) REFERENCES rooms(room_no)
);
-- Immutable history: problem changes
CREATE TABLE IF NOT EXISTS room_problem_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
room_no INTEGER NOT NULL,
problem_type TEXT NOT NULL,
action TEXT NOT NULL CHECK(action IN ('add','deactivate','update')),
description TEXT,
note TEXT NOT NULL,
changed_by TEXT NOT NULL,
changed_at_utc TEXT NOT NULL,
FOREIGN KEY(room_no) REFERENCES rooms(room_no)
);
CREATE TABLE IF NOT EXISTS reservations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
room_no INTEGER NOT NULL,
guest_name TEXT NOT NULL,
guest_phone TEXT NOT NULL,
check_in_date TEXT NOT NULL, -- YYYY-MM-DD local
check_out_date TEXT NOT NULL, -- YYYY-MM-DD local
nights INTEGER NOT NULL,
rate_ro REAL NOT NULL,
total_ro REAL NOT NULL,
status TEXT NOT NULL CHECK(status IN ('active','closed','cancelled')),
created_by TEXT NOT NULL,
created_at_utc TEXT NOT NULL,
updated_by TEXT NOT NULL,
updated_at_utc TEXT NOT NULL,
close_note TEXT,
FOREIGN KEY(room_no) REFERENCES rooms(room_no)
);
CREATE TABLE IF NOT EXISTS reservation_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
reservation_id INTEGER NOT NULL,
action TEXT NOT NULL CHECK(action IN ('create','update','close','cancel')),
note TEXT NOT NULL,
changed_by TEXT NOT NULL,
changed_at_utc TEXT NOT NULL,
snapshot_json TEXT,
FOREIGN KEY(reservation_id) REFERENCES reservations(id)
);
CREATE TABLE IF NOT EXISTS payments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
reservation_id INTEGER NOT NULL,
amount_ro REAL NOT NULL,
method TEXT NOT NULL CHECK(method IN ('cash','card','bank','other')),
note TEXT,
changed_by TEXT NOT NULL,
changed_at_utc TEXT NOT NULL,
FOREIGN KEY(reservation_id) REFERENCES reservations(id)
);
CREATE TABLE IF NOT EXISTS payment_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
payment_id INTEGER,
reservation_id INTEGER NOT NULL,
action TEXT NOT NULL CHECK(action IN ('add','void')),
note TEXT NOT NULL,
changed_by TEXT NOT NULL,
changed_at_utc TEXT NOT NULL,
FOREIGN KEY(reservation_id) REFERENCES reservations(id)
);
CREATE TABLE IF NOT EXISTS income_expense (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entry_date TEXT NOT NULL, -- YYYY-MM-DD local (business day)
kind TEXT NOT NULL CHECK(kind IN ('income','expense')),
category TEXT NOT NULL,
amount_ro REAL NOT NULL,
method TEXT, -- income
vendor TEXT, -- expense
note TEXT,
changed_by TEXT NOT NULL,
changed_at_utc TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS day_closings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
business_date TEXT NOT NULL UNIQUE, -- YYYY-MM-DD closed day
closed_at_utc TEXT NOT NULL,
closed_by TEXT NOT NULL,
note TEXT NOT NULL,
pdf_path TEXT,
pdf_bytes BLOB
);
CREATE TABLE IF NOT EXISTS audit_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
entity TEXT NOT NULL,
entity_id TEXT,
action TEXT NOT NULL,
note TEXT NOT NULL,
changed_by TEXT NOT NULL,
changed_at_utc TEXT NOT NULL
);
"""
def init_schema(conn: sqlite3.Connection) -> None:
conn.executescript(SCHEMA_SQL)
conn.execute("INSERT OR IGNORE INTO meta(key,value) VALUES(?,?)", ("app", "venus-hotel-frontdesk"))
conn.execute("INSERT OR IGNORE INTO meta(key,value) VALUES(?,?)", ("schema_version", "1"))
conn.execute("INSERT OR IGNORE INTO meta(key,value) VALUES(?,?)", ("timezone", "Asia/Muscat"))