Files
Jyotisha/frontend/supabase/migrations/20260718040000_guided_candidate_actions.sql
T
2026-07-18 18:40:23 +08:00

137 lines
5.0 KiB
PL/PgSQL

begin;
create or replace function public.save_guided_birth_time_candidate(
p_user_id uuid,
p_case_id uuid,
p_result_id uuid,
p_action_id uuid,
p_expected_version integer,
p_turn_state jsonb
)
returns void
language plpgsql
security definer
set search_path = ''
as $$
declare
current_version integer;
receipts uuid[];
begin
select turn_version, processed_action_ids
into current_version, receipts
from public.birth_time_rectification_cases
where id = p_case_id and user_id = p_user_id
for update;
if not found then raise exception 'invalid_guided_candidate_turn'; end if;
if p_action_id = any(receipts) then return; end if;
if current_version <> p_expected_version then raise exception 'stale_guided_candidate_turn'; end if;
if (p_turn_state ->> 'turnVersion')::integer <> p_expected_version + 1
or p_turn_state #>> '{nextAction,kind}' <> 'candidate_saved'
or p_turn_state #>> '{nextAction,resultId}' <> p_result_id::text
then raise exception 'invalid_guided_candidate_turn'; end if;
update public.birth_time_rectification_cases
set candidate_saved_at = now(),
turn_version = p_expected_version + 1,
turn_state = p_turn_state,
processed_action_ids = (array_append(processed_action_ids, p_action_id))[
greatest(cardinality(processed_action_ids) + 2 - 100, 1):cardinality(processed_action_ids) + 1
],
updated_at = now()
where id = p_case_id
and user_id = p_user_id
and turn_version = p_expected_version
and candidate_result_id = p_result_id
and status = 'candidate'
and candidate_result ->> 'confidence' = 'medium'
and (
(
turn_state #>> '{nextAction,kind}' = 'present_medium_result'
and turn_state #>> '{nextAction,resultId}' = p_result_id::text
)
or turn_state is null
or turn_state = '{}'::jsonb
);
if not found then raise exception 'invalid_guided_candidate_turn'; end if;
end;
$$;
create or replace function public.confirm_guided_birth_time_candidate(
p_user_id uuid,
p_case_id uuid,
p_result_id uuid,
p_time time without time zone,
p_action_id uuid,
p_expected_version integer,
p_snapshot jsonb,
p_turn_state jsonb
)
returns void
language plpgsql
security definer
set search_path = ''
as $$
declare
current_version integer;
receipts uuid[];
begin
select turn_version, processed_action_ids
into current_version, receipts
from public.birth_time_rectification_cases
where id = p_case_id and user_id = p_user_id
for update;
if not found then raise exception 'invalid_guided_candidate_turn'; end if;
if p_action_id = any(receipts) then return; end if;
if current_version <> p_expected_version then raise exception 'stale_guided_candidate_turn'; end if;
if (p_turn_state ->> 'turnVersion')::integer <> p_expected_version + 1
or p_turn_state #>> '{nextAction,kind}' <> 'ready'
or p_turn_state #>> '{nextAction,activeTime}' <> to_char(p_time, 'HH24:MI')
or p_snapshot ->> 'activeTime' <> to_char(p_time, 'HH24:MI')
then raise exception 'invalid_guided_candidate_turn'; end if;
update public.birth_time_rectification_cases
set status = 'confirmed', journey_snapshot = p_snapshot,
confirmed_time = p_time, confirmed_at = now(),
turn_version = p_expected_version + 1, turn_state = p_turn_state,
processed_action_ids = (array_append(processed_action_ids, p_action_id))[
greatest(cardinality(processed_action_ids) + 2 - 100, 1):cardinality(processed_action_ids) + 1
],
updated_at = now()
where id = p_case_id
and user_id = p_user_id
and turn_version = p_expected_version
and candidate_result_id = p_result_id
and status = 'confirming'
and candidate_result ->> 'confidence' = 'high'
and (candidate_result ->> 'canApply')::boolean is true
and candidate_result #>> '{winningSegment,representativeTime}' = to_char(p_time, 'HH24:MI')
and (
(
turn_state #>> '{nextAction,kind}' = 'request_candidate_confirmation'
and turn_state #>> '{nextAction,resultId}' = p_result_id::text
)
or turn_state is null
or turn_state = '{}'::jsonb
);
if not found then raise exception 'invalid_guided_candidate_turn'; end if;
update public.profiles
set active_birth_time = p_time, birth_time = p_time, birth_time_status = 'confirmed'
where id = p_user_id and rectification_case_id = p_case_id;
if not found then raise exception 'birth_time_profile_not_found'; end if;
end;
$$;
revoke all on function public.save_guided_birth_time_candidate(uuid, uuid, uuid, uuid, integer, jsonb)
from public, anon, authenticated;
grant execute on function public.save_guided_birth_time_candidate(uuid, uuid, uuid, uuid, integer, jsonb)
to service_role;
revoke all on function public.confirm_guided_birth_time_candidate(uuid, uuid, uuid, time without time zone, uuid, integer, jsonb, jsonb)
from public, anon, authenticated;
grant execute on function public.confirm_guided_birth_time_candidate(uuid, uuid, uuid, time without time zone, uuid, integer, jsonb, jsonb)
to service_role;
commit;