From 09351957def9aa1c8ef3bbe97a890a76cffed39c Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:44:45 +0000 Subject: [PATCH] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/integrations/supabase/types.ts | 201 ++++++++++++++++++ ...0_788dad00-10b3-4523-b2e9-abaa72dec456.sql | 112 ++++++++++ 2 files changed, 313 insertions(+) create mode 100644 supabase/migrations/20260417024440_788dad00-10b3-4523-b2e9-abaa72dec456.sql diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index c1c5e05..1638011 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -14,6 +14,88 @@ export type Database = { } public: { Tables: { + call_logs: { + Row: { + billable: boolean + call_date: string + caller_name: string | null + caller_phone: string | null + case_id: string + contact_id: string | null + created_at: string + created_by: string | null + direction: string + duration_minutes: number | null + follow_up_date: string | null + follow_up_required: boolean + homeowner_id: string | null + id: string + notes: string | null + subject: string + updated_at: string + } + Insert: { + billable?: boolean + call_date?: string + caller_name?: string | null + caller_phone?: string | null + case_id: string + contact_id?: string | null + created_at?: string + created_by?: string | null + direction?: string + duration_minutes?: number | null + follow_up_date?: string | null + follow_up_required?: boolean + homeowner_id?: string | null + id?: string + notes?: string | null + subject?: string + updated_at?: string + } + Update: { + billable?: boolean + call_date?: string + caller_name?: string | null + caller_phone?: string | null + case_id?: string + contact_id?: string | null + created_at?: string + created_by?: string | null + direction?: string + duration_minutes?: number | null + follow_up_date?: string | null + follow_up_required?: boolean + homeowner_id?: string | null + id?: string + notes?: string | null + subject?: string + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "call_logs_case_id_fkey" + columns: ["case_id"] + isOneToOne: false + referencedRelation: "cases" + referencedColumns: ["id"] + }, + { + foreignKeyName: "call_logs_contact_id_fkey" + columns: ["contact_id"] + isOneToOne: false + referencedRelation: "contacts" + referencedColumns: ["id"] + }, + { + foreignKeyName: "call_logs_homeowner_id_fkey" + columns: ["homeowner_id"] + isOneToOne: false + referencedRelation: "homeowners" + referencedColumns: ["id"] + }, + ] + } case_contacts: { Row: { case_id: string @@ -1435,6 +1517,125 @@ export type Database = { }, ] } + payment_plan_installments: { + Row: { + amount: number + created_at: string + due_date: string + id: string + ledger_entry_id: string | null + notes: string | null + paid: boolean + paid_amount: number | null + paid_on: string | null + plan_id: string + sort_order: number + updated_at: string + } + Insert: { + amount?: number + created_at?: string + due_date: string + id?: string + ledger_entry_id?: string | null + notes?: string | null + paid?: boolean + paid_amount?: number | null + paid_on?: string | null + plan_id: string + sort_order?: number + updated_at?: string + } + Update: { + amount?: number + created_at?: string + due_date?: string + id?: string + ledger_entry_id?: string | null + notes?: string | null + paid?: boolean + paid_amount?: number | null + paid_on?: string | null + plan_id?: string + sort_order?: number + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "payment_plan_installments_ledger_entry_id_fkey" + columns: ["ledger_entry_id"] + isOneToOne: false + referencedRelation: "collection_ledger_entries" + referencedColumns: ["id"] + }, + { + foreignKeyName: "payment_plan_installments_plan_id_fkey" + columns: ["plan_id"] + isOneToOne: false + referencedRelation: "payment_plans" + referencedColumns: ["id"] + }, + ] + } + payment_plans: { + Row: { + collection_id: string + created_at: string + created_by: string | null + down_payment: number + frequency: string + id: string + installment_amount: number + installment_count: number + name: string | null + notes: string | null + start_date: string + status: string + total_amount: number + updated_at: string + } + Insert: { + collection_id: string + created_at?: string + created_by?: string | null + down_payment?: number + frequency?: string + id?: string + installment_amount?: number + installment_count?: number + name?: string | null + notes?: string | null + start_date?: string + status?: string + total_amount?: number + updated_at?: string + } + Update: { + collection_id?: string + created_at?: string + created_by?: string | null + down_payment?: number + frequency?: string + id?: string + installment_amount?: number + installment_count?: number + name?: string | null + notes?: string | null + start_date?: string + status?: string + total_amount?: number + updated_at?: string + } + Relationships: [ + { + foreignKeyName: "payment_plans_collection_id_fkey" + columns: ["collection_id"] + isOneToOne: false + referencedRelation: "collections" + referencedColumns: ["id"] + }, + ] + } profiles: { Row: { created_at: string diff --git a/supabase/migrations/20260417024440_788dad00-10b3-4523-b2e9-abaa72dec456.sql b/supabase/migrations/20260417024440_788dad00-10b3-4523-b2e9-abaa72dec456.sql new file mode 100644 index 0000000..8cd2ba4 --- /dev/null +++ b/supabase/migrations/20260417024440_788dad00-10b3-4523-b2e9-abaa72dec456.sql @@ -0,0 +1,112 @@ +-- Payment Plans (attached to a collection) +CREATE TABLE public.payment_plans ( + id uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY, + collection_id uuid NOT NULL REFERENCES public.collections(id) ON DELETE CASCADE, + name text, + status text NOT NULL DEFAULT 'active', -- active, completed, defaulted, cancelled + total_amount numeric NOT NULL DEFAULT 0, + down_payment numeric NOT NULL DEFAULT 0, + installment_count integer NOT NULL DEFAULT 1, + installment_amount numeric NOT NULL DEFAULT 0, + frequency text NOT NULL DEFAULT 'monthly', -- weekly, biweekly, monthly + start_date date NOT NULL DEFAULT CURRENT_DATE, + notes text, + created_by uuid, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now() +); + +CREATE INDEX idx_payment_plans_collection ON public.payment_plans(collection_id); + +ALTER TABLE public.payment_plans ENABLE ROW LEVEL SECURITY; + +CREATE POLICY pp_select ON public.payment_plans FOR SELECT TO authenticated +USING (EXISTS (SELECT 1 FROM public.collections c WHERE c.id = collection_id AND public.can_access_case(c.case_id, auth.uid()))); + +CREATE POLICY pp_insert ON public.payment_plans FOR INSERT TO authenticated +WITH CHECK (EXISTS (SELECT 1 FROM public.collections c WHERE c.id = collection_id AND public.can_access_case(c.case_id, auth.uid()))); + +CREATE POLICY pp_update ON public.payment_plans FOR UPDATE TO authenticated +USING (EXISTS (SELECT 1 FROM public.collections c WHERE c.id = collection_id AND public.can_access_case(c.case_id, auth.uid()))); + +CREATE POLICY pp_delete ON public.payment_plans FOR DELETE TO authenticated +USING (EXISTS (SELECT 1 FROM public.collections c WHERE c.id = collection_id AND public.can_access_case(c.case_id, auth.uid()))); + +CREATE TRIGGER trg_pp_updated BEFORE UPDATE ON public.payment_plans + FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at(); + +-- Installments (schedule items; manually marked paid) +CREATE TABLE public.payment_plan_installments ( + id uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY, + plan_id uuid NOT NULL REFERENCES public.payment_plans(id) ON DELETE CASCADE, + sort_order integer NOT NULL DEFAULT 0, + due_date date NOT NULL, + amount numeric NOT NULL DEFAULT 0, + paid boolean NOT NULL DEFAULT false, + paid_on date, + paid_amount numeric, + ledger_entry_id uuid REFERENCES public.collection_ledger_entries(id) ON DELETE SET NULL, + notes text, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now() +); + +CREATE INDEX idx_ppi_plan ON public.payment_plan_installments(plan_id); + +ALTER TABLE public.payment_plan_installments ENABLE ROW LEVEL SECURITY; + +CREATE POLICY ppi_select ON public.payment_plan_installments FOR SELECT TO authenticated +USING (EXISTS (SELECT 1 FROM public.payment_plans p JOIN public.collections c ON c.id = p.collection_id WHERE p.id = plan_id AND public.can_access_case(c.case_id, auth.uid()))); + +CREATE POLICY ppi_insert ON public.payment_plan_installments FOR INSERT TO authenticated +WITH CHECK (EXISTS (SELECT 1 FROM public.payment_plans p JOIN public.collections c ON c.id = p.collection_id WHERE p.id = plan_id AND public.can_access_case(c.case_id, auth.uid()))); + +CREATE POLICY ppi_update ON public.payment_plan_installments FOR UPDATE TO authenticated +USING (EXISTS (SELECT 1 FROM public.payment_plans p JOIN public.collections c ON c.id = p.collection_id WHERE p.id = plan_id AND public.can_access_case(c.case_id, auth.uid()))); + +CREATE POLICY ppi_delete ON public.payment_plan_installments FOR DELETE TO authenticated +USING (EXISTS (SELECT 1 FROM public.payment_plans p JOIN public.collections c ON c.id = p.collection_id WHERE p.id = plan_id AND public.can_access_case(c.case_id, auth.uid()))); + +CREATE TRIGGER trg_ppi_updated BEFORE UPDATE ON public.payment_plan_installments + FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at(); + +-- Call Logs (attached to a case; optionally to a contact/homeowner) +CREATE TABLE public.call_logs ( + id uuid NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY, + case_id uuid NOT NULL REFERENCES public.cases(id) ON DELETE CASCADE, + contact_id uuid REFERENCES public.contacts(id) ON DELETE SET NULL, + homeowner_id uuid REFERENCES public.homeowners(id) ON DELETE SET NULL, + call_date timestamptz NOT NULL DEFAULT now(), + direction text NOT NULL DEFAULT 'outbound', -- inbound, outbound + duration_minutes integer, + caller_name text, + caller_phone text, + subject text NOT NULL DEFAULT '', + notes text, + follow_up_required boolean NOT NULL DEFAULT false, + follow_up_date date, + billable boolean NOT NULL DEFAULT false, + created_by uuid, + created_at timestamptz NOT NULL DEFAULT now(), + updated_at timestamptz NOT NULL DEFAULT now() +); + +CREATE INDEX idx_call_logs_case ON public.call_logs(case_id); +CREATE INDEX idx_call_logs_date ON public.call_logs(call_date DESC); + +ALTER TABLE public.call_logs ENABLE ROW LEVEL SECURITY; + +CREATE POLICY cl_select ON public.call_logs FOR SELECT TO authenticated +USING (public.can_access_case(case_id, auth.uid())); + +CREATE POLICY cl_insert ON public.call_logs FOR INSERT TO authenticated +WITH CHECK (public.can_access_case(case_id, auth.uid())); + +CREATE POLICY cl_update ON public.call_logs FOR UPDATE TO authenticated +USING (public.can_access_case(case_id, auth.uid()) AND (created_by = auth.uid() OR public.is_admin(auth.uid()))); + +CREATE POLICY cl_delete ON public.call_logs FOR DELETE TO authenticated +USING (public.can_access_case(case_id, auth.uid()) AND (created_by = auth.uid() OR public.is_admin(auth.uid()))); + +CREATE TRIGGER trg_call_logs_updated BEFORE UPDATE ON public.call_logs + FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at(); \ No newline at end of file