Files
Car-Service-Database/init.sql
T
2026-08-26 23:34:22 +03:00

106 lines
4.4 KiB
SQL

CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE TABLE IF NOT EXISTS customers (
customer_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
email TEXT UNIQUE,
phone TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS vehicles (
vehicle_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id UUID NOT NULL REFERENCES customers(customer_id) ON DELETE CASCADE,
registration_number TEXT NOT NULL UNIQUE,
make TEXT NOT NULL,
model TEXT NOT NULL,
model_year INTEGER CHECK (model_year BETWEEN 1886 AND EXTRACT(YEAR FROM CURRENT_DATE)::INTEGER + 1),
engine TEXT,
transmission TEXT,
fuel_type TEXT,
color TEXT,
vin CHAR(17) UNIQUE,
mileage INTEGER NOT NULL DEFAULT 0 CHECK (mileage >= 0),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS employees (
employee_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
role TEXT NOT NULL CHECK (role IN ('technician', 'service_advisor', 'manager')),
email TEXT UNIQUE,
active BOOLEAN NOT NULL DEFAULT TRUE
);
CREATE TABLE IF NOT EXISTS appointments (
appointment_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
vehicle_id UUID NOT NULL REFERENCES vehicles(vehicle_id) ON DELETE CASCADE,
employee_id UUID REFERENCES employees(employee_id) ON DELETE SET NULL,
scheduled_at TIMESTAMPTZ NOT NULL,
reason TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'scheduled'
CHECK (status IN ('scheduled', 'confirmed', 'completed', 'cancelled', 'no_show')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS service_orders (
service_order_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
vehicle_id UUID NOT NULL REFERENCES vehicles(vehicle_id) ON DELETE RESTRICT,
assigned_employee_id UUID REFERENCES employees(employee_id) ON DELETE SET NULL,
opened_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
closed_at TIMESTAMPTZ,
complaint TEXT NOT NULL,
service_date DATE NOT NULL DEFAULT CURRENT_DATE,
diagnosis TEXT,
status TEXT NOT NULL DEFAULT 'open'
CHECK (status IN ('open', 'in_progress', 'waiting_for_parts', 'ready', 'closed', 'cancelled')),
CHECK (closed_at IS NULL OR closed_at >= opened_at)
);
CREATE TABLE IF NOT EXISTS service_order_items (
item_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
service_order_id UUID NOT NULL REFERENCES service_orders(service_order_id) ON DELETE CASCADE,
item_type TEXT NOT NULL CHECK (item_type IN ('labor', 'part')),
description TEXT NOT NULL,
quantity NUMERIC(10, 2) NOT NULL DEFAULT 1 CHECK (quantity > 0),
unit_price NUMERIC(12, 2) NOT NULL CHECK (unit_price >= 0),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS invoices (
invoice_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
service_order_id UUID NOT NULL UNIQUE REFERENCES service_orders(service_order_id) ON DELETE RESTRICT,
issued_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
due_at DATE,
status TEXT NOT NULL DEFAULT 'unpaid'
CHECK (status IN ('draft', 'unpaid', 'paid', 'void')),
tax_rate NUMERIC(5, 2) NOT NULL DEFAULT 0 CHECK (tax_rate >= 0 AND tax_rate <= 100)
);
CREATE TABLE IF NOT EXISTS app_users (
user_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username TEXT NOT NULL UNIQUE,
display_name TEXT NOT NULL,
email TEXT UNIQUE,
role TEXT NOT NULL DEFAULT 'viewer'
CHECK (role IN ('admin', 'service_advisor', 'technician', 'viewer')),
can_read BOOLEAN NOT NULL DEFAULT TRUE,
can_add BOOLEAN NOT NULL DEFAULT FALSE,
can_delete BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_vehicles_customer_id ON vehicles(customer_id);
CREATE INDEX IF NOT EXISTS idx_appointments_scheduled_at ON appointments(scheduled_at);
CREATE INDEX IF NOT EXISTS idx_service_orders_vehicle_id ON service_orders(vehicle_id);
CREATE INDEX IF NOT EXISTS idx_service_orders_status ON service_orders(status);
INSERT INTO customers (first_name, last_name, email, phone)
VALUES ('Alex', 'Morgan', 'alex.morgan@example.com', '+1-555-0100')
ON CONFLICT (email) DO NOTHING;
INSERT INTO app_users (username, display_name, role, can_read, can_add, can_delete)
VALUES ('admin', 'Workshop administrator', 'admin', TRUE, TRUE, TRUE)
ON CONFLICT (username) DO NOTHING;