require('dotenv').config(); const mysql = require('mysql2/promise'); const axios = require('axios'); async function addTasks(conn, packageId, packageName, category, estimatedHours) { // Check if package already has tasks const [existing] = await conn.execute('SELECT COUNT(*) as count FROM package_tasks WHERE package_id = ?', [packageId]); if (existing[0].count > 0) { console.log(` ✓ Pakke ${packageId} har allerede opgaver`); return; } let tasks = []; // Generate tasks based on package name/category if (packageName.includes('Tagrende') || packageName.includes('tagrende')) { tasks = [ { name: 'Forberedelse og opmåling', desc: 'Opmåle facadelængde og planlægge montering', hours: 0.5, phase: 'forberedelse', order: 1 }, { name: 'Montering af konsoljern', desc: 'Montere konsoljern med korrekt afstand (60cm)', hours: 1.0, phase: 'hovedarbejde', order: 1 }, { name: 'Montering af tagrende', desc: 'Montere tagrende med korrekt fald (1:500)', hours: 1.5, phase: 'hovedarbejde', order: 2 }, { name: 'Montering af rende-tilbehør', desc: 'Montere hjørner, afslutninger og rendekrog', hours: 0.5, phase: 'hovedarbejde', order: 3 }, { name: 'Slutkontrol', desc: 'Kontrollere tæthed og fald', hours: 0.5, phase: 'inspektion', order: 1 } ]; } else if (packageName.includes('Nedløb') || packageName.includes('nedløb')) { tasks = [ { name: 'Opmåling', desc: 'Måle højde og planlægge fastgørelse', hours: 0.3, phase: 'forberedelse', order: 1 }, { name: 'Montering af rørbeslag', desc: 'Montere rørbeslag med korrekt afstand', hours: 0.5, phase: 'hovedarbejde', order: 1 }, { name: 'Montering af nedløbsrør', desc: 'Montere nedløbsrør og samle sektioner', hours: 0.7, phase: 'hovedarbejde', order: 2 }, { name: 'Tilslutning og afslutning', desc: 'Tilslutte til tagrende og montere nedløbsbrønd', hours: 0.5, phase: 'afslutning', order: 1 } ]; } else if (packageName.includes('spær') || packageName.includes('Spær')) { tasks = [ { name: 'Inspektion af eksisterende spær', desc: 'Kontrollere tilstand og identificere problemer', hours: 1.0, phase: 'forberedelse', order: 1 }, { name: 'Opmåling og tilskæring', desc: 'Opmåle og tilskære nyt tømmer', hours: 1.5, phase: 'forberedelse', order: 2 }, { name: 'Opretning af spær', desc: 'Montere forstærkninger og rette skader', hours: 3.0, phase: 'hovedarbejde', order: 1 }, { name: 'Kontrol af konstruktion', desc: 'Kontrollere stabilitet og vinkelrethed', hours: 0.5, phase: 'inspektion', order: 1 } ]; } else if (packageName.includes('B7') || packageName.includes('tagplade')) { tasks = [ { name: 'Forberedelse', desc: 'Kontrollere underlaget og planlægge oplægning', hours: 0.5, phase: 'forberedelse', order: 1 }, { name: 'Montering af lægter', desc: 'Montere bære- og kontralægter', hours: 2.0, phase: 'hovedarbejde', order: 1 }, { name: 'Oplægning af B7 plader', desc: 'Lægge B7 plader med korrekt overlæg', hours: 2.5, phase: 'hovedarbejde', order: 2 }, { name: 'Fastgørelse', desc: 'Skrue plader fast med tagskruer', hours: 1.0, phase: 'hovedarbejde', order: 3 }, { name: 'Slutkontrol', desc: 'Kontrollere tæthed og finish', hours: 0.5, phase: 'inspektion', order: 1 } ]; } else if (packageName.includes('Rygning') || packageName.includes('rygning')) { tasks = [ { name: 'Opmåling', desc: 'Måle rygningslængde og forberede materiale', hours: 0.3, phase: 'forberedelse', order: 1 }, { name: 'Montering af rygningselementer', desc: 'Montere rygning med korrekt overlæg', hours: 1.5, phase: 'hovedarbejde', order: 1 }, { name: 'Tætning og afslutning', desc: 'Tætne ender og kontrollere finish', hours: 0.5, phase: 'afslutning', order: 1 } ]; } else if (packageName.includes('Taghætte') || packageName.includes('taghætte')) { tasks = [ { name: 'Udskæring i tag', desc: 'Lave hul til taghætte med korrekt dimension', hours: 0.5, phase: 'forberedelse', order: 1 }, { name: 'Montering af taghætte', desc: 'Montere taghætte og tætne omkring', hours: 0.8, phase: 'hovedarbejde', order: 1 }, { name: 'Afslutning', desc: 'Kontrollere tæthed og finish', hours: 0.2, phase: 'inspektion', order: 1 } ]; } else if (packageName.includes('undertag') || packageName.includes('Undertag')) { tasks = [ { name: 'Forberedelse', desc: 'Kontrollere spærkonstruktion', hours: 0.5, phase: 'forberedelse', order: 1 }, { name: 'Montering af lægter', desc: 'Montere lægter til undertag', hours: 1.5, phase: 'hovedarbejde', order: 1 }, { name: 'Montering af undertag', desc: 'Lægge undertag med korrekt overlæg', hours: 2.0, phase: 'hovedarbejde', order: 2 }, { name: 'Tætning', desc: 'Tætne samlinger og gennemføringer', hours: 1.0, phase: 'hovedarbejde', order: 3 } ]; } else if (packageName.includes('Velux') || packageName.includes('tagvindue')) { tasks = [ { name: 'Opmåling og udskæring', desc: 'Opmåle og udskære hul i tag', hours: 1.5, phase: 'forberedelse', order: 1 }, { name: 'Montering af vindue', desc: 'Montere Velux vindue i ramme', hours: 2.0, phase: 'hovedarbejde', order: 1 }, { name: 'Montering af inddækning', desc: 'Montere inddækningskit omkring vindue', hours: 1.5, phase: 'hovedarbejde', order: 2 }, { name: 'Tætning og isolering', desc: 'Tætne og isolere omkring vindue', hours: 1.0, phase: 'afslutning', order: 1 }, { name: 'Test og justering', desc: 'Teste åbning/lukning og justere', hours: 0.5, phase: 'inspektion', order: 1 } ]; } else if (packageName.includes('vindskede') || packageName.includes('Vindskede')) { tasks = [ { name: 'Opmåling', desc: 'Måle gavllængde og tilskære brædder', hours: 0.5, phase: 'forberedelse', order: 1 }, { name: 'Montering af vindskeder', desc: 'Montere vindskeder med beslag', hours: 2.0, phase: 'hovedarbejde', order: 1 }, { name: 'Behandling', desc: 'Grundmaling eller oliering', hours: 1.0, phase: 'afslutning', order: 1 } ]; } else if (packageName.includes('nedrivning') || packageName.includes('Nedrivning')) { tasks = [ { name: 'Sikkerhedsforanstaltninger', desc: 'Opsætte afspærring og sikkerhedsudstyr', hours: 0.5, phase: 'forberedelse', order: 1 }, { name: 'Nedtagning', desc: 'Nedtage materialer forsigtig', hours: 3.0, phase: 'hovedarbejde', order: 1 }, { name: 'Sortering og bortkørsel', desc: 'Sortere affald og køre til genbrugsstation', hours: 1.5, phase: 'afslutning', order: 1 } ]; } else if (packageName.includes('trækbånd') || packageName.includes('Trækbånd')) { tasks = [ { name: 'Opmåling', desc: 'Måle og planlægge placering', hours: 0.5, phase: 'forberedelse', order: 1 }, { name: 'Montering af beslag', desc: 'Montere vægbeslag og tagbeslag', hours: 1.0, phase: 'hovedarbejde', order: 1 }, { name: 'Montering af trækbånd', desc: 'Montere og spænde trækbånd', hours: 1.0, phase: 'hovedarbejde', order: 2 }, { name: 'Kontrol', desc: 'Kontrollere spænding og fastgørelse', hours: 0.5, phase: 'inspektion', order: 1 } ]; } else if (packageName.includes('skortrende') || packageName.includes('Skortrende')) { tasks = [ { name: 'Opmåling', desc: 'Måle omkring skorsten', hours: 0.5, phase: 'forberedelse', order: 1 }, { name: 'Tilskæring af zink/kobber', desc: 'Tilskære og forme skortrende', hours: 2.0, phase: 'hovedarbejde', order: 1 }, { name: 'Montering', desc: 'Montere skortrende med beslag', hours: 2.0, phase: 'hovedarbejde', order: 2 }, { name: 'Lodning og tætning', desc: 'Lodde samlinger og tætne', hours: 1.5, phase: 'afslutning', order: 1 } ]; } else { // Generic tasks for other packages const hoursPerTask = estimatedHours / 4; tasks = [ { name: 'Forberedelse', desc: 'Klargøre arbejdsområde og materialer', hours: hoursPerTask * 0.5, phase: 'forberedelse', order: 1 }, { name: 'Hovedarbejde', desc: 'Udføre hovedopgaven', hours: hoursPerTask * 2.5, phase: 'hovedarbejde', order: 1 }, { name: 'Afslutning', desc: 'Rydde op og afslutte arbejde', hours: hoursPerTask * 0.5, phase: 'afslutning', order: 1 }, { name: 'Kvalitetskontrol', desc: 'Kontrollere resultat', hours: hoursPerTask * 0.5, phase: 'inspektion', order: 1 } ]; } // Insert tasks for (const task of tasks) { await conn.execute( `INSERT INTO package_tasks (package_id, task_name, task_description, estimated_hours, task_order, task_phase) VALUES (?, ?, ?, ?, ?, ?)`, [packageId, task.name, task.desc, task.hours, task.order, task.phase] ); } console.log(` ✓ Tilføjet ${tasks.length} opgaver til pakke ${packageId}`); } async function addMaterials(conn, packageId, packageName, description) { // Check if package already has materials const [existing] = await conn.execute('SELECT COUNT(*) as count FROM package_materials WHERE package_id = ?', [packageId]); if (existing[0].count > 0) { console.log(` ✓ Pakke ${packageId} har allerede materialer`); return; } // Try to parse VARENUMRE from description const varenumreRegex = /(\d{6,})/g; const matches = description.match(varenumreRegex); if (matches && matches.length > 0) { // Get materials from API const response = await axios.get('http://localhost:4031/api/materials'); const allMaterials = response.data.materials || []; let addedCount = 0; for (const varenr of matches) { const material = allMaterials.find(m => m.varenummer === varenr); if (material && material.price) { await conn.execute( `INSERT INTO package_materials (package_id, material_name, material_category, quantity, unit, unit_price, total_price, supplier, base_quantity) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ packageId, material.name, material.category || 'Diverse', 1, material.enhed || 'stk', parseFloat(material.price), parseFloat(material.price), material.leverandoer || 'Bygma', 1 ] ); addedCount++; } } if (addedCount > 0) { console.log(` ✓ Tilføjet ${addedCount} materialer til pakke ${packageId}`); return; } } // If no VARENUMRE found or no matches, add generic materials based on package type let materials = []; if (packageName.includes('Tagrende') || packageName.includes('tagrende')) { materials = [ { name: 'Tagrende 3m', category: 'Tag', qty: 1, unit: 'stk', price: 250, supplier: 'Lindab' }, { name: 'Konsoljern', category: 'Tag', qty: 5, unit: 'stk', price: 25, supplier: 'Lindab' }, { name: 'Rendeafslutning', category: 'Tag', qty: 2, unit: 'stk', price: 45, supplier: 'Lindab' }, { name: 'Rendekrog', category: 'Tag', qty: 2, unit: 'stk', price: 35, supplier: 'Lindab' } ]; } else if (packageName.includes('Nedløb') || packageName.includes('nedløb')) { materials = [ { name: 'Nedløbsrør 3m', category: 'Tag', qty: 1, unit: 'stk', price: 180, supplier: 'Lindab' }, { name: 'Rørholder', category: 'Tag', qty: 3, unit: 'stk', price: 22, supplier: 'Lindab' }, { name: 'Nedløbsbøjning', category: 'Tag', qty: 2, unit: 'stk', price: 65, supplier: 'Lindab' } ]; } else if (packageName.includes('B7') && !packageName.includes('Rygning') && !packageName.includes('Taghætte')) { materials = [ { name: 'B7 Bølgeplade 2,5m', category: 'Tag', qty: 10, unit: 'm²', price: 125, supplier: 'Bygma' }, { name: 'Tagskruer', category: 'Tag', qty: 100, unit: 'stk', price: 2.5, supplier: 'Bygma' }, { name: 'Bærelægte 38x73', category: 'Tømrer', qty: 20, unit: 'lbm', price: 25, supplier: 'Bygma' } ]; } else if (packageName.includes('Rygning')) { materials = [ { name: 'Rygning til B7', category: 'Tag', qty: 1, unit: 'lbm', price: 180, supplier: 'Bygma' }, { name: 'Rygningselement', category: 'Tag', qty: 1, unit: 'stk', price: 95, supplier: 'Bygma' } ]; } else if (packageName.includes('spær') || packageName.includes('Spær')) { materials = [ { name: 'Spærtræ 200mm', category: 'Tømrer', qty: 10, unit: 'lbm', price: 85, supplier: 'Bygma' }, { name: 'Spærskruer', category: 'Beslag', qty: 50, unit: 'stk', price: 3.5, supplier: 'Bygma' }, { name: 'Træbeslag', category: 'Beslag', qty: 10, unit: 'stk', price: 45, supplier: 'Bygma' } ]; } else { // Generic material for other packages materials = [ { name: 'Diverse materialer', category: 'Diverse', qty: 1, unit: 'stk', price: 500, supplier: 'Bygma' } ]; } // Insert materials for (const mat of materials) { await conn.execute( `INSERT INTO package_materials (package_id, material_name, material_category, quantity, unit, unit_price, total_price, supplier, base_quantity) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ packageId, mat.name, mat.category, mat.qty, mat.unit, mat.price, mat.qty * mat.price, mat.supplier, mat.qty ] ); } console.log(` ✓ Tilføjet ${materials.length} materialer til pakke ${packageId}`); } (async () => { const conn = await mysql.createConnection({ host: process.env.DB_HOST, port: process.env.DB_PORT, user: process.env.DB_USER, password: process.env.DB_PASSWORD, database: process.env.DB_NAME }); // Get all active packages const [packages] = await conn.execute( 'SELECT id, name, description, category, estimated_hours FROM material_packages WHERE is_active = 1 ORDER BY id' ); console.log(`🔄 STARTER POPULERING AF ${packages.length} PAKKER...\n`); let tasksAdded = 0; let materialsAdded = 0; for (const pkg of packages) { console.log(`\n📦 Pakke ${pkg.id}: ${pkg.name}`); try { const [tasksBefore] = await conn.execute('SELECT COUNT(*) as count FROM package_tasks WHERE package_id = ?', [pkg.id]); await addTasks(conn, pkg.id, pkg.name, pkg.category, pkg.estimated_hours || 4); const [tasksAfter] = await conn.execute('SELECT COUNT(*) as count FROM package_tasks WHERE package_id = ?', [pkg.id]); if (tasksAfter[0].count > tasksBefore[0].count) tasksAdded++; const [matsBefore] = await conn.execute('SELECT COUNT(*) as count FROM package_materials WHERE package_id = ?', [pkg.id]); await addMaterials(conn, pkg.id, pkg.name, pkg.description || ''); const [matsAfter] = await conn.execute('SELECT COUNT(*) as count FROM package_materials WHERE package_id = ?', [pkg.id]); if (matsAfter[0].count > matsBefore[0].count) materialsAdded++; } catch (error) { console.log(` ❌ Fejl: ${error.message}`); } } console.log(`\n\n✅ FÆRDIG!`); console.log(` ${tasksAdded} pakker fik opgaver`); console.log(` ${materialsAdded} pakker fik materialer`); await conn.end(); })();