- Added TaskCategorizationService to categorize tasks based on keywords in descriptions. - Implemented fuzzy matching using Levenshtein distance for better keyword matching. - Introduced caching for categories and keywords to optimize database queries. - Added methods for categorizing individual tasks and batch processing for project tasks. - Created SQL migration scripts for task_categories and category_keywords tables. - Included default categories and keywords for initial setup. - Enhanced project_tasks table with new columns for categorization data. - Added statistics export functionality for category performance analysis.
151 lines
7.2 KiB
SQL
151 lines
7.2 KiB
SQL
-- Feature 3: Smart Packages with Task Ordering
|
|
-- Date: 2025-01-XX
|
|
-- Description: Tilføjer task ordering, dependencies og geometry-baseret material beregning
|
|
|
|
-- Opret package_tasks tabel til at linke tasks til packages
|
|
CREATE TABLE IF NOT EXISTS package_tasks (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
package_id INT NOT NULL,
|
|
task_name VARCHAR(255) NOT NULL,
|
|
task_description TEXT,
|
|
estimated_hours DECIMAL(8,2) DEFAULT 0,
|
|
task_order INT DEFAULT 0 COMMENT 'Rækkefølge inden for fase',
|
|
task_phase ENUM('forberedelse', 'hovedarbejde', 'afslutning', 'inspektion') DEFAULT 'hovedarbejde',
|
|
depends_on_task_id INT DEFAULT NULL COMMENT 'ID af task der skal udføres først',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
FOREIGN KEY (package_id) REFERENCES material_packages(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (depends_on_task_id) REFERENCES package_tasks(id) ON DELETE SET NULL,
|
|
|
|
INDEX idx_package_id (package_id),
|
|
INDEX idx_task_phase (task_phase),
|
|
INDEX idx_task_order (task_order),
|
|
INDEX idx_depends_on (depends_on_task_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- Tilføj geometry multiplier kolonner til package_materials (skip hvis eksisterer)
|
|
SET @dbname = 'tilbudgivern';
|
|
SET @tablename = 'package_materials';
|
|
SET @columnname = 'geometry_multiplier';
|
|
SET @preparedStatement = (SELECT IF(
|
|
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
|
|
WHERE TABLE_SCHEMA = @dbname AND TABLE_NAME = @tablename AND COLUMN_NAME = @columnname) > 0,
|
|
'SELECT "Column geometry_multiplier already exists";',
|
|
'ALTER TABLE package_materials ADD COLUMN geometry_multiplier VARCHAR(50) DEFAULT NULL COMMENT "area, length, width, spaer_count, perimeter, none";'
|
|
));
|
|
PREPARE alterStatement FROM @preparedStatement;
|
|
EXECUTE alterStatement;
|
|
DEALLOCATE PREPARE alterStatement;
|
|
|
|
SET @columnname = 'base_quantity';
|
|
SET @preparedStatement = (SELECT IF(
|
|
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
|
|
WHERE TABLE_SCHEMA = @dbname AND TABLE_NAME = @tablename AND COLUMN_NAME = @columnname) > 0,
|
|
'SELECT "Column base_quantity already exists";',
|
|
'ALTER TABLE package_materials ADD COLUMN base_quantity DECIMAL(10,3) DEFAULT NULL COMMENT "Basis mængde før geometri multiplikation";'
|
|
));
|
|
PREPARE alterStatement FROM @preparedStatement;
|
|
EXECUTE alterStatement;
|
|
DEALLOCATE PREPARE alterStatement;
|
|
|
|
SET @columnname = 'waste_factor';
|
|
SET @preparedStatement = (SELECT IF(
|
|
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS
|
|
WHERE TABLE_SCHEMA = @dbname AND TABLE_NAME = @tablename AND COLUMN_NAME = @columnname) > 0,
|
|
'SELECT "Column waste_factor already exists";',
|
|
'ALTER TABLE package_materials ADD COLUMN waste_factor DECIMAL(5,3) DEFAULT 1.10 COMMENT "Spildfaktor (1.10 = 10% spild)";'
|
|
));
|
|
PREPARE alterStatement FROM @preparedStatement;
|
|
EXECUTE alterStatement;
|
|
DEALLOCATE PREPARE alterStatement;
|
|
|
|
-- Opdater eksisterende records med default værdier
|
|
UPDATE package_materials
|
|
SET
|
|
base_quantity = quantity,
|
|
waste_factor = 1.10,
|
|
geometry_multiplier = 'none'
|
|
WHERE base_quantity IS NULL;
|
|
|
|
-- Opret smart_packages tabel (hvis ikke eksisterer) til færdige packages
|
|
CREATE TABLE IF NOT EXISTS smart_packages (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
package_code VARCHAR(50) UNIQUE NOT NULL COMMENT 'B7, S12, etc',
|
|
package_name VARCHAR(255) NOT NULL,
|
|
package_description TEXT,
|
|
default_geometry_type ENUM('fladt_tag', 'skraat_tag', 'mansard', 'komplekst') DEFAULT 'skraat_tag',
|
|
estimated_total_hours DECIMAL(8,2) DEFAULT 0,
|
|
estimated_material_cost DECIMAL(12,2) DEFAULT 0,
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
INDEX idx_package_code (package_code),
|
|
INDEX idx_active (is_active)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- Opret customer_project_packages junction tabel
|
|
CREATE TABLE IF NOT EXISTS customer_project_packages (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
project_id INT NOT NULL,
|
|
smart_package_id INT NOT NULL,
|
|
quantity INT DEFAULT 1,
|
|
added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
FOREIGN KEY (project_id) REFERENCES customer_projects(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (smart_package_id) REFERENCES smart_packages(id) ON DELETE CASCADE,
|
|
|
|
INDEX idx_project_id (project_id),
|
|
INDEX idx_smart_package_id (smart_package_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- Indsæt eksempel B7 package i material_packages tabel først
|
|
INSERT INTO material_packages (name, description, category, created_by, total_estimated_price, is_active)
|
|
VALUES ('B7 - Tag Renovation Komplet', 'Komplet tagrenovation med nedtagning, spær, undertag, tagplader og isolering', 'Tagmaterialer', 'system', 85000, 1)
|
|
ON DUPLICATE KEY UPDATE name = VALUES(name);
|
|
|
|
-- Hent B7 package ID
|
|
SET @b7_id = (SELECT id FROM material_packages WHERE name = 'B7 - Tag Renovation Komplet' LIMIT 1);
|
|
|
|
-- Indsæt også i smart_packages (reference tabel)
|
|
INSERT INTO smart_packages (package_code, package_name, package_description, estimated_total_hours, estimated_material_cost)
|
|
SELECT 'B7', name, description, 120, total_estimated_price
|
|
FROM material_packages
|
|
WHERE id = @b7_id
|
|
ON DUPLICATE KEY UPDATE package_name = VALUES(package_name);
|
|
|
|
-- Indsæt tasks for B7 package med rækkefølge
|
|
INSERT INTO package_tasks (package_id, task_name, task_description, estimated_hours, task_order, task_phase, depends_on_task_id)
|
|
VALUES
|
|
-- Fase 1: Forberedelse
|
|
(@b7_id, 'Stillads opsætning', 'Opsætte stillads rundt om hele bygningen', 8, 1, 'forberedelse', NULL),
|
|
(@b7_id, 'Sik kerhedsforanstaltninger', 'Opsætte sikkerhedsnet og advarselsskiltning', 2, 2, 'forberedelse', NULL),
|
|
|
|
-- Fase 2: Hovedarbejde (nedrivning først)
|
|
(@b7_id, 'Nedtagning af gamle tagplader', 'Fjerne og bortskaffe gamle tagplader', 12, 1, 'hovedarbejde', NULL),
|
|
(@b7_id, 'Fjernelse af gamle lægter', 'Fjerne gamle lægter og genbrugsmaterialer', 8, 2, 'hovedarbejde', NULL),
|
|
(@b7_id, 'Inspektion og reparation af spær', 'Inspicere spær og reparere/udskifte skadede dele', 12, 3, 'hovedarbejde', NULL),
|
|
(@b7_id, 'Montering af nyt undertag', 'Montere undertag med overlæg og tape', 16, 4, 'hovedarbejde', NULL),
|
|
(@b7_id, 'Montering af lægter', 'Montere nye lægter med korrekt afstand (0.6m eller 1.0m)', 14, 5, 'hovedarbejde', NULL),
|
|
(@b7_id, 'Montering af tagplader', 'Montere nye tagplader med overlæg og skruer', 20, 6, 'hovedarbejde', NULL),
|
|
(@b7_id, 'Montering af vindskeder', 'Montere vindskeder langs gavle', 10, 7, 'hovedarbejde', NULL),
|
|
|
|
-- Fase 3: Afslutning
|
|
(@b7_id, 'Montering af tagrende og nedløb', 'Montere tagrende og nedløb med korrekt fald', 12, 1, 'afslutning', NULL),
|
|
(@b7_id, 'Tætning og fuger', 'Tætne gennemføringer og fuger', 6, 2, 'afslutning', NULL),
|
|
(@b7_id, 'Oprydning', 'Fjerne affald og rengøre arbejdsområdet', 4, 3, 'afslutning', NULL),
|
|
|
|
-- Fase 4: Inspektion
|
|
(@b7_id, 'Endelig inspektion', 'Gennemgå hele taget for kvalitetskontrol', 4, 1, 'inspektion', NULL);
|
|
|
|
SELECT 'Feature 3 Migration Complete!' as Status;
|
|
SELECT
|
|
COUNT(*) as total_tasks,
|
|
task_phase,
|
|
SUM(estimated_hours) as phase_hours
|
|
FROM package_tasks
|
|
WHERE package_id = @b7_id
|
|
GROUP BY task_phase
|
|
ORDER BY FIELD(task_phase, 'forberedelse', 'hovedarbejde', 'afslutning', 'inspektion');
|