mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
183fe0a93c
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
115 lines
5.6 KiB
SQL
115 lines
5.6 KiB
SQL
|
|
-- Zoho account mappings (local COA -> Zoho account)
|
|
CREATE TABLE public.zoho_account_mappings (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE,
|
|
chart_of_account_id UUID NOT NULL REFERENCES public.chart_of_accounts(id) ON DELETE CASCADE,
|
|
zoho_account_id TEXT NOT NULL,
|
|
zoho_account_name TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE(association_id, chart_of_account_id)
|
|
);
|
|
|
|
ALTER TABLE public.zoho_account_mappings ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Staff full access on zoho_account_mappings"
|
|
ON public.zoho_account_mappings FOR ALL TO authenticated
|
|
USING (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role))
|
|
WITH CHECK (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role));
|
|
|
|
-- Zoho customer mappings (owner/unit -> Zoho customer)
|
|
CREATE TABLE public.zoho_customer_mappings (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE,
|
|
owner_id UUID REFERENCES public.owners(id) ON DELETE CASCADE,
|
|
unit_id UUID REFERENCES public.units(id) ON DELETE CASCADE,
|
|
zoho_customer_id TEXT NOT NULL,
|
|
zoho_customer_name TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE(association_id, owner_id)
|
|
);
|
|
|
|
ALTER TABLE public.zoho_customer_mappings ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Staff full access on zoho_customer_mappings"
|
|
ON public.zoho_customer_mappings FOR ALL TO authenticated
|
|
USING (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role))
|
|
WITH CHECK (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role));
|
|
|
|
-- Zoho sync settings per association (toggle which entry types sync)
|
|
CREATE TABLE public.zoho_sync_settings (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE UNIQUE,
|
|
sync_invoices BOOLEAN NOT NULL DEFAULT true,
|
|
sync_payments BOOLEAN NOT NULL DEFAULT true,
|
|
sync_contacts BOOLEAN NOT NULL DEFAULT true,
|
|
sync_bills BOOLEAN NOT NULL DEFAULT false,
|
|
sync_journal_entries BOOLEAN NOT NULL DEFAULT false,
|
|
auto_sync_enabled BOOLEAN NOT NULL DEFAULT true,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE public.zoho_sync_settings ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Staff full access on zoho_sync_settings"
|
|
ON public.zoho_sync_settings FOR ALL TO authenticated
|
|
USING (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role))
|
|
WITH CHECK (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role));
|
|
|
|
-- Zoho sync log for tracking sync history and errors
|
|
CREATE TABLE public.zoho_sync_log (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE,
|
|
sync_type TEXT NOT NULL, -- 'invoice', 'payment', 'contact', 'bill', etc.
|
|
direction TEXT NOT NULL DEFAULT 'push', -- 'push' or 'pull'
|
|
status TEXT NOT NULL DEFAULT 'success', -- 'success', 'error', 'partial'
|
|
record_count INTEGER DEFAULT 0,
|
|
error_message TEXT,
|
|
details JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE public.zoho_sync_log ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Staff full access on zoho_sync_log"
|
|
ON public.zoho_sync_log FOR ALL TO authenticated
|
|
USING (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role))
|
|
WITH CHECK (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role));
|
|
|
|
-- Association fee rules (interest & late fee configuration per association)
|
|
CREATE TABLE public.association_fee_rules (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
association_id UUID NOT NULL REFERENCES public.associations(id) ON DELETE CASCADE UNIQUE,
|
|
-- Interest settings
|
|
interest_enabled BOOLEAN NOT NULL DEFAULT false,
|
|
interest_rate NUMERIC NOT NULL DEFAULT 0, -- APR percentage e.g. 18.0
|
|
interest_grace_days INTEGER NOT NULL DEFAULT 30,
|
|
interest_compound TEXT NOT NULL DEFAULT 'monthly', -- 'monthly', 'daily', 'quarterly'
|
|
interest_apply_to TEXT NOT NULL DEFAULT 'assessments', -- 'assessments', 'all_charges', 'assessments_and_fees'
|
|
-- Late fee settings
|
|
late_fee_enabled BOOLEAN NOT NULL DEFAULT false,
|
|
late_fee_type TEXT NOT NULL DEFAULT 'flat', -- 'flat' or 'percentage'
|
|
late_fee_amount NUMERIC NOT NULL DEFAULT 0, -- dollar amount or percentage
|
|
late_fee_trigger_days INTEGER NOT NULL DEFAULT 15, -- days past due before late fee applies
|
|
late_fee_max NUMERIC, -- optional max cap for percentage-based fees
|
|
late_fee_recurring BOOLEAN NOT NULL DEFAULT false, -- apply every month?
|
|
-- Schedule
|
|
auto_apply_enabled BOOLEAN NOT NULL DEFAULT false,
|
|
auto_apply_schedule TEXT NOT NULL DEFAULT 'monthly', -- 'monthly', 'quarterly'
|
|
auto_apply_day INTEGER NOT NULL DEFAULT 1, -- day of month
|
|
-- Push to Zoho
|
|
push_to_zoho BOOLEAN NOT NULL DEFAULT true,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
ALTER TABLE public.association_fee_rules ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY "Staff full access on association_fee_rules"
|
|
ON public.association_fee_rules FOR ALL TO authenticated
|
|
USING (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role))
|
|
WITH CHECK (has_role(auth.uid(), 'admin'::app_role) OR has_role(auth.uid(), 'manager'::app_role));
|