-- Migration 103: Fixed-Price Reporting Views -- Pre-aggregated views for dashboard and reporting performance -- Agreement performance aggregation CREATE OR REPLACE VIEW fixed_price_agreement_performance AS SELECT a.id, a.agreement_number, a.customer_id, a.customer_name, a.status, a.monthly_hours, a.hourly_rate, a.overtime_rate, a.internal_cost_rate, -- Period counts COUNT(DISTINCT bp.id) as total_periods, COUNT(DISTINCT bp.id) FILTER (WHERE bp.status = 'billed') as billed_periods, -- Hour aggregations COALESCE(SUM(bp.included_hours), 0) as total_included_hours, COALESCE(SUM(bp.used_hours), 0) as total_used_hours, COALESCE(SUM(bp.overtime_hours) FILTER (WHERE bp.overtime_approved), 0) as total_approved_overtime, -- Revenue (only billed periods) COALESCE(SUM(bp.base_amount) FILTER (WHERE bp.status = 'billed'), 0) as total_base_revenue, COALESCE(SUM(bp.overtime_amount) FILTER (WHERE bp.status = 'billed' AND bp.overtime_approved), 0) as total_overtime_revenue, COALESCE( SUM(bp.base_amount) FILTER (WHERE bp.status = 'billed') + SUM(bp.overtime_amount) FILTER (WHERE bp.status = 'billed' AND bp.overtime_approved), 0 ) as total_revenue, -- Cost calculation COALESCE(SUM(bp.used_hours) * a.internal_cost_rate, 0) as total_internal_cost, -- Profit COALESCE( SUM(bp.base_amount) FILTER (WHERE bp.status = 'billed') + SUM(bp.overtime_amount) FILTER (WHERE bp.status = 'billed' AND bp.overtime_approved) - SUM(bp.used_hours) * a.internal_cost_rate, 0 ) as total_profit, -- Utilization (used hours / included hours) CASE WHEN SUM(bp.included_hours) > 0 THEN ROUND((SUM(bp.used_hours) / SUM(bp.included_hours) * 100)::numeric, 1) ELSE 0 END as utilization_percent, -- Latest period MAX(bp.period_end) as latest_period_end FROM customer_fixed_price_agreements a LEFT JOIN fixed_price_billing_periods bp ON a.id = bp.agreement_id GROUP BY a.id; -- Monthly trend view CREATE OR REPLACE VIEW fixed_price_monthly_trends AS SELECT DATE_TRUNC('month', bp.period_start)::date as month, COUNT(DISTINCT a.id) as active_agreements, COUNT(DISTINCT bp.id) as total_periods, SUM(bp.included_hours) as total_included_hours, SUM(bp.used_hours) as total_used_hours, SUM(bp.overtime_hours) FILTER (WHERE bp.overtime_approved) as total_approved_overtime, SUM(bp.base_amount) FILTER (WHERE bp.status = 'billed') as monthly_base_revenue, SUM(bp.overtime_amount) FILTER (WHERE bp.status = 'billed' AND bp.overtime_approved) as monthly_overtime_revenue, SUM(bp.base_amount + COALESCE(bp.overtime_amount, 0)) FILTER (WHERE bp.status = 'billed') as monthly_total_revenue, AVG(a.internal_cost_rate) as avg_internal_cost_rate, SUM(bp.used_hours * a.internal_cost_rate) as monthly_internal_cost, SUM(bp.base_amount + COALESCE(bp.overtime_amount, 0)) FILTER (WHERE bp.status = 'billed') - SUM(bp.used_hours * a.internal_cost_rate) as monthly_profit FROM fixed_price_billing_periods bp JOIN customer_fixed_price_agreements a ON bp.agreement_id = a.id GROUP BY DATE_TRUNC('month', bp.period_start) ORDER BY month DESC; -- Customer aggregation CREATE OR REPLACE VIEW fixed_price_customer_summary AS SELECT a.customer_id, a.customer_name, COUNT(DISTINCT a.id) as agreement_count, COUNT(DISTINCT a.id) FILTER (WHERE a.status = 'active') as active_agreements, SUM(bp.used_hours) as total_hours_used, SUM(bp.base_amount + COALESCE(bp.overtime_amount, 0)) FILTER (WHERE bp.status = 'billed') as total_revenue, SUM(bp.used_hours * a.internal_cost_rate) as total_cost, SUM(bp.base_amount + COALESCE(bp.overtime_amount, 0)) FILTER (WHERE bp.status = 'billed') - SUM(bp.used_hours * a.internal_cost_rate) as total_profit, MAX(bp.period_end) as last_billing_date FROM customer_fixed_price_agreements a LEFT JOIN fixed_price_billing_periods bp ON a.id = bp.agreement_id GROUP BY a.customer_id, a.customer_name; COMMENT ON VIEW fixed_price_agreement_performance IS 'Aggregated performance metrics per agreement for reporting'; COMMENT ON VIEW fixed_price_monthly_trends IS 'Month-over-month revenue and profitability trends'; COMMENT ON VIEW fixed_price_customer_summary IS 'Customer-level aggregation of all fixed-price agreements';