feat(classes): weekly recurring schedules with lazy session materialization

class_schedules rules generate concrete session rows for a rolling 28-day
horizon — no cron; materialize runs idempotently on dashboard and public
reads via a partial unique index on (schedule_id, starts_at). Rule delete
stops future sessions; existing sessions keep bookings and overrides.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-18 17:31:17 +02:00
1 parent 7b9080eb1c
commit ad60167a31
15 files changed
+1029 -7

No files matched your search

@@ -0,0 +1,27 @@
-- +goose Up
-- Weekly recurring rules for class sessions. Rules materialize concrete
-- session rows for a rolling horizon (the service writes them); sessions
-- keep a nullable schedule_id link so regeneration is idempotent via the
-- partial unique index and deleting a rule stops future sessions without
-- touching existing ones.
CREATE TABLE class_schedules (
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,
day_of_week integer NOT NULL CHECK (day_of_week BETWEEN 0 AND 6),
starts_local time NOT NULL,
active boolean NOT NULL DEFAULT true,
created_at timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX class_schedules_tenant_idx ON class_schedules (tenant_id);
ALTER TABLE class_sessions
ADD COLUMN schedule_id uuid REFERENCES class_schedules(id) ON DELETE SET NULL;
CREATE UNIQUE INDEX class_sessions_schedule_start_idx
ON class_sessions (schedule_id, starts_at)
WHERE schedule_id IS NOT NULL;
-- +goose Down
ALTER TABLE class_sessions DROP COLUMN IF EXISTS schedule_id;
DROP TABLE IF EXISTS class_schedules;