diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index 15aaa8e..0d23437 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -486,6 +486,54 @@ export type Database = { }, ] } + client_fee_overrides: { + Row: { + amount: number + client_id: string + created_at: string + created_by: string | null + enabled: boolean + fee_item_id: string + id: string + updated_at: string + } + Insert: { + amount?: number + client_id: string + created_at?: string + created_by?: string | null + enabled?: boolean + fee_item_id: string + id?: string + updated_at?: string + } + Update: { + amount?: number + client_id?: string + created_at?: string + created_by?: string | null + enabled?: boolean + fee_item_id?: string + id?: string + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "client_fee_overrides_client_id_fkey" + columns: ["client_id"] + isOneToOne: false + referencedRelation: "clients" + referencedColumns: ["id"] + }, + { + foreignKeyName: "client_fee_overrides_fee_item_id_fkey" + columns: ["fee_item_id"] + isOneToOne: false + referencedRelation: "fee_schedule_items" + referencedColumns: ["id"] + }, + ] + } client_field_values: { Row: { client_id: string diff --git a/supabase/migrations/20260422175027_614d39b8-c491-4ed9-92ba-5d1eb13c549f.sql b/supabase/migrations/20260422175027_614d39b8-c491-4ed9-92ba-5d1eb13c549f.sql new file mode 100644 index 0000000..68eec19 --- /dev/null +++ b/supabase/migrations/20260422175027_614d39b8-c491-4ed9-92ba-5d1eb13c549f.sql @@ -0,0 +1,50 @@ +-- Per-client overrides for fee schedule expense items +CREATE TABLE public.client_fee_overrides ( + id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY, + client_id UUID NOT NULL REFERENCES public.clients(id) ON DELETE CASCADE, + fee_item_id UUID NOT NULL REFERENCES public.fee_schedule_items(id) ON DELETE CASCADE, + amount NUMERIC NOT NULL DEFAULT 0, + enabled BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), + created_by UUID, + UNIQUE (client_id, fee_item_id) +); + +CREATE INDEX idx_client_fee_overrides_client ON public.client_fee_overrides(client_id); + +ALTER TABLE public.client_fee_overrides ENABLE ROW LEVEL SECURITY; + +CREATE POLICY "cfo_select_auth" ON public.client_fee_overrides + FOR SELECT TO authenticated USING (true); + +CREATE POLICY "cfo_insert_auth" ON public.client_fee_overrides + FOR INSERT TO authenticated + WITH CHECK ( + is_admin(auth.uid()) OR EXISTS ( + SELECT 1 FROM public.clients c + WHERE c.id = client_fee_overrides.client_id AND c.created_by = auth.uid() + ) + ); + +CREATE POLICY "cfo_update_auth" ON public.client_fee_overrides + FOR UPDATE TO authenticated + USING ( + is_admin(auth.uid()) OR EXISTS ( + SELECT 1 FROM public.clients c + WHERE c.id = client_fee_overrides.client_id AND c.created_by = auth.uid() + ) + ); + +CREATE POLICY "cfo_delete_auth" ON public.client_fee_overrides + FOR DELETE TO authenticated + USING ( + is_admin(auth.uid()) OR EXISTS ( + SELECT 1 FROM public.clients c + WHERE c.id = client_fee_overrides.client_id AND c.created_by = auth.uid() + ) + ); + +CREATE TRIGGER trg_cfo_updated_at + BEFORE UPDATE ON public.client_fee_overrides + FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at(); \ No newline at end of file