diff --git a/supabase/migrations/20260607180000_backfill_imported_bill_approvers.sql b/supabase/migrations/20260607180000_backfill_imported_bill_approvers.sql new file mode 100644 index 0000000..11331cc --- /dev/null +++ b/supabase/migrations/20260607180000_backfill_imported_bill_approvers.sql @@ -0,0 +1,62 @@ +-- Bills that arrive already 'approved'/'paid' (Buildium imports, bulk loads, +-- direct entry) never get routed through the in-app approval flow, so they have +-- no bill_approvals row and the Approvers column shows nothing. Per product +-- decision, give them a synthetic approver so the column is never blank. +-- +-- Label: system imports (created_by null) -> 'Imported'; in-app entries -> +-- the creator's name, falling back to 'Direct entry'. + +-- 1) Future imports: auto-create an approver row when a bill is inserted already +-- in an approved/paid state with no approver. Bills inserted as 'pending' +-- (the normal approval flow) are untouched. +create or replace function public.autocreate_imported_bill_approver() +returns trigger +language plpgsql +security definer +set search_path to 'public' +as $$ +declare + v_name text; +begin + if NEW.status in ('approved','paid') + and not exists (select 1 from public.bill_approvals ba where ba.bill_id = NEW.id) then + if NEW.created_by is null then + v_name := 'Imported'; + else + select coalesce(nullif(btrim(p.full_name), ''), 'Direct entry') + into v_name + from public.profiles p + where p.id = NEW.created_by; + v_name := coalesce(v_name, 'Direct entry'); + end if; + + insert into public.bill_approvals + (bill_id, association_id, approver_name, amount, status, approved_date, created_by) + values + (NEW.id, NEW.association_id, v_name, coalesce(NEW.amount, 0), 'approved', + coalesce(NEW.approved_date, NEW.paid_date, NEW.bill_date, current_date), NEW.created_by); + end if; + return NEW; +end; +$$; + +drop trigger if exists trg_bills_autocreate_imported_approver on public.bills; +create trigger trg_bills_autocreate_imported_approver + after insert on public.bills + for each row execute function public.autocreate_imported_bill_approver(); + +-- 2) Backfill existing approved/paid bills that have no approver row. +insert into public.bill_approvals + (bill_id, association_id, approver_name, amount, status, approved_date, created_by) +select b.id, + b.association_id, + case when b.created_by is null then 'Imported' + else coalesce(nullif(btrim(p.full_name), ''), 'Direct entry') end, + coalesce(b.amount, 0), + 'approved', + coalesce(b.approved_date, b.paid_date, b.bill_date, current_date), + b.created_by +from public.bills b +left join public.profiles p on p.id = b.created_by +where b.status in ('approved','paid') + and not exists (select 1 from public.bill_approvals ba where ba.bill_id = b.id);