-- Migration 013: Board Planning tables (scenarios, investments, assessments) -- Applies to all existing tenant schemas DO $$ DECLARE tenant_schema TEXT; BEGIN FOR tenant_schema IN SELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE 'tenant_%' LOOP -- Board Scenarios EXECUTE format(' CREATE TABLE IF NOT EXISTS %I.board_scenarios ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(255) NOT NULL, description TEXT, scenario_type VARCHAR(30) NOT NULL CHECK (scenario_type IN (''investment'', ''assessment'')), status VARCHAR(20) DEFAULT ''draft'' CHECK (status IN (''draft'', ''active'', ''approved'', ''archived'')), projection_months INTEGER DEFAULT 36, projection_cache JSONB, projection_cached_at TIMESTAMPTZ, created_by UUID NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() )', tenant_schema); -- Scenario Investments EXECUTE format(' CREATE TABLE IF NOT EXISTS %I.scenario_investments ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), scenario_id UUID NOT NULL REFERENCES %I.board_scenarios(id) ON DELETE CASCADE, source_recommendation_id UUID, label VARCHAR(255) NOT NULL, investment_type VARCHAR(50) CHECK (investment_type IN (''cd'', ''money_market'', ''treasury'', ''savings'', ''other'')), fund_type VARCHAR(20) NOT NULL CHECK (fund_type IN (''operating'', ''reserve'')), principal DECIMAL(15,2) NOT NULL, interest_rate DECIMAL(6,4), term_months INTEGER, institution VARCHAR(255), purchase_date DATE, maturity_date DATE, auto_renew BOOLEAN DEFAULT FALSE, executed_investment_id UUID, notes TEXT, sort_order INTEGER DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() )', tenant_schema, tenant_schema); -- Scenario Assessments EXECUTE format(' CREATE TABLE IF NOT EXISTS %I.scenario_assessments ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), scenario_id UUID NOT NULL REFERENCES %I.board_scenarios(id) ON DELETE CASCADE, change_type VARCHAR(30) NOT NULL CHECK (change_type IN (''dues_increase'', ''special_assessment'', ''dues_decrease'')), label VARCHAR(255) NOT NULL, target_fund VARCHAR(20) CHECK (target_fund IN (''operating'', ''reserve'', ''both'')), percentage_change DECIMAL(6,3), flat_amount_change DECIMAL(10,2), special_total DECIMAL(15,2), special_per_unit DECIMAL(10,2), special_installments INTEGER DEFAULT 1, effective_date DATE NOT NULL, end_date DATE, applies_to_group_id UUID, notes TEXT, sort_order INTEGER DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() )', tenant_schema, tenant_schema); -- Indexes EXECUTE format('CREATE INDEX IF NOT EXISTS idx_%s_bs_type_status ON %I.board_scenarios(scenario_type, status)', replace(tenant_schema, '.', '_'), tenant_schema); EXECUTE format('CREATE INDEX IF NOT EXISTS idx_%s_si_scenario ON %I.scenario_investments(scenario_id)', replace(tenant_schema, '.', '_'), tenant_schema); EXECUTE format('CREATE INDEX IF NOT EXISTS idx_%s_sa_scenario ON %I.scenario_assessments(scenario_id)', replace(tenant_schema, '.', '_'), tenant_schema); RAISE NOTICE 'Board planning tables created for schema: %', tenant_schema; END LOOP; END $$;