chore: seminarhof customer project
This commit is contained in:
10
db/sqlite/0001-init.sql
Normal file
10
db/sqlite/0001-init.sql
Normal file
@@ -0,0 +1,10 @@
|
||||
CREATE TABLE IF NOT EXISTS kanban_card (
|
||||
card_id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'todo',
|
||||
position INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_kanban_card_status_position
|
||||
ON kanban_card (status, position);
|
||||
214
db/sqlite/0002-seminarhof.sql
Normal file
214
db/sqlite/0002-seminarhof.sql
Normal file
@@ -0,0 +1,214 @@
|
||||
-- Drop kanban template scaffold.
|
||||
DROP TABLE IF EXISTS kanban_card;
|
||||
|
||||
-- Seminarhof Drawehn core schema.
|
||||
-- Multi-tenant from day one (venue_id on every domain row).
|
||||
-- All money stored as integer cents (euro_cents) to avoid float drift.
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────
|
||||
-- Tenancy
|
||||
|
||||
CREATE TABLE IF NOT EXISTS venue (
|
||||
venue_id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
locale_default TEXT NOT NULL DEFAULT 'de',
|
||||
meal_window_breakfast TEXT NOT NULL DEFAULT '07:00-10:00',
|
||||
meal_window_lunch TEXT NOT NULL DEFAULT '12:00-14:00',
|
||||
meal_window_dinner TEXT NOT NULL DEFAULT '18:00-20:00',
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────
|
||||
-- Identity
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app_user (
|
||||
user_id TEXT PRIMARY KEY,
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
locale TEXT NOT NULL DEFAULT 'de',
|
||||
role TEXT NOT NULL, -- 'admin' | 'client' | 'owner'
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS client (
|
||||
client_id TEXT PRIMARY KEY,
|
||||
venue_id TEXT NOT NULL REFERENCES venue(venue_id),
|
||||
name TEXT,
|
||||
is_stammgruppe INTEGER NOT NULL DEFAULT 0,
|
||||
billing_address TEXT,
|
||||
contact_email TEXT,
|
||||
contact_phone TEXT,
|
||||
website TEXT,
|
||||
notes TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS client_member (
|
||||
client_id TEXT NOT NULL REFERENCES client(client_id),
|
||||
user_id TEXT NOT NULL REFERENCES app_user(user_id),
|
||||
role TEXT NOT NULL DEFAULT 'organiser', -- 'organiser' | 'colleague'
|
||||
PRIMARY KEY (client_id, user_id)
|
||||
);
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────
|
||||
-- Physical inventory
|
||||
|
||||
CREATE TABLE IF NOT EXISTS bathroom (
|
||||
bathroom_id TEXT PRIMARY KEY,
|
||||
venue_id TEXT NOT NULL REFERENCES venue(venue_id),
|
||||
label TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS room (
|
||||
room_id TEXT PRIMARY KEY,
|
||||
venue_id TEXT NOT NULL REFERENCES venue(venue_id),
|
||||
number INTEGER NOT NULL,
|
||||
beds INTEGER NOT NULL,
|
||||
room_type TEXT NOT NULL, -- 'MBZ' | 'DZ' | 'EZ_only'
|
||||
building TEXT NOT NULL, -- 'gaestehaus' | 'haupthaus'
|
||||
floor TEXT NOT NULL, -- 'eg' | 'og'
|
||||
bathroom_id TEXT REFERENCES bathroom(bathroom_id),
|
||||
wheelchair INTEGER NOT NULL DEFAULT 0,
|
||||
ground_floor INTEGER NOT NULL DEFAULT 0,
|
||||
quiet INTEGER NOT NULL DEFAULT 0,
|
||||
shared_bath INTEGER NOT NULL DEFAULT 0,
|
||||
dogs_allowed INTEGER NOT NULL DEFAULT 0,
|
||||
double_bed_140 INTEGER NOT NULL DEFAULT 0,
|
||||
allergy_friendly INTEGER NOT NULL DEFAULT 0,
|
||||
surcharge_eur_cents INTEGER NOT NULL DEFAULT 0,
|
||||
UNIQUE (venue_id, number)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS seminar_room (
|
||||
seminar_room_id TEXT PRIMARY KEY,
|
||||
venue_id TEXT NOT NULL REFERENCES venue(venue_id),
|
||||
name TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────
|
||||
-- Bookings
|
||||
|
||||
CREATE TABLE IF NOT EXISTS booking (
|
||||
booking_id TEXT PRIMARY KEY,
|
||||
venue_id TEXT NOT NULL REFERENCES venue(venue_id),
|
||||
client_id TEXT NOT NULL REFERENCES client(client_id),
|
||||
event_name TEXT NOT NULL,
|
||||
start_date TEXT,
|
||||
end_date TEXT,
|
||||
status TEXT NOT NULL, -- enquiry | form_received | reserved | deposit_paid | confirmed | ended | cancelled
|
||||
half_house INTEGER NOT NULL DEFAULT 0,
|
||||
online_ad INTEGER NOT NULL DEFAULT 0,
|
||||
cover_image_url TEXT,
|
||||
short_description TEXT,
|
||||
organiser_website TEXT,
|
||||
expected_persons INTEGER,
|
||||
meal_time_breakfast TEXT,
|
||||
meal_time_lunch TEXT,
|
||||
meal_time_dinner TEXT,
|
||||
daily_plan TEXT,
|
||||
arrival_time TEXT,
|
||||
departure_time TEXT,
|
||||
payment_method TEXT NOT NULL DEFAULT 'transfer', -- 'cash' | 'transfer'
|
||||
agb_year INTEGER,
|
||||
agb_accepted_at TEXT,
|
||||
privacy_accepted_at TEXT,
|
||||
notes TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_booking_venue_dates
|
||||
ON booking (venue_id, start_date, end_date);
|
||||
CREATE INDEX IF NOT EXISTS idx_booking_client
|
||||
ON booking (client_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_booking_status
|
||||
ON booking (venue_id, status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS booking_extra (
|
||||
booking_extra_id TEXT PRIMARY KEY,
|
||||
booking_id TEXT NOT NULL REFERENCES booking(booking_id),
|
||||
kind TEXT NOT NULL, -- 'cake' | 'second_seminar_room' | 'early_arrival' | 'bedlinen' | 'massage_bench' | 'sauna'
|
||||
qty INTEGER NOT NULL DEFAULT 1,
|
||||
on_dates TEXT, -- JSON array of dates for cake-day picker
|
||||
unit_price_cents INTEGER NOT NULL DEFAULT 0,
|
||||
note TEXT
|
||||
);
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────
|
||||
-- Participants
|
||||
|
||||
CREATE TABLE IF NOT EXISTS participant (
|
||||
participant_id TEXT PRIMARY KEY,
|
||||
booking_id TEXT NOT NULL REFERENCES booking(booking_id),
|
||||
name TEXT NOT NULL,
|
||||
email TEXT,
|
||||
age INTEGER,
|
||||
kind TEXT NOT NULL DEFAULT 'overnight', -- 'overnight' | 'day_guest'
|
||||
dietary_tag TEXT, -- 'omnivore' | 'vegetarian' | 'vegan' | 'gluten_free' | 'lactose_free' | 'pescatarian' | 'unknown'
|
||||
free_text TEXT,
|
||||
self_form_token TEXT UNIQUE,
|
||||
self_form_submitted_at TEXT,
|
||||
notes TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_participant_booking
|
||||
ON participant (booking_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS participant_allergy (
|
||||
participant_id TEXT NOT NULL REFERENCES participant(participant_id),
|
||||
allergen TEXT NOT NULL, -- 'nuts' | 'soy' | 'gluten_strict' | 'dairy' | 'egg' | 'fish' | 'other'
|
||||
severity TEXT NOT NULL DEFAULT 'standard', -- 'standard' | 'separate_prep'
|
||||
note TEXT,
|
||||
PRIMARY KEY (participant_id, allergen)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS room_assignment (
|
||||
booking_id TEXT NOT NULL REFERENCES booking(booking_id),
|
||||
participant_id TEXT NOT NULL REFERENCES participant(participant_id),
|
||||
room_id TEXT NOT NULL REFERENCES room(room_id),
|
||||
PRIMARY KEY (booking_id, participant_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_room_assignment_room
|
||||
ON room_assignment (room_id);
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────
|
||||
-- Invoicing
|
||||
|
||||
CREATE TABLE IF NOT EXISTS invoice (
|
||||
invoice_id TEXT PRIMARY KEY,
|
||||
booking_id TEXT NOT NULL REFERENCES booking(booking_id),
|
||||
kind TEXT NOT NULL, -- 'deposit' | 'final'
|
||||
invoice_number TEXT NOT NULL UNIQUE,
|
||||
issued_on TEXT NOT NULL,
|
||||
due_on TEXT,
|
||||
paid_on TEXT,
|
||||
amount_cents INTEGER NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'outstanding', -- 'outstanding' | 'paid' | 'cancelled'
|
||||
pdf_url TEXT,
|
||||
datev_ref TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_invoice_booking
|
||||
ON invoice (booking_id);
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────
|
||||
-- Audit
|
||||
|
||||
CREATE TABLE IF NOT EXISTS audit_log (
|
||||
audit_id TEXT PRIMARY KEY,
|
||||
venue_id TEXT NOT NULL REFERENCES venue(venue_id),
|
||||
user_id TEXT REFERENCES app_user(user_id),
|
||||
entity TEXT NOT NULL,
|
||||
entity_id TEXT NOT NULL,
|
||||
field TEXT,
|
||||
before_value TEXT,
|
||||
after_value TEXT,
|
||||
action TEXT NOT NULL, -- 'create' | 'update' | 'delete'
|
||||
at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_audit_entity
|
||||
ON audit_log (entity, entity_id);
|
||||
12
db/sqlite/0003-sessions.sql
Normal file
12
db/sqlite/0003-sessions.sql
Normal file
@@ -0,0 +1,12 @@
|
||||
-- Auth sessions: opaque cookie token → user_id mapping.
|
||||
-- We avoid JWT to keep the dependency footprint small; revocation is just DELETE.
|
||||
|
||||
CREATE TABLE session (
|
||||
session_id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES app_user(user_id) ON DELETE CASCADE,
|
||||
expires_at TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX session_user_idx ON session(user_id);
|
||||
CREATE INDEX session_expires_idx ON session(expires_at);
|
||||
4
db/sqlite/0004-passwords.sql
Normal file
4
db/sqlite/0004-passwords.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- Password support for app_user. Format stored: pbkdf2:<iterations>:<salt_b64>:<hash_b64>
|
||||
-- Existing rows have NULL password_hash and cannot log in until one is set.
|
||||
|
||||
ALTER TABLE app_user ADD COLUMN password_hash TEXT;
|
||||
4
db/sqlite/0005-course-fields.sql
Normal file
4
db/sqlite/0005-course-fields.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
-- Rename short_description -> description (the field is multi-sentence prose, not a
|
||||
-- "short" blurb) and add a separate one-line event_outline captured on the enquiry form.
|
||||
ALTER TABLE booking RENAME COLUMN short_description TO description;
|
||||
ALTER TABLE booking ADD COLUMN event_outline TEXT;
|
||||
17
db/sqlite/0006-booking-lifecycle.sql
Normal file
17
db/sqlite/0006-booking-lifecycle.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- Booking lifecycle milestones.
|
||||
--
|
||||
-- The status enum is reshaped to a lean "bucket": enquiry | reserved |
|
||||
-- confirmed | ended | cancelled. The contract + deposit progression that
|
||||
-- runs inside `reserved` (over ~1 year) is tracked as the columns below plus the
|
||||
-- deposit row on the invoice table — NOT as extra statuses. A daily cron reads
|
||||
-- these columns; nothing here runs a long-lived workflow.
|
||||
ALTER TABLE booking ADD COLUMN contract_sent_at TEXT; -- ISO; day-0 anchor + R1 idempotency guard
|
||||
ALTER TABLE booking ADD COLUMN contract_response TEXT; -- 'approved' | 'declined' | null (pending)
|
||||
ALTER TABLE booking ADD COLUMN contract_response_at TEXT; -- ISO
|
||||
ALTER TABLE booking ADD COLUMN deposit_reminder_sent_at TEXT; -- ISO; R2 idempotency guard
|
||||
ALTER TABLE booking ADD COLUMN flagged_at TEXT; -- ISO; set when admin review is needed
|
||||
ALTER TABLE booking ADD COLUMN flag_reason TEXT; -- 'deposit_overdue' | 'short_window' | 'contract_declined'
|
||||
|
||||
-- Collapse the two retired statuses onto the new bucket (for any non-reset DB).
|
||||
UPDATE booking SET status = 'reserved' WHERE status = 'form_received';
|
||||
UPDATE booking SET status = 'confirmed' WHERE status = 'deposit_paid';
|
||||
6
db/sqlite/0007-booking-status-dates.sql
Normal file
6
db/sqlite/0007-booking-status-dates.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
-- Status transition timestamps. Set by applyBookingTransition when each
|
||||
-- bucket is entered for the first time. No backfill — existing rows get NULL.
|
||||
ALTER TABLE booking ADD COLUMN reserved_at TEXT;
|
||||
ALTER TABLE booking ADD COLUMN confirmed_at TEXT;
|
||||
ALTER TABLE booking ADD COLUMN ended_at TEXT;
|
||||
ALTER TABLE booking ADD COLUMN cancelled_at TEXT;
|
||||
64
db/sqlite/0008-enquiry.sql
Normal file
64
db/sqlite/0008-enquiry.sql
Normal file
@@ -0,0 +1,64 @@
|
||||
-- Public enquiries get their own table and lifecycle, separate from bookings.
|
||||
-- A public submission lands here as `pending`. An admin then either:
|
||||
-- approve → status=approved, a booking is created (copy) referencing this
|
||||
-- enquiry via booking.enquiry_id (admin picks start/end + a client)
|
||||
-- waitlist → waitlisted_at set (requires ≥1 date option); stays pending so it
|
||||
-- can still be approved or declined later
|
||||
-- declined → status=declined
|
||||
--
|
||||
-- `waitlisted_at` is a parallel timestamp on a pending row, NOT a status — a
|
||||
-- waitlisted enquiry is still pending and can be approved or declined.
|
||||
--
|
||||
-- Dates live in `enquiry_date_option` (1-to-N, priority-ordered), NOT on the
|
||||
-- enquiry row — a visitor can propose several date ranges in priority order
|
||||
-- (E6.1). The enquiry has no single start/end of its own; reads that need a
|
||||
-- "preferred" date pick the lowest-priority option.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS enquiry (
|
||||
enquiry_id TEXT PRIMARY KEY,
|
||||
venue_id TEXT NOT NULL REFERENCES venue(venue_id),
|
||||
-- Contact details from the public form. No client row exists yet — one is
|
||||
-- selected or created on approval.
|
||||
contact_name TEXT,
|
||||
contact_email TEXT NOT NULL,
|
||||
contact_phone TEXT,
|
||||
website TEXT,
|
||||
-- Event details.
|
||||
event_name TEXT NOT NULL,
|
||||
event_outline TEXT,
|
||||
description TEXT,
|
||||
expected_persons INTEGER,
|
||||
half_house INTEGER NOT NULL DEFAULT 0,
|
||||
notes TEXT,
|
||||
privacy_accepted_at TEXT,
|
||||
-- Lifecycle.
|
||||
status TEXT NOT NULL DEFAULT 'pending', -- pending | approved | declined
|
||||
waitlisted_at TEXT,
|
||||
approved_at TEXT,
|
||||
declined_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_enquiry_venue_status
|
||||
ON enquiry (venue_id, status);
|
||||
|
||||
-- Prioritized date options for an enquiry (E6.1). `priority` is 0-based; 0 is
|
||||
-- the visitor's first choice. Optional: an enquiry may have zero options.
|
||||
CREATE TABLE IF NOT EXISTS enquiry_date_option (
|
||||
option_id TEXT PRIMARY KEY,
|
||||
enquiry_id TEXT NOT NULL REFERENCES enquiry(enquiry_id) ON DELETE CASCADE,
|
||||
start_date TEXT NOT NULL,
|
||||
end_date TEXT NOT NULL,
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_enquiry_date_option_enquiry
|
||||
ON enquiry_date_option (enquiry_id, priority);
|
||||
|
||||
-- A booking may originate from an approved enquiry. NULL for admin-created
|
||||
-- bookings. UNIQUE so an enquiry maps to at most one booking (SQLite allows
|
||||
-- many NULLs in a unique index).
|
||||
ALTER TABLE booking ADD COLUMN enquiry_id TEXT REFERENCES enquiry(enquiry_id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_booking_enquiry
|
||||
ON booking (enquiry_id);
|
||||
94
db/sqlite/0009-better-auth.sql
Normal file
94
db/sqlite/0009-better-auth.sql
Normal file
@@ -0,0 +1,94 @@
|
||||
-- Migrate from custom app_user/session to Better Auth.
|
||||
-- Drop tables with FKs to app_user, drop app_user, recreate with better-auth schema.
|
||||
|
||||
-- Drop tables that reference app_user
|
||||
DROP TABLE IF EXISTS client_member;
|
||||
DROP TABLE IF EXISTS session;
|
||||
DROP TABLE IF EXISTS audit_log;
|
||||
DROP TABLE IF EXISTS app_user;
|
||||
|
||||
-- Better Auth core tables
|
||||
CREATE TABLE IF NOT EXISTS "user" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL UNIQUE,
|
||||
"email_verified" INTEGER NOT NULL,
|
||||
"image" TEXT,
|
||||
"created_at" TEXT NOT NULL,
|
||||
"updated_at" TEXT NOT NULL,
|
||||
"role" TEXT NOT NULL DEFAULT 'client',
|
||||
"locale" TEXT NOT NULL DEFAULT 'de'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "session" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"expires_at" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL UNIQUE,
|
||||
"created_at" TEXT NOT NULL,
|
||||
"updated_at" TEXT NOT NULL,
|
||||
"ip_address" TEXT,
|
||||
"user_agent" TEXT,
|
||||
"user_id" TEXT NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "account" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"account_id" TEXT NOT NULL,
|
||||
"provider_id" TEXT NOT NULL,
|
||||
"user_id" TEXT NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE,
|
||||
"access_token" TEXT,
|
||||
"refresh_token" TEXT,
|
||||
"id_token" TEXT,
|
||||
"access_token_expires_at" TEXT,
|
||||
"refresh_token_expires_at" TEXT,
|
||||
"scope" TEXT,
|
||||
"password" TEXT,
|
||||
"created_at" TEXT NOT NULL,
|
||||
"updated_at" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "verification" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"identifier" TEXT NOT NULL,
|
||||
"value" TEXT NOT NULL,
|
||||
"expires_at" TEXT NOT NULL,
|
||||
"created_at" TEXT NOT NULL,
|
||||
"updated_at" TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Booking-client cookie sessions (kept separate from better-auth sessions)
|
||||
CREATE TABLE IF NOT EXISTS booking_session (
|
||||
session_id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL REFERENCES "user" ("id") ON DELETE CASCADE,
|
||||
expires_at TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
-- Recreate client_member referencing user(id)
|
||||
CREATE TABLE IF NOT EXISTS client_member (
|
||||
client_id TEXT NOT NULL REFERENCES client(client_id),
|
||||
user_id TEXT NOT NULL REFERENCES "user" ("id"),
|
||||
role TEXT NOT NULL DEFAULT 'organiser',
|
||||
PRIMARY KEY (client_id, user_id)
|
||||
);
|
||||
|
||||
-- Recreate audit_log referencing user(id)
|
||||
CREATE TABLE IF NOT EXISTS audit_log (
|
||||
audit_id TEXT PRIMARY KEY,
|
||||
venue_id TEXT NOT NULL REFERENCES venue(venue_id),
|
||||
user_id TEXT REFERENCES "user" ("id"),
|
||||
entity TEXT NOT NULL,
|
||||
entity_id TEXT NOT NULL,
|
||||
field TEXT,
|
||||
before_value TEXT,
|
||||
after_value TEXT,
|
||||
action TEXT NOT NULL,
|
||||
at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS session_user_id_idx ON "session" ("user_id");
|
||||
CREATE INDEX IF NOT EXISTS account_user_id_idx ON "account" ("user_id");
|
||||
CREATE INDEX IF NOT EXISTS verification_identifier_idx ON "verification" ("identifier");
|
||||
CREATE INDEX IF NOT EXISTS booking_session_user_idx ON booking_session (user_id);
|
||||
CREATE INDEX IF NOT EXISTS booking_session_expires_idx ON booking_session (expires_at);
|
||||
CREATE INDEX IF NOT EXISTS audit_log_entity_idx ON audit_log (entity, entity_id);
|
||||
Reference in New Issue
Block a user