9.0 KiB
9.0 KiB
Installation Manuals System - Implementation Status
📅 Dato: 29. Oktober 2025
✅ Implementeret
1. Database Struktur
- Tabel:
project_materialshar nuvarenr VARCHAR(50)kolonne - Index: Tilføjet index på varenr for bedre JOIN performance
- Status: ✅ Komplet
2. Backend Service
- Fil:
backend/src/services/installationManualService.js - Funktioner:
checkMissingManuals(projectId)- Tjek hvilke materialer mangler vejledningerfetchManual(varenr)- Hent en enkelt vejledning via Python scraperfetchMultipleManuals(varenrs)- Bulk hentning af vejledningergetManual(varenr)- Hent vejledning fra databasecalculateInstallationHours(manual, quantity, area)- Beregn timer baseret på manual
- Status: ✅ Komplet (servicen er oprettet, men ikke integreret endnu)
3. API Endpoints
Alle endpoints tilføjet til unified-server.js:
✅ GET /api/installation-manuals/check-missing
- Query param:
projectId(optional) - Returnerer liste af materialer uden vejledninger
- Status: Fungerer
✅ GET /api/installation-manuals/:varenr
- Henter specifik vejledning fra database
- Parser JSON felter (installation_steps, key_points, required_tools)
- Status: Fungerer
✅ GET /api/project-materials/:projectId
- Henter alle materialer for et projekt
- Inkluderer
hasManualstatus - LEFT JOIN med installation_manuals
- Status: Fungerer (returnerer tom liste for projekt 21)
✅ POST /api/installation-manuals/fetch-missing
- Body:
{projectId: number}eller{varenrs: string[]} - Bulk-henter manglende vejledninger (max 10 ad gangen)
- 2 sekunders delay mellem scrapes for at undgå rate limiting
- Status: Fungerer
✅ POST /api/pricing/scrape-manual
- Body:
{varenr: string} - Eksisterende endpoint - virker allerede
- Status: Testet og fungerer
4. Frontend Test Tool
- Fil:
test-manuals.html - Features:
- Indtast varenummer og hent manual
- Viser scraper output
- Viser manual detaljer fra database
- Hurtig-test knapper med eksempel varenumre
- URL: http://localhost:4031/test-manuals.html
- Status: ✅ Komplet og fungerer
5. Backend Material Saving
- Ændringer i
unified-server.js:- Linje 223: INSERT statement inkluderer nu varenr
- Linje 7359: POST /api/customer-projects/:projectId/materials inkluderer varenr
- Begge statements understøtter
material.varenrellermaterial.vareNr
- Status: ✅ Koden er opdateret
⚠️ Ikke Komplet Implementeret
1. Frontend Integration
Problem: Smart packages sender ikke varenr med materialerne
Løsning nødvendig:
- Opdater
InlineSmartPackage.jsforuddefinerede pakker til at inkludere varenr - Når der vælges materialer fra Bygma, inkluder vareNr i material objektet
- Eller: Automatisk lookup af varenr baseret på product_name via bygma_products
Eksempel:
// I stedet for:
{ name: 'Eternit B7 tagplader', quantity: 1.1, unit: 'm²', unitPrice: 245.00 }
// Skal det være:
{ name: 'Eternit B7 tagplader', varenr: '083846', quantity: 1.1, unit: 'm²', unitPrice: 245.00 }
2. Automatisk Manual Fetching
Mangler: Automatisk hentning når nye materialer tilføjes
Forslag til implementation:
// I POST /api/customer-projects/:projectId/materials
// Efter materialer er gemt:
const materialsWithoutManuals = materials.filter(m =>
m.varenr && !hasManualInDatabase(m.varenr)
);
// Trigger background job
if (materialsWithoutManuals.length > 0) {
fetchManualsInBackground(materialsWithoutManuals.map(m => m.varenr));
}
3. Hour Calculation Integration
Mangler: Integration i quote generation
Hvor det skal implementeres:
pdfGenerationService.jseller lignende- Ved generering af tilbud skal systemet:
- Hente project_materials
- For hver material, tjek om der findes installation_manual
- Beregn timer:
quantity × time_estimate_per_unit - Summér til total_hours
- Inkluder i PDF
Eksempel kode:
async function calculateProjectHours(projectId) {
const [materials] = await db.execute(`
SELECT pm.*, im.time_estimate_per_unit, im.difficulty_level
FROM project_materials pm
LEFT JOIN installation_manuals im ON pm.varenr = im.varenr
WHERE pm.project_id = ?
`, [projectId]);
let totalHours = 0;
for (const material of materials) {
if (material.time_estimate_per_unit) {
const hours = material.quantity * material.time_estimate_per_unit;
// Add complexity multiplier
const multiplier = material.difficulty_level === 'advanced' ? 1.3 :
material.difficulty_level === 'intermediate' ? 1.15 : 1.0;
totalHours += hours * multiplier;
}
}
return totalHours;
}
4. Bygma Product Lookup
Mangler: Automatisk varenr lookup baseret på product navn
Når frontend kun sender produkt navn, kunne backend automatisk finde varenr:
async function enrichMaterialWithVarenr(material) {
if (!material.varenr && material.name) {
const [products] = await db.execute(
'SELECT vareNr FROM bygma_products WHERE tekst LIKE ? LIMIT 1',
[`%${material.name}%`]
);
if (products.length > 0) {
material.varenr = products[0].vareNr;
}
}
return material;
}
🧪 Test Scenarie
Test med Røsevangen 44 (Project ID 21)
Nuværende status:
- ✅ Projekt oprettet: "Tag udskiftning - Røsevangen 44"
- ✅ Kunde: Alexander Warme
- ❌ Ingen geometri data endnu
- ❌ Ingen materialer endnu
- ❌ Ingen smart pakke valgt
Test steps:
- Åbn projektet i frontend
- Tilføj taggeometri (areal, hældning, etc.)
- Vælg "B7 Tag Udskiftning - Komplet" pakke
- Materialer bliver gemt (skal nu inkludere varenr)
- System tjekker for manglende manuals
- Hent manglende manuals automatisk
- Beregn timer baseret på manuals
- Generer tilbud med korrekte timer
- Eksportér til PDF
For at teste manuelt lige nu:
# 1. Test scraper
curl -X POST http://localhost:4031/api/pricing/scrape-manual \
-H "Content-Type: application/json" \
-d '{"varenr":"083846"}'
# 2. Tjek materialer for projekt 21
curl http://localhost:4031/api/project-materials/21 | jq
# 3. Tjek manglende manuals
curl "http://localhost:4031/api/installation-manuals/check-missing?projectId=21" | jq
📋 Næste Skridt (Prioriteret)
Højt Prioritet
- ✅ Tilføj varenr kolonne til project_materials (DONE)
- ✅ Opdater INSERT statements (DONE)
- ⚠️ Opdater InlineSmartPackage.js til at inkludere varenr i foruddefinerede pakker
- ⚠️ Implementer automatisk varenr lookup baseret på product navn
- ⚠️ Implementer hour calculation i quote generation
Mellem Prioritet
- Tilføj background job til at hente manuals automatisk
- Tilføj UI feedback når manuals bliver hentet
- Vис installation manual info i FinalReview
- Tilføj manual status indicator i materials liste
Lav Prioritet
- Caching af manuals for bedre performance
- Bulk import af populære manuals
- Manual review/approval workflow
- Admin panel til at redigere manuals
🔧 Teknisk Info
Database
- Database navn:
tilbudgivern(IKKE tilbudgivern_db) - Tables:
project_materials- har nu varenr kolonneinstallation_manuals- eksisterer alleredebygma_products- har vareNr kolonne for lookup
Python Scraper
- Fil:
scrape_manual_by_varenr.py - Størrelse: 23,383 bytes
- Requirements: OPENAI_API_KEY environment variable
- Output: Gemmer direkte i installation_manuals tabel
API Authentication
- Endpoints er ikke protected (ingen auth nødvendig)
- PM2 process:
tilbudgivern-unified - Port: 4031
🐛 Kendte Issues
-
Database Auth: Direct MySQL access virker ikke via terminal (auth plugin issues)
- Workaround: Brug backend API endpoints i stedet
-
Bygma Coverage: Ikke alle produkter har montagevejledninger online
- Scraperen returnerer "No manual found" for mange produkter
- Løsning: Fallback til standard estimates baseret på kategori
-
Rate Limiting: Bygma kan rate-limite hvis for mange requests
- Implementeret: 2 sekunders delay mellem bulk fetches
- Max: 10 manuals ad gangen i bulk endpoint
📊 Statistik
- Materialer uden varenr: 6 (fra tidligere imports)
- Manuals i database: Ukendt (kan ikke query directly)
- PM2 Restarts: #328
- API Endpoints tilføjet: 4 nye + 1 opdateret
🎯 Success Kriterier
Systemet er komplet når:
- Database har varenr kolonne ✅
- API endpoints fungerer ✅
- Test UI virker ✅
- Frontend sender varenr med materialer
- Manuals bliver hentet automatisk
- Timer beregnes baseret på manuals
- PDF inkluderer korrekte timer
- Test projekt fungerer end-to-end
📝 Noter
- Installation manuals er primært for tagarbejde (B7 pakker)
- Systemet er designet til at være udvidelig til andre produkt kategorier
- Manual scraping kræver OpenAI API (cost consideration)
- Systemet kan falde tilbage på standard estimates hvis manual mangler