Files
Jyotisha/frontend/supabase/migrations/20260717020000_birth_time_journey.sql
T
2026-07-17 16:19:11 +08:00

209 lines
7.3 KiB
PL/PgSQL

begin;
alter table public.profiles
add column if not exists reported_birth_time time without time zone,
add column if not exists active_birth_time time without time zone,
add column if not exists birth_time_source text,
add column if not exists birth_time_period text,
add column if not exists birth_time_clue text,
add column if not exists uncertainty_before_minutes integer,
add column if not exists uncertainty_after_minutes integer,
add column if not exists birth_time_status text,
add column if not exists rectification_confidence numeric(5, 2),
add column if not exists rectification_case_id uuid;
update public.profiles
set
reported_birth_time = coalesce(reported_birth_time, birth_time),
active_birth_time = coalesce(active_birth_time, birth_time),
birth_time_source = coalesce(birth_time_source, 'legacy_import'),
birth_time_status = coalesce(birth_time_status, 'confirmed')
where birth_time is not null;
alter table public.profiles
drop constraint if exists profiles_birth_time_source_check,
drop constraint if exists profiles_birth_time_period_check,
drop constraint if exists profiles_birth_time_status_check,
drop constraint if exists profiles_uncertainty_before_range,
drop constraint if exists profiles_uncertainty_after_range,
drop constraint if exists profiles_rectification_confidence_range;
alter table public.profiles
add constraint profiles_birth_time_source_check check (
birth_time_source is null or birth_time_source in (
'hospital_record',
'family_exact',
'approximate',
'period_only',
'unknown',
'legacy_import'
)
),
add constraint profiles_birth_time_period_check check (
birth_time_period is null or birth_time_period in (
'early_morning',
'morning',
'afternoon',
'evening',
'late_night'
)
),
add constraint profiles_birth_time_status_check check (
birth_time_status is null or birth_time_status in (
'reported',
'assessing',
'rectifying',
'candidate',
'confirmed'
)
),
add constraint profiles_uncertainty_before_range check (
uncertainty_before_minutes is null or uncertainty_before_minutes between 0 and 720
),
add constraint profiles_uncertainty_after_range check (
uncertainty_after_minutes is null or uncertainty_after_minutes between 0 and 720
),
add constraint profiles_rectification_confidence_range check (
rectification_confidence is null or rectification_confidence between 0 and 100
);
create table if not exists public.birth_time_rectification_cases (
id uuid primary key default gen_random_uuid(),
user_id uuid not null references auth.users(id) on delete cascade,
status text not null default 'assessing' check (
status in ('assessing', 'rectifying', 'candidate', 'confirmed')
),
reported_date date not null,
reported_time time without time zone,
reported_period text,
source text not null,
uncertainty_before_minutes integer,
uncertainty_after_minutes integer,
questionnaire jsonb not null default '{}'::jsonb check (jsonb_typeof(questionnaire) = 'object'),
journey_snapshot jsonb not null default '{}'::jsonb check (jsonb_typeof(journey_snapshot) = 'object'),
answers jsonb not null default '{}'::jsonb check (jsonb_typeof(answers) = 'object'),
candidate_scan jsonb not null default '{}'::jsonb check (jsonb_typeof(candidate_scan) = 'object'),
scoring_result jsonb not null default '{}'::jsonb check (jsonb_typeof(scoring_result) = 'object'),
candidate_start time without time zone,
candidate_end time without time zone,
algorithm_version text not null default 'birth-time-journey-v1',
ayanamsa text not null default 'lahiri',
node_mode text not null default 'true',
confirmed_time time without time zone,
confirmed_at timestamptz,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
alter table public.profiles
drop constraint if exists profiles_rectification_case_id_fkey,
add constraint profiles_rectification_case_id_fkey
foreign key (rectification_case_id)
references public.birth_time_rectification_cases(id)
on delete set null;
create or replace function public.guard_birth_time_journey()
returns trigger
language plpgsql
set search_path = ''
as $$
begin
if old.reported_birth_time is not null
and new.reported_birth_time is distinct from old.reported_birth_time then
raise exception 'reported_birth_time_is_immutable';
end if;
if new.active_birth_time is distinct from old.active_birth_time then
new.birth_time := new.active_birth_time;
elsif new.birth_time is distinct from old.birth_time then
new.active_birth_time := new.birth_time;
end if;
if new.reported_birth_time is null and new.birth_time is not null then
new.reported_birth_time := new.birth_time;
end if;
if new.birth_time_source is null and new.birth_time is not null then
new.birth_time_source := 'legacy_import';
end if;
if new.birth_time_status is null and new.active_birth_time is not null then
new.birth_time_status := 'confirmed';
end if;
return new;
end;
$$;
drop trigger if exists profiles_guard_birth_time_journey on public.profiles;
create trigger profiles_guard_birth_time_journey
before update of birth_time, reported_birth_time, active_birth_time on public.profiles
for each row execute function public.guard_birth_time_journey();
alter table public.birth_time_rectification_cases enable row level security;
drop policy if exists birth_time_cases_select_own on public.birth_time_rectification_cases;
create policy birth_time_cases_select_own
on public.birth_time_rectification_cases
for select to authenticated
using ((select auth.uid()) = user_id);
drop policy if exists birth_time_cases_insert_own on public.birth_time_rectification_cases;
create policy birth_time_cases_insert_own
on public.birth_time_rectification_cases
for insert to authenticated
with check ((select auth.uid()) = user_id);
drop policy if exists birth_time_cases_update_own on public.birth_time_rectification_cases;
create policy birth_time_cases_update_own
on public.birth_time_rectification_cases
for update to authenticated
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);
revoke all on table public.birth_time_rectification_cases from anon, authenticated, service_role;
grant all on table public.birth_time_rectification_cases to service_role;
grant select on table public.birth_time_rectification_cases to authenticated;
grant insert (
id,
user_id,
status,
reported_date,
reported_time,
reported_period,
source,
uncertainty_before_minutes,
uncertainty_after_minutes,
questionnaire,
journey_snapshot,
answers,
candidate_scan,
scoring_result,
candidate_start,
candidate_end,
updated_at
) on table public.birth_time_rectification_cases to authenticated;
grant update (
status,
questionnaire,
journey_snapshot,
answers,
candidate_scan,
scoring_result,
candidate_start,
candidate_end,
confirmed_time,
confirmed_at,
updated_at
) on table public.birth_time_rectification_cases to authenticated;
revoke update (birth_time) on table public.profiles from authenticated;
grant update (
reported_birth_time,
birth_time_source,
birth_time_period,
birth_time_clue,
uncertainty_before_minutes,
uncertainty_after_minutes
) on table public.profiles to authenticated;
commit;