mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-06-04 12:33:00 +00:00
176 lines
6.2 KiB
SQL
176 lines
6.2 KiB
SQL
-- +goose Up
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
|
|
|
|
CREATE TABLE IF NOT EXISTS tenants (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
slug text NOT NULL UNIQUE,
|
|
name text NOT NULL,
|
|
preset text NOT NULL,
|
|
locale text NOT NULL DEFAULT 'cs',
|
|
timezone text NOT NULL DEFAULT 'Europe/Prague',
|
|
plan_code text NOT NULL DEFAULT 'starter',
|
|
subscription_status text NOT NULL DEFAULT 'trialing',
|
|
stripe_customer_id text,
|
|
stripe_subscription_id text,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id uuid PRIMARY KEY,
|
|
email text NOT NULL,
|
|
display_name text,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS tenant_users (
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
role text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
PRIMARY KEY (tenant_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS locations (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
name text NOT NULL,
|
|
timezone text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS staff (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
location_id uuid REFERENCES locations(id) ON DELETE SET NULL,
|
|
display_name text NOT NULL,
|
|
active boolean NOT NULL DEFAULT true,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS services (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
name text NOT NULL,
|
|
duration_minutes integer NOT NULL,
|
|
buffer_before_minutes integer NOT NULL DEFAULT 0,
|
|
buffer_after_minutes integer NOT NULL DEFAULT 0,
|
|
price_cents integer NOT NULL DEFAULT 0,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS class_templates (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
title text NOT NULL,
|
|
duration_minutes integer NOT NULL,
|
|
capacity integer NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS class_sessions (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
template_id uuid NOT NULL REFERENCES class_templates(id) ON DELETE CASCADE,
|
|
location_id uuid REFERENCES locations(id) ON DELETE SET NULL,
|
|
starts_at timestamptz NOT NULL,
|
|
ends_at timestamptz NOT NULL,
|
|
capacity integer NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS availability_rules (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
staff_id uuid REFERENCES staff(id) ON DELETE CASCADE,
|
|
day_of_week integer NOT NULL,
|
|
starts_local time NOT NULL,
|
|
ends_local time NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS availability_exceptions (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
staff_id uuid REFERENCES staff(id) ON DELETE CASCADE,
|
|
starts_at timestamptz NOT NULL,
|
|
ends_at timestamptz NOT NULL,
|
|
kind text NOT NULL,
|
|
reason text,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS bookings (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
service_id uuid REFERENCES services(id) ON DELETE SET NULL,
|
|
class_session_id uuid REFERENCES class_sessions(id) ON DELETE SET NULL,
|
|
staff_id uuid REFERENCES staff(id) ON DELETE SET NULL,
|
|
location_id uuid REFERENCES locations(id) ON DELETE SET NULL,
|
|
booking_mode text NOT NULL,
|
|
customer_name text NOT NULL,
|
|
customer_email text NOT NULL,
|
|
starts_at timestamptz NOT NULL,
|
|
ends_at timestamptz NOT NULL,
|
|
status text NOT NULL,
|
|
reference text NOT NULL UNIQUE,
|
|
notes text,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS waitlist_entries (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
class_session_id uuid NOT NULL REFERENCES class_sessions(id) ON DELETE CASCADE,
|
|
customer_name text NOT NULL,
|
|
customer_email text NOT NULL,
|
|
position integer NOT NULL,
|
|
status text NOT NULL DEFAULT 'pending',
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS reminder_jobs (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
booking_id uuid REFERENCES bookings(id) ON DELETE CASCADE,
|
|
channel text NOT NULL,
|
|
scheduled_for timestamptz NOT NULL,
|
|
dispatched_at timestamptz,
|
|
status text NOT NULL DEFAULT 'pending',
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS subscription_events (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id uuid NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
|
|
stripe_event_id text NOT NULL UNIQUE,
|
|
event_type text NOT NULL,
|
|
payload jsonb NOT NULL,
|
|
processed_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_bookings_tenant_time ON bookings (tenant_id, starts_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_sessions_tenant_time ON class_sessions (tenant_id, starts_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_reminder_jobs_pending ON reminder_jobs (scheduled_for) WHERE status = 'pending';
|
|
|
|
-- +goose Down
|
|
DROP TABLE IF EXISTS subscription_events;
|
|
DROP TABLE IF EXISTS reminder_jobs;
|
|
DROP TABLE IF EXISTS waitlist_entries;
|
|
DROP TABLE IF EXISTS bookings;
|
|
DROP TABLE IF EXISTS availability_exceptions;
|
|
DROP TABLE IF EXISTS availability_rules;
|
|
DROP TABLE IF EXISTS class_sessions;
|
|
DROP TABLE IF EXISTS class_templates;
|
|
DROP TABLE IF EXISTS services;
|
|
DROP TABLE IF EXISTS staff;
|
|
DROP TABLE IF EXISTS locations;
|
|
DROP TABLE IF EXISTS tenant_users;
|
|
DROP TABLE IF EXISTS users;
|
|
DROP TABLE IF EXISTS tenants;
|
|
|