"""SQLite database initialization and access for Handoff Pro.""" import json import os import sqlite3 import uuid from datetime import datetime DB_PATH = os.environ.get("HANDOFF_DB", os.path.join(os.path.dirname(__file__), "..", "data", "handoff.db")) SCHEMA = """ CREATE TABLE IF NOT EXISTS jobs ( id TEXT PRIMARY KEY, user_id TEXT DEFAULT 'kellow', jobtread_job_id TEXT UNIQUE, client_name TEXT, jobtread_customer_id TEXT, address TEXT, description TEXT, status TEXT DEFAULT 'proposal', created_at TEXT, updated_at TEXT, synced_to_jobtread_at TEXT ); CREATE TABLE IF NOT EXISTS estimates ( id TEXT PRIMARY KEY, job_id TEXT REFERENCES jobs(id), jobtread_estimate_id TEXT UNIQUE, labor_hours REAL DEFAULT 0, labor_rate REAL DEFAULT 0, materials_cost REAL DEFAULT 0, markup_percent REAL DEFAULT 20, total_cost REAL DEFAULT 0, notes TEXT, status TEXT DEFAULT 'draft', created_at TEXT, synced_to_jobtread_at TEXT ); CREATE TABLE IF NOT EXISTS line_items ( id TEXT PRIMARY KEY, estimate_id TEXT REFERENCES estimates(id), description TEXT, category TEXT, quantity REAL DEFAULT 1, unit TEXT DEFAULT 'ea', unit_cost REAL DEFAULT 0, total REAL DEFAULT 0 ); CREATE TABLE IF NOT EXISTS pricing_catalogs ( id TEXT PRIMARY KEY, user_id TEXT DEFAULT 'kellow', name TEXT, labor_rates TEXT, material_markups TEXT, created_at TEXT ); CREATE TABLE IF NOT EXISTS invoices ( id TEXT PRIMARY KEY, estimate_id TEXT REFERENCES estimates(id), job_id TEXT REFERENCES jobs(id), invoice_number TEXT, jobtread_invoice_id TEXT UNIQUE, qbo_invoice_id TEXT, amount_due REAL DEFAULT 0, amount_paid REAL DEFAULT 0, due_date TEXT, status TEXT DEFAULT 'draft', created_at TEXT, synced_to_jobtread_at TEXT, synced_to_qbo_at TEXT ); CREATE TABLE IF NOT EXISTS daily_logs ( id TEXT PRIMARY KEY, job_id TEXT REFERENCES jobs(id), log_date TEXT, crew_names TEXT, hours_worked REAL DEFAULT 0, notes TEXT, photos TEXT, created_at TEXT ); CREATE TABLE IF NOT EXISTS signatures ( id TEXT PRIMARY KEY, estimate_id TEXT REFERENCES estimates(id), client_name TEXT, signature_data TEXT, signed_at TEXT ); CREATE TABLE IF NOT EXISTS client_activity ( id TEXT PRIMARY KEY, estimate_id TEXT REFERENCES estimates(id), job_id TEXT REFERENCES jobs(id), action TEXT, metadata TEXT, timestamp TEXT ); CREATE TABLE IF NOT EXISTS jobtread_sync_log ( id TEXT PRIMARY KEY, local_id TEXT, jobtread_id TEXT, entity_type TEXT, action TEXT, status TEXT DEFAULT 'pending', error_message TEXT, synced_at TEXT ); CREATE TABLE IF NOT EXISTS project_milestones ( id TEXT PRIMARY KEY, job_id TEXT REFERENCES jobs(id), phase_name TEXT, start_date TEXT, end_date TEXT, status TEXT DEFAULT 'pending' ); """ def get_db() -> sqlite3.Connection: os.makedirs(os.path.dirname(DB_PATH), exist_ok=True) conn = sqlite3.connect(DB_PATH, timeout=10) conn.row_factory = sqlite3.Row conn.execute("PRAGMA journal_mode=WAL") conn.execute("PRAGMA busy_timeout=5000") return conn def init_db(): conn = get_db() conn.executescript(SCHEMA) conn.commit() conn.close() def new_id(): return str(uuid.uuid4())[:8] def now(): return datetime.now().astimezone().isoformat() def row_to_dict(row): if row is None: return None return dict(row) def rows_to_list(rows): return [dict(r) for r in rows] if __name__ == "__main__": init_db() print(json.dumps({"ok": True, "db_path": DB_PATH}))