12 KiB
Custom Installation Opgaver - Manual
📋 Oversigt
Dette system gør det muligt at manuelt oprette installation opgaver for materialer der IKKE har montage vejledninger. Tømmeren kan selv definere:
- Opgave navn: fx "Opsætning af lægter"
- Tid pr. enhed: fx 10 minutter pr. løbende meter
- Enhed: per_meter, per_sqm, per_piece, per_project
- Materialekobling: Varenummer på materialet
- Værktøjer: Liste af nødvendige værktøjer
- Timepris: Kan tilpasses pr. opgave
Alt er redigerbart og justerbart efter behov.
🗄️ Database Struktur
Nye felter i smart_package_tasks tabel:
time_unit -- Enhed: 'per_sqm', 'per_meter', 'per_piece', 'per_project'
time_per_unit -- Timer pr. enhed (fx 0.17 = 10 min)
is_custom -- Boolean: Er det en manuelt oprettet opgave?
material_varenr -- Varenummer på materialet
🔧 API Endpoints
1. Opret Custom Task
POST /api/smart-packages/custom-tasks
{
"packageId": 1,
"name": "Opsætning af lægter",
"description": "Præcis montage af lægter med korrekt afstand (cc 370mm). Inkluderer skruearbejde og kontrol af vaterpas.",
"timeUnit": "per_meter",
"timePerUnit": 0.17,
"hourlyRate": 580,
"materialVarenr": "147072",
"tools": ["skruemaskine", "vaterpas", "målebånd", "snor"],
"skills": ["tømrerarbejde", "præcision"],
"optional": false
}
Response:
{
"success": true,
"taskId": 42,
"order": 4,
"message": "Custom task 'Opsætning af lægter' oprettet med 0.17 timer pr. per_meter"
}
2. Hent Alle Custom Tasks
GET /api/smart-packages/custom-tasks
Query params:
packageId- Filtrer på specifik pakkematerialVarenr- Filtrer på specifikt materiale
Response:
{
"success": true,
"tasks": [
{
"id": 42,
"package_id": 1,
"name": "Opsætning af lægter",
"description": "...",
"time_unit": "per_meter",
"time_per_unit": 0.17,
"time_display": "10 min pr. løbende meter",
"hourly_rate": 580,
"material_varenr": "147072",
"material_name": "Lægter 38x73mm",
"package_name": "B7 Tag Udskiftning",
"required_tools": ["skruemaskine", "vaterpas"],
"is_custom": 1,
"created_at": "2025-10-29T10:30:00"
}
],
"count": 1
}
3. Opdater Task (inkl. custom felter)
PUT /api/smart-packages/tasks/:taskId
{
"name": "Opsætning af lægter - opdateret",
"timeUnit": "per_meter",
"timePerUnit": 0.20,
"materialVarenr": "147072",
"tools": ["skruemaskine", "vaterpas", "målebånd"]
}
💡 Eksempler på Custom Tasks
Eksempel 1: Lægter (løbende meter)
POST /api/smart-packages/custom-tasks
{
"packageId": 1,
"name": "Opsætning af lægter",
"description": "Præcis montage af lægter med korrekt cc-mål 370mm",
"timeUnit": "per_meter", // Pr. løbende meter
"timePerUnit": 0.17, // 10 minutter = 0.166 timer
"hourlyRate": 580,
"materialVarenr": "147072",
"tools": ["skruemaskine", "vaterpas", "målebånd", "snor"]
}
Beregning:
- 100 løbende meter lægter × 0.17 timer = 17 timer
- 17 timer × 580 kr = 9,860 kr
Eksempel 2: Spær (pr. styk)
POST /api/smart-packages/custom-tasks
{
"packageId": 1,
"name": "Montage af spær",
"description": "Opsætning af bærende spær med korrekt afstand og vinkel",
"timeUnit": "per_piece", // Pr. styk
"timePerUnit": 0.75, // 45 minutter pr. spær
"hourlyRate": 580,
"tools": ["boremaskine", "vaterpas", "vinkelmåler", "sav"]
}
Beregning:
- 12 spær × 0.75 timer = 9 timer
- 9 timer × 580 kr = 5,220 kr
Eksempel 3: Tagpap (pr. m²)
POST /api/smart-packages/custom-tasks
{
"packageId": 2,
"name": "Udlægning af tagpap",
"description": "Udlægning af diffusionsåben tagpap med 10cm overlap",
"timeUnit": "per_sqm", // Pr. m²
"timePerUnit": 0.08, // ~5 minutter pr. m²
"hourlyRate": 580,
"materialVarenr": "TAG123",
"tools": ["saks", "hæftepistol", "målebånd"]
}
Beregning:
- 100 m² tagpap × 0.08 timer = 8 timer
- 8 timer × 580 kr = 4,640 kr
Eksempel 4: Hele projekt (fast tid)
POST /api/smart-packages/custom-tasks
{
"packageId": 3,
"name": "Oprydning og aflevering",
"description": "Komplet oprydning, bortskaffelse af affald og aflevering",
"timeUnit": "per_project", // Fast tid for hele projektet
"timePerUnit": 4.0, // 4 timer totalt
"hourlyRate": 580
}
Beregning:
- Fast pris: 4 timer × 580 kr = 2,320 kr
🔄 Workflow: Fra Materiale til Opgave
Trin 1: Identificer materialer uden vejledning
-- Find materialer uden installation manual
SELECT
m.varenr,
m.material_name,
m.category
FROM materials m
LEFT JOIN installation_manuals im ON m.varenr = im.material_varenr
WHERE im.id IS NULL
AND m.category IN ('Tømmer', 'Tagmateriale', 'Isolering')
ORDER BY m.material_name;
Trin 2: Opret custom task for materialet
curl -X POST http://localhost:5001/api/smart-packages/custom-tasks \
-H "Content-Type: application/json" \
-d '{
"packageId": 1,
"name": "Opsætning af lægter",
"timeUnit": "per_meter",
"timePerUnit": 0.17,
"materialVarenr": "147072"
}'
Trin 3: Tilføj til smart pakke
Custom tasken er nu automatisk tilknyttet pakken og kan bruges i tilbudsgivning.
📊 time_unit Enheder
| Enhed | Værdi | Beskrivelse | Eksempel |
|---|---|---|---|
| per_meter | per_meter |
Timer pr. løbende meter | Lægter, tagrender |
| per_sqm | per_sqm |
Timer pr. m² | Tagpap, isolering, gulve |
| per_piece | per_piece |
Timer pr. styk | Spær, døre, vinduer |
| per_project | per_project |
Fast tid for hele projektet | Oprydning, inspektion |
| per_hour | per_hour |
Timer pr. time (sjældent) | Konsulentarbejde |
🧮 Tidsberegning Konvertering
Fra minutter til timer (decimal):
// 10 minutter
const minutes = 10;
const hours = minutes / 60; // 0.166667
// Afrund til 2 decimaler
const timePerUnit = Math.round(hours * 100) / 100; // 0.17
Almindelige konverteringer:
| Minutter | Timer (decimal) | Brug i API |
|---|---|---|
| 5 min | 0.08 | 0.08 |
| 10 min | 0.17 | 0.17 |
| 15 min | 0.25 | 0.25 |
| 20 min | 0.33 | 0.33 |
| 30 min | 0.50 | 0.50 |
| 45 min | 0.75 | 0.75 |
| 60 min | 1.00 | 1.00 |
🎯 Use Cases
Use Case 1: Tømrer har erfaring med lægter
Scenario: Tømmer ved at det tager ca. 10 min pr. løbende meter at montere lægter.
Løsning:
{
"name": "Opsætning af lægter",
"timeUnit": "per_meter",
"timePerUnit": 0.17, // 10 min
"materialVarenr": "147072"
}
Use Case 2: Kompleks opgave med variabel tid
Scenario: Spær montage tager 30-60 min afhængigt af størrelse. Brug gennemsnit.
Løsning:
{
"name": "Montage af spær",
"timeUnit": "per_piece",
"timePerUnit": 0.75, // 45 min gennemsnit
"description": "Tid varierer: 30-60 min pr. spær afhængigt af dimension"
}
Use Case 3: Ingen klar enhed - brug projekt
Scenario: Oprydning tager samme tid uanset størrelse.
Løsning:
{
"name": "Oprydning og aflevering",
"timeUnit": "per_project",
"timePerUnit": 4.0, // 4 timer fast
"description": "Inkluderer bortskaffelse, oprydning og slutinspektion"
}
🔍 View: custom_installation_tasks
Der er oprettet et database view til at få overblik:
SELECT * FROM custom_installation_tasks
ORDER BY created_at DESC;
Output:
+----+----------------------+------------------+--------------+-----------------------------+
| id | task_name | time_unit | time_per_unit| time_display |
+----+----------------------+------------------+--------------+-----------------------------+
| 42 | Opsætning af lægter | per_meter | 0.17 | 10 min pr. løbende meter |
| 43 | Montage af spær | per_piece | 0.75 | 45 min pr. styk |
| 44 | Udlægning af tagpap | per_sqm | 0.08 | 5 min pr. m² |
+----+----------------------+------------------+--------------+-----------------------------+
🚀 Integration med Tilbudsgivning
Dynamisk beregning i quote system
// Beregn timer baseret på time_unit
function calculateTaskHours(task, geometry) {
switch(task.time_unit) {
case 'per_meter':
// Fx lægter: 250 løbende meter × 0.17 timer
return geometry.total_length * task.time_per_unit;
case 'per_sqm':
// Fx tagpap: 100 m² × 0.08 timer
return geometry.total_area * task.time_per_unit;
case 'per_piece':
// Fx spær: 12 styk × 0.75 timer
return geometry.count * task.time_per_unit;
case 'per_project':
// Fast tid
return task.time_per_unit;
default:
return task.estimated_hours || 0;
}
}
// Brug i tilbud
const taskHours = calculateTaskHours(task, projectGeometry);
const taskCost = taskHours * task.hourly_rate;
✅ Validering & Best Practices
✅ DO:
- Brug erfaring: Basér tid på faktisk erfaring fra tidligere projekter
- Vær realistisk: Inkluder pauser, opstilling, nedpakning
- Dokumentér: Skriv klar beskrivelse af hvad der er inkluderet
- Tilføj værktøjer: Angiv nødvendige værktøjer for planlægning
- Kobl materiale: Angiv
materialVarenrfor klar sammenhæng
❌ DON'T:
- Undgå for optimistiske tider: Husk spildtid, fejl, justeringer
- Glem ikke forberedelse: Opstilling tager også tid
- Ignorer kompleksitet: Svære forhold kræver mere tid
- Brug ikke gamle data: Opdater baseret på ny erfaring
📝 Eksempel Script: Bulk Oprettelse
// bulk-create-custom-tasks.js
const tasks = [
{
packageId: 1,
name: "Opsætning af lægter",
timeUnit: "per_meter",
timePerUnit: 0.17,
materialVarenr: "147072"
},
{
packageId: 1,
name: "Montage af spær",
timeUnit: "per_piece",
timePerUnit: 0.75
},
{
packageId: 1,
name: "Udlægning af tagpap",
timeUnit: "per_sqm",
timePerUnit: 0.08,
materialVarenr: "TAG123"
}
];
async function createTasks() {
for (const task of tasks) {
const response = await fetch('http://localhost:5001/api/smart-packages/custom-tasks', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(task)
});
const result = await response.json();
console.log(`✅ ${result.message}`);
}
}
createTasks();
🔄 Opdatering af Eksisterende Tasks
Ændre tid pr. enhed:
curl -X PUT http://localhost:5001/api/smart-packages/tasks/42 \
-H "Content-Type: application/json" \
-d '{
"name": "Opsætning af lægter",
"timePerUnit": 0.20,
"timeUnit": "per_meter"
}'
Ændre enhed type:
# Skift fra per_project til per_sqm
curl -X PUT http://localhost:5001/api/smart-packages/tasks/45 \
-H "Content-Type: application/json" \
-d '{
"timeUnit": "per_sqm",
"timePerUnit": 0.15
}'
📊 Statistik & Rapportering
Hent custom tasks grupperet på enhed:
SELECT
time_unit,
COUNT(*) as task_count,
AVG(time_per_unit) as avg_time,
MIN(time_per_unit) as min_time,
MAX(time_per_unit) as max_time
FROM smart_package_tasks
WHERE is_custom = 1
GROUP BY time_unit;
Find mest brugte custom tasks:
SELECT
t.task_name,
t.time_unit,
t.time_per_unit,
COUNT(spu.id) as times_used
FROM smart_package_tasks t
LEFT JOIN smart_package_usage spu ON t.package_id = spu.package_id
WHERE t.is_custom = 1
GROUP BY t.id
ORDER BY times_used DESC
LIMIT 10;
🎓 Tømmer Cheat Sheet
Hurtig reference til almindelige opgaver:
| Opgave | Enhed | Typisk tid | timePerUnit |
|---|---|---|---|
| Lægter opsætning | per_meter | 10 min | 0.17 |
| Spær montage | per_piece | 45 min | 0.75 |
| Tagpap udlægning | per_sqm | 5 min | 0.08 |
| Isolering | per_sqm | 8 min | 0.13 |
| Vindspær | per_meter | 12 min | 0.20 |
| Tagrender | per_meter | 15 min | 0.25 |
| Nedrivning | per_sqm | 6 min | 0.10 |
| Oprydning | per_project | 4 timer | 4.00 |
Oprettet: 2025-10-29
Version: 1.0
Status: ✅ Produktionsklar