diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index 1d0485f..c990442 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -1561,6 +1561,7 @@ export type Database = { due_date: string | null id: string invoice_number: string + is_retainer: boolean issue_date: string notes: string | null paid_at: string | null @@ -1579,6 +1580,7 @@ export type Database = { due_date?: string | null id?: string invoice_number: string + is_retainer?: boolean issue_date?: string notes?: string | null paid_at?: string | null @@ -1597,6 +1599,7 @@ export type Database = { due_date?: string | null id?: string invoice_number?: string + is_retainer?: boolean issue_date?: string notes?: string | null paid_at?: string | null @@ -2287,6 +2290,90 @@ export type Database = { }, ] } + trust_ledger_entries: { + Row: { + amount: number + applied_invoice_id: string | null + applied_payment_id: string | null + client_id: string + created_at: string + created_by: string | null + entry_date: string + entry_type: string + id: string + note: string | null + source_invoice_id: string | null + source_payment_id: string | null + updated_at: string + } + Insert: { + amount: number + applied_invoice_id?: string | null + applied_payment_id?: string | null + client_id: string + created_at?: string + created_by?: string | null + entry_date?: string + entry_type: string + id?: string + note?: string | null + source_invoice_id?: string | null + source_payment_id?: string | null + updated_at?: string + } + Update: { + amount?: number + applied_invoice_id?: string | null + applied_payment_id?: string | null + client_id?: string + created_at?: string + created_by?: string | null + entry_date?: string + entry_type?: string + id?: string + note?: string | null + source_invoice_id?: string | null + source_payment_id?: string | null + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "trust_ledger_entries_applied_invoice_id_fkey" + columns: ["applied_invoice_id"] + isOneToOne: false + referencedRelation: "invoices" + referencedColumns: ["id"] + }, + { + foreignKeyName: "trust_ledger_entries_applied_payment_id_fkey" + columns: ["applied_payment_id"] + isOneToOne: false + referencedRelation: "invoice_payments" + referencedColumns: ["id"] + }, + { + foreignKeyName: "trust_ledger_entries_client_id_fkey" + columns: ["client_id"] + isOneToOne: false + referencedRelation: "clients" + referencedColumns: ["id"] + }, + { + foreignKeyName: "trust_ledger_entries_source_invoice_id_fkey" + columns: ["source_invoice_id"] + isOneToOne: false + referencedRelation: "invoices" + referencedColumns: ["id"] + }, + { + foreignKeyName: "trust_ledger_entries_source_payment_id_fkey" + columns: ["source_payment_id"] + isOneToOne: false + referencedRelation: "invoice_payments" + referencedColumns: ["id"] + }, + ] + } user_roles: { Row: { created_at: string diff --git a/supabase/migrations/20260418010645_2ca5538f-221c-439d-8f12-54b0ce082083.sql b/supabase/migrations/20260418010645_2ca5538f-221c-439d-8f12-54b0ce082083.sql new file mode 100644 index 0000000..eee168b --- /dev/null +++ b/supabase/migrations/20260418010645_2ca5538f-221c-439d-8f12-54b0ce082083.sql @@ -0,0 +1,64 @@ + +ALTER TABLE public.invoices ADD COLUMN IF NOT EXISTS is_retainer boolean NOT NULL DEFAULT false; + +CREATE TABLE IF NOT EXISTS public.trust_ledger_entries ( + id uuid PRIMARY KEY DEFAULT gen_random_uuid(), + client_id uuid NOT NULL REFERENCES public.clients(id) ON DELETE CASCADE, + entry_date date NOT NULL DEFAULT CURRENT_DATE, + entry_type text NOT NULL CHECK (entry_type IN ('deposit', 'withdrawal')), + amount numeric NOT NULL CHECK (amount >= 0), + note text, + source_invoice_id uuid REFERENCES public.invoices(id) ON DELETE SET NULL, + applied_invoice_id uuid REFERENCES public.invoices(id) ON DELETE SET NULL, + source_payment_id uuid REFERENCES public.invoice_payments(id) ON DELETE SET NULL, + applied_payment_id uuid REFERENCES public.invoice_payments(id) ON DELETE SET NULL, + created_by uuid, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now() +); + +CREATE INDEX IF NOT EXISTS trust_ledger_client_idx ON public.trust_ledger_entries(client_id, entry_date DESC); + +ALTER TABLE public.trust_ledger_entries ENABLE ROW LEVEL SECURITY; + +CREATE POLICY trust_ledger_select ON public.trust_ledger_entries + FOR SELECT TO authenticated USING (true); + +CREATE POLICY trust_ledger_insert ON public.trust_ledger_entries + FOR INSERT TO authenticated WITH CHECK (auth.uid() IS NOT NULL); + +CREATE POLICY trust_ledger_delete ON public.trust_ledger_entries + FOR DELETE TO authenticated USING (public.is_admin(auth.uid()) OR created_by = auth.uid()); + +CREATE TRIGGER trust_ledger_set_updated_at + BEFORE UPDATE ON public.trust_ledger_entries + FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at(); + +CREATE OR REPLACE FUNCTION public.tg_trust_deposit_from_payment() +RETURNS trigger +LANGUAGE plpgsql +SECURITY DEFINER +SET search_path = public +AS $$ +DECLARE + v_client_id uuid; + v_is_retainer boolean; +BEGIN + SELECT i.client_id, i.is_retainer INTO v_client_id, v_is_retainer + FROM public.invoices i WHERE i.id = NEW.invoice_id; + + IF v_is_retainer IS TRUE AND v_client_id IS NOT NULL AND NEW.amount > 0 THEN + INSERT INTO public.trust_ledger_entries + (client_id, entry_date, entry_type, amount, note, source_invoice_id, source_payment_id, created_by) + VALUES + (v_client_id, NEW.paid_on, 'deposit', NEW.amount, + 'Retainer payment', NEW.invoice_id, NEW.id, NEW.created_by); + END IF; + RETURN NEW; +END; +$$; + +DROP TRIGGER IF EXISTS trust_deposit_from_payment ON public.invoice_payments; +CREATE TRIGGER trust_deposit_from_payment + AFTER INSERT ON public.invoice_payments + FOR EACH ROW EXECUTE FUNCTION public.tg_trust_deposit_from_payment();