84 lines
4.4 KiB
SQL
84 lines
4.4 KiB
SQL
-- ====================================================================
|
||
-- 0053_booking_calendar — Kalenderbuchung (Booking Phase 1, Microsoft Graph)
|
||
-- ====================================================================
|
||
-- Baut auf Phase 0 (0052_appointment_requests) auf. Modell: zentrale
|
||
-- Azure-AD-App mit *Application Permissions* (IT erteilt EINMAL Admin-
|
||
-- Consent) + Opt-in pro Mitarbeiter. Kein Pro-MA-OAuth, keine Refresh-
|
||
-- Token-Speicherung — das App-only-Token kommt per Client-Credentials,
|
||
-- nur das Client-Secret liegt in der ENV. Siehe docs/booking-modul.md.
|
||
--
|
||
-- DSGVO: Der Opt-in-Schalter (calendar_connections.enabled) ist die
|
||
-- aktive Entscheidung des MA. Zusätzlich beschränkt eine Exchange
|
||
-- Application Access Policy die App technisch auf eine Sicherheitsgruppe.
|
||
|
||
-- ── Pro-MA-Verbindung + Verfügbarkeitsregeln ───────────────────────────
|
||
create table if not exists public.calendar_connections (
|
||
id uuid primary key default gen_random_uuid(),
|
||
employee_id uuid not null unique
|
||
references public.employees(id) on delete cascade,
|
||
provider text not null default 'microsoft',
|
||
-- M365-Postfach für die Graph-Calls (UPN/Mailbox, i. d. R. = Dienst-Mail).
|
||
mailbox_upn text not null,
|
||
-- Opt-in: nur wenn true, ruft TeamVis Graph für dieses Postfach auf.
|
||
enabled boolean not null default true,
|
||
-- Verfügbarkeitsregeln (Slots = Arbeitszeit − Belegt − vergebene Buchungen)
|
||
timezone text not null default 'Europe/Berlin',
|
||
slot_minutes integer not null default 30,
|
||
buffer_minutes integer not null default 0,
|
||
min_notice_hours integer not null default 24,
|
||
max_advance_days integer not null default 30,
|
||
workday_start time not null default '09:00',
|
||
workday_end time not null default '17:00',
|
||
-- ISO-Wochentage: 1=Montag … 7=Sonntag
|
||
workdays integer[] not null default '{1,2,3,4,5}',
|
||
-- Diagnostik: letzter erfolgreicher „Verbindung testen", letzter Fehler.
|
||
last_verified_at timestamptz,
|
||
last_error text,
|
||
created_at timestamptz not null default now(),
|
||
updated_at timestamptz not null default now()
|
||
);
|
||
|
||
comment on table public.calendar_connections is
|
||
'Opt-in pro Mitarbeiter für die Microsoft-Graph-Kalenderbuchung (Phase 1).';
|
||
|
||
-- ── Bestätigte Buchungen (echter Kalendereintrag via Graph) ────────────
|
||
create table if not exists public.bookings (
|
||
id uuid primary key default gen_random_uuid(),
|
||
employee_id uuid not null
|
||
references public.employees(id) on delete cascade,
|
||
appointment_request_id uuid
|
||
references public.appointment_requests(id) on delete set null,
|
||
start_at timestamptz not null,
|
||
end_at timestamptz not null,
|
||
time_zone text not null default 'Europe/Berlin',
|
||
guest_name text not null,
|
||
guest_email text,
|
||
guest_phone text,
|
||
company text,
|
||
subject text,
|
||
message text,
|
||
meeting_type text, -- 'vor_ort' | 'telefon' | 'video' | null
|
||
status text not null default 'confirmed',
|
||
-- 'confirmed' | 'cancelled'
|
||
graph_event_id text, -- Outlook-Event-ID (für Storno/Update)
|
||
ical_uid text,
|
||
cancel_token text not null, -- Self-Service-Storno durch den Gast
|
||
consent_given boolean not null default false,
|
||
source_url text,
|
||
created_at timestamptz not null default now()
|
||
);
|
||
|
||
create index if not exists bookings_employee_idx
|
||
on public.bookings (employee_id, start_at);
|
||
create index if not exists bookings_cancel_token_idx
|
||
on public.bookings (cancel_token);
|
||
|
||
-- ── RLS: admin/service-role only, kein anon-Grant ──────────────────────
|
||
-- Frei/Belegt-Lookup und Insert laufen ausschließlich über serverseitige
|
||
-- (rate-limitierte) Service-Role-Actions, wie card_leads/appointment_requests.
|
||
alter table public.calendar_connections enable row level security;
|
||
alter table public.bookings enable row level security;
|
||
|
||
grant select, insert, update, delete on public.calendar_connections to service_role;
|
||
grant select, insert, update, delete on public.bookings to service_role;
|