Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-17 02:44:45 +00:00
co-authored by renee-png
parent 45fc461927
commit 09351957de
2 changed files with 313 additions and 0 deletions
@@ -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();