52 lines
2.2 KiB
SQL
52 lines
2.2 KiB
SQL
-- Users table
|
|||
|
|
CREATE TABLE IF NOT EXISTS users (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
username VARCHAR(100) UNIQUE NOT NULL,
|
||
|
|
password_hash VARCHAR(255) NOT NULL,
|
||
|
|
role VARCHAR(20) NOT NULL DEFAULT 'user' CHECK (role IN ('admin', 'user')),
|
||
|
|
mfa_secret VARCHAR(255),
|
||
|
|
mfa_enabled BOOLEAN DEFAULT FALSE,
|
||
|
|
must_change_password BOOLEAN DEFAULT TRUE,
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Field definitions table (dynamic fields configured by admin)
|
||
|
|
CREATE TABLE IF NOT EXISTS field_definitions (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
field_key VARCHAR(100) UNIQUE NOT NULL, -- internal key e.g. "first_name"
|
||
|
|
label VARCHAR(200) NOT NULL, -- display label e.g. "First Name"
|
||
|
|
field_type VARCHAR(20) NOT NULL DEFAULT 'text' CHECK (field_type IN ('text', 'number', 'phone', 'email')),
|
||
|
|
required BOOLEAN DEFAULT FALSE,
|
||
|
|
sort_order INTEGER DEFAULT 0,
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Contracts table with JSONB data (fully dynamic)
|
||
|
|
CREATE TABLE IF NOT EXISTS mobile_contracts (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
data JSONB NOT NULL DEFAULT '{}',
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Audit log table
|
||
|
|
CREATE TABLE IF NOT EXISTS audit_log (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
user_id INTEGER REFERENCES users(id),
|
||
|
|
action VARCHAR(100) NOT NULL,
|
||
|
|
details TEXT,
|
||
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Seed default fields
|
||
|
|
INSERT INTO field_definitions (field_key, label, field_type, required, sort_order) VALUES
|
||
|
|
('first_name', 'First Name', 'text', TRUE, 1),
|
||
|
|
('last_name', 'Last Name', 'text', TRUE, 2),
|
||
|
|
('phone_number', 'Phone Number', 'phone', FALSE, 3),
|
||
|
|
('mobile_contract_number', 'Mobile Contract Number', 'text', FALSE, 4),
|
||
|
|
('monthly_fixed_cost', 'Monthly Fixed Cost', 'number', FALSE, 5),
|
||
|
|
('monthly_available_data', 'Monthly Available Data', 'number', FALSE, 6)
|
||
|
|
ON CONFLICT (field_key) DO NOTHING;
|