37 lines
1.7 KiB
SQL
37 lines
1.7 KiB
SQL
-- Sādhana streak rewards.
|
|
--
|
|
-- `sadhna_rewards` is the catalog of gift items (one row per reward),
|
|
-- seeded/synced at BFF startup from the embedded rewards.json so the
|
|
-- name / meaning / image_url stay in lockstep with the source of truth.
|
|
--
|
|
-- `sadhna_reward_grants` records which reward a user earned at which
|
|
-- streak milestone (a multiple of 7 days). The UNIQUE (user_id, milestone)
|
|
-- makes granting idempotent — a milestone hands out exactly one gift no
|
|
-- matter how often the dashboard is recomputed. `celebrated_at` is NULL
|
|
-- until the client has shown the confetti celebration, so a freshly earned
|
|
-- gift surfaces exactly once.
|
|
CREATE TABLE IF NOT EXISTS sadhna_rewards (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
key TEXT NOT NULL UNIQUE,
|
|
name TEXT NOT NULL,
|
|
meaning TEXT NOT NULL DEFAULT '',
|
|
image_url TEXT NOT NULL DEFAULT '',
|
|
active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
sort INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS sadhna_reward_grants (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
reward_id UUID NOT NULL REFERENCES sadhna_rewards(id) ON DELETE CASCADE,
|
|
milestone INTEGER NOT NULL,
|
|
granted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
celebrated_at TIMESTAMPTZ,
|
|
UNIQUE (user_id, milestone)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS sadhna_reward_grants_user_idx
|
|
ON sadhna_reward_grants (user_id, granted_at DESC);
|