-- Enhanced quote database structure -- This script creates tables to store detailed quote information for better reporting -- Create project_types table for standardized project types CREATE TABLE IF NOT EXISTS project_types ( id INT AUTO_INCREMENT PRIMARY KEY, type_name VARCHAR(100) NOT NULL UNIQUE, type_icon VARCHAR(10) DEFAULT NULL, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Insert standard project types INSERT IGNORE INTO project_types (type_name, type_icon, description) VALUES ('tagrenovering', '🏠', 'Komplet renovering af eksisterende tag'), ('tagskifte', '🔧', 'Udskiftning af tagmaterialer'), ('tagudskiftning', '🔨', 'Fuldstændig udskiftning af tag'), ('tagreparation', '⚒️', 'Reparation af eksisterende tag'), ('tagterasse', '🏗️', 'Installation eller renovering af tagterasse'), ('tageftersyn', '🔍', 'Inspektion og mindre reparationer'); -- Create roof_types table for standardized roof types CREATE TABLE IF NOT EXISTS roof_types ( id INT AUTO_INCREMENT PRIMARY KEY, roof_name VARCHAR(100) NOT NULL UNIQUE, roof_icon VARCHAR(10) DEFAULT NULL, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Insert standard roof types INSERT IGNORE INTO roof_types (roof_name, roof_icon, description) VALUES ('skrå tag', '📐', 'Traditionelt skrå tag med hældning'), ('fladt tag', '📏', 'Fladt tag eller tagterasse'), ('tagterasse', '🏗️', 'Bebygget tagterasse'), ('mansardtag', '🏛️', 'Tag med knækket profil'), ('saddeltag', '⛺', 'Klassisk saddeltag'); -- Add project_type_id to customer_projects table ALTER TABLE customer_projects ADD COLUMN project_type_id INT DEFAULT NULL, ADD FOREIGN KEY (project_type_id) REFERENCES project_types(id); -- Add roof_type_id to roof_geometry table ALTER TABLE roof_geometry ADD COLUMN roof_type_id INT DEFAULT NULL, ADD FOREIGN KEY (roof_type_id) REFERENCES roof_types(id); -- Create enhanced_quote_details table to store additional quote information CREATE TABLE IF NOT EXISTS enhanced_quote_details ( id INT AUTO_INCREMENT PRIMARY KEY, quote_id INT NOT NULL, project_type_id INT, roof_type_id INT, total_area DECIMAL(10,2), roof_pitch DECIMAL(5,2), work_hours DECIMAL(8,2), worker_count INT, hourly_rate DECIMAL(8,2), material_count INT DEFAULT 0, material_categories JSON, labor_breakdown JSON, material_breakdown JSON, pricing_details JSON, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (quote_id) REFERENCES generated_quotes(id) ON DELETE CASCADE, FOREIGN KEY (project_type_id) REFERENCES project_types(id), FOREIGN KEY (roof_type_id) REFERENCES roof_types(id) ); -- Create index for faster lookups CREATE INDEX idx_enhanced_quote_details_quote_id ON enhanced_quote_details(quote_id); CREATE INDEX idx_customer_projects_type ON customer_projects(project_type_id); CREATE INDEX idx_roof_geometry_type ON roof_geometry(roof_type_id); -- Create view for easy quote retrieval with all details CREATE OR REPLACE VIEW v_enhanced_quotes AS SELECT gq.id, gq.quote_text, gq.quote_format, gq.ai_tokens_used, gq.ai_cost, gq.ai_model, gq.created_at, gq.updated_at, -- Project information cp.project_name, cp.customer_name, cp.customer_email, cp.customer_phone, cp.customer_address, cp.project_description, cp.project_status, pt.type_name as project_type, pt.type_icon as project_icon, -- Calculation details pc.total_incl_vat, pc.total_labor_cost, pc.total_material_cost, pc.subtotal, pc.vat_amount, pc.vat_percentage, pc.overhead_percentage, pc.profit_percentage, -- Geometry details rg.total_area, rt.roof_name as roof_type, rt.roof_icon as roof_icon, rg.roof_pitch, rg.length, rg.width, -- Labor details pl.total_work_hours, pl.carpenter_count, pl.hourly_rate, -- Enhanced details eqd.material_count, eqd.material_categories, eqd.labor_breakdown, eqd.material_breakdown, eqd.pricing_details FROM generated_quotes gq LEFT JOIN project_calculations pc ON gq.calculation_id = pc.id LEFT JOIN customer_projects cp ON gq.project_id = cp.id LEFT JOIN project_types pt ON cp.project_type_id = pt.id LEFT JOIN roof_geometry rg ON cp.id = rg.project_id LEFT JOIN roof_types rt ON rg.roof_type_id = rt.id LEFT JOIN project_labor pl ON cp.id = pl.project_id LEFT JOIN enhanced_quote_details eqd ON gq.id = eqd.quote_id; -- Create trigger to automatically populate enhanced_quote_details when a quote is created DELIMITER // CREATE OR REPLACE TRIGGER tr_populate_enhanced_quote_details AFTER INSERT ON generated_quotes FOR EACH ROW BEGIN DECLARE project_type_id_val INT DEFAULT NULL; DECLARE roof_type_id_val INT DEFAULT NULL; DECLARE area_val DECIMAL(10,2) DEFAULT NULL; DECLARE pitch_val DECIMAL(5,2) DEFAULT NULL; DECLARE hours_val DECIMAL(8,2) DEFAULT NULL; DECLARE workers_val INT DEFAULT NULL; DECLARE rate_val DECIMAL(8,2) DEFAULT NULL; DECLARE material_cnt INT DEFAULT 0; DECLARE material_cats JSON DEFAULT NULL; -- Get project type SELECT cp.project_type_id INTO project_type_id_val FROM customer_projects cp WHERE cp.id = NEW.project_id; -- Get roof information SELECT rg.roof_type_id, rg.total_area, rg.roof_pitch INTO roof_type_id_val, area_val, pitch_val FROM roof_geometry rg WHERE rg.project_id = NEW.project_id; -- Get labor information SELECT pl.total_work_hours, pl.carpenter_count, pl.hourly_rate INTO hours_val, workers_val, rate_val FROM project_labor pl WHERE pl.project_id = NEW.project_id; -- Get material information SELECT COUNT(*), JSON_ARRAYAGG(DISTINCT material_category) INTO material_cnt, material_cats FROM project_materials pm WHERE pm.project_id = NEW.project_id; -- Insert enhanced details INSERT INTO enhanced_quote_details ( quote_id, project_type_id, roof_type_id, total_area, roof_pitch, work_hours, worker_count, hourly_rate, material_count, material_categories ) VALUES ( NEW.id, project_type_id_val, roof_type_id_val, area_val, pitch_val, hours_val, workers_val, rate_val, material_cnt, material_cats ); END// DELIMITER ; -- Update existing quotes to have enhanced details INSERT INTO enhanced_quote_details ( quote_id, project_type_id, roof_type_id, total_area, roof_pitch, work_hours, worker_count, hourly_rate, material_count, material_categories ) SELECT gq.id, cp.project_type_id, rg.roof_type_id, rg.total_area, rg.roof_pitch, pl.total_work_hours, pl.carpenter_count, pl.hourly_rate, COALESCE((SELECT COUNT(*) FROM project_materials pm WHERE pm.project_id = cp.id), 0), COALESCE((SELECT JSON_ARRAYAGG(DISTINCT material_category) FROM project_materials pm WHERE pm.project_id = cp.id), JSON_ARRAY()) FROM generated_quotes gq LEFT JOIN customer_projects cp ON gq.project_id = cp.id LEFT JOIN roof_geometry rg ON cp.id = rg.project_id LEFT JOIN project_labor pl ON cp.id = pl.project_id WHERE NOT EXISTS ( SELECT 1 FROM enhanced_quote_details eqd WHERE eqd.quote_id = gq.id );