diff --git a/supabase/migrations/20260807002000_reporting_view_fixes.sql b/supabase/migrations/20260807002000_reporting_view_fixes.sql index 297fd65..404f784 100644 --- a/supabase/migrations/20260807002000_reporting_view_fixes.sql +++ b/supabase/migrations/20260807002000_reporting_view_fixes.sql @@ -23,6 +23,22 @@ $$; GRANT EXECUTE ON FUNCTION public.is_service_context() TO authenticated; +-- ============================================================================ +-- 1. A billing administrator could not read their own receivables report +-- ============================================================================ +-- +-- v_billing_detail joined public.students purely to build a display name, but +-- can_access_student() admits org admins, auditors, parents, a student's own +-- teacher and campus staff — and NOT billing admins, even though the invoices +-- policy grants them every invoice in the organisation. The inner join then +-- dropped every row, so the receivables report came back empty for exactly the +-- role that exists to run it, with no error to explain why. +-- +-- The tempting fix is to add is_billing_admin() to can_access_student(). That +-- would also hand finance staff allergies, chronic_conditions, special_needs, +-- disciplinary_history, custody_agreement and primary_physician, which they +-- have no business reading. So the name is resolved on its own instead, and +-- student row access is left exactly as it was. CREATE OR REPLACE FUNCTION public.student_display_name(_student UUID) RETURNS TEXT LANGUAGE sql STABLE SECURITY DEFINER SET search_path = public AS $$