Assessment groups can now define billing frequency (monthly, quarterly, annual) with configurable due months and due day. Invoice generation respects each group's schedule - only generating invoices when the selected month is a billing month for that group. Adds a generation preview showing which groups will be billed, period tracking on invoices, and billing period context in the payments UI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
58 lines
2.0 KiB
SQL
58 lines
2.0 KiB
SQL
-- Migration 011: Add billing frequency support to invoices
|
|
-- Adds due_months and due_day to assessment_groups
|
|
-- Adds period_start, period_end, assessment_group_id to invoices
|
|
|
|
DO $$
|
|
DECLARE
|
|
v_schema TEXT;
|
|
BEGIN
|
|
FOR v_schema IN
|
|
SELECT schema_name FROM information_schema.schemata
|
|
WHERE schema_name LIKE 'tenant_%'
|
|
LOOP
|
|
-- Add due_months and due_day to assessment_groups
|
|
EXECUTE format('
|
|
ALTER TABLE %I.assessment_groups
|
|
ADD COLUMN IF NOT EXISTS due_months INTEGER[] DEFAULT ''{1,2,3,4,5,6,7,8,9,10,11,12}'',
|
|
ADD COLUMN IF NOT EXISTS due_day INTEGER DEFAULT 1
|
|
', v_schema);
|
|
|
|
-- Add period tracking and assessment group link to invoices
|
|
EXECUTE format('
|
|
ALTER TABLE %I.invoices
|
|
ADD COLUMN IF NOT EXISTS period_start DATE,
|
|
ADD COLUMN IF NOT EXISTS period_end DATE,
|
|
ADD COLUMN IF NOT EXISTS assessment_group_id UUID
|
|
', v_schema);
|
|
|
|
-- Backfill due_months based on existing frequency values
|
|
EXECUTE format('
|
|
UPDATE %I.assessment_groups
|
|
SET due_months = CASE frequency
|
|
WHEN ''quarterly'' THEN ''{1,4,7,10}''::INTEGER[]
|
|
WHEN ''annual'' THEN ''{1}''::INTEGER[]
|
|
ELSE ''{1,2,3,4,5,6,7,8,9,10,11,12}''::INTEGER[]
|
|
END
|
|
WHERE due_months IS NULL OR due_months = ''{1,2,3,4,5,6,7,8,9,10,11,12}''
|
|
AND frequency != ''monthly''
|
|
', v_schema);
|
|
|
|
-- Backfill period_start/period_end for existing invoices (all monthly)
|
|
EXECUTE format('
|
|
UPDATE %I.invoices
|
|
SET period_start = invoice_date,
|
|
period_end = (invoice_date + INTERVAL ''1 month'' - INTERVAL ''1 day'')::DATE
|
|
WHERE period_start IS NULL AND invoice_type = ''regular_assessment''
|
|
', v_schema);
|
|
|
|
-- Backfill assessment_group_id on existing invoices from units
|
|
EXECUTE format('
|
|
UPDATE %I.invoices i
|
|
SET assessment_group_id = u.assessment_group_id
|
|
FROM %I.units u
|
|
WHERE i.unit_id = u.id AND i.assessment_group_id IS NULL
|
|
', v_schema, v_schema);
|
|
|
|
END LOOP;
|
|
END $$;
|