6.5 KiB
6.5 KiB
Markup Slider System for SmartPackages
📊 Oversigt
SmartPackage systemet understøtter nu to niveauer af markup som kan justeres individuelt for hvert tilbud:
1. Material Markup Slider 💰
- Standard: 20%
- Justerbar: 0% - 50%
- Placering: Ved tilføjelse af SmartPackage til tilbud
- Anvendelse: Påføres alle materialer fra pakken
- Gemt i:
quotes.material_markup_percent
2. Final Review Markup Slider 📈
- Standard: 2%
- Justerbar: 0% - 10%
- Placering: I final review trinnet
- Anvendelse: Påføres på subtotal (materialer + arbejde)
- Gemt i:
quotes.final_review_markup_percent
🔧 Database Struktur
Nye felter i quotes tabel:
ALTER TABLE quotes
ADD COLUMN material_markup_percent DECIMAL(5,2) DEFAULT 20.00
COMMENT 'Material markup procent (standard 20%)',
ADD COLUMN final_review_markup_percent DECIMAL(5,2) DEFAULT 2.00
COMMENT 'Final review markup procent (standard 2%)';
🔌 API Endpoint
POST /api/smart-packages/:id/calculate-with-geometry
Request body:
{
"projectId": 123, // Optional: Hent geometri og markup fra database
"geometry": { // Optional: Brug custom geometri
"length_main": 15,
"width_main": 10,
"total_area": 85,
"nedløb_antal": 4
},
"materialMarkupPercent": 20, // Optional: Override material markup
"finalReviewMarkupPercent": 2 // Optional: Override final review markup
}
Response:
{
"success": true,
"package": {
"id": 97,
"name": "Tagrende med Konsoljern"
},
"materials": [
{
"varenr": "077424",
"name": "Tagrende 3m",
"quantity": 5,
"base_price": 150.00, // Indkøbspris
"price": 180.00, // Med markup (150 * 1.20)
"markup_percent": 20
}
],
"markup": {
"material_markup_percent": 20,
"final_review_markup_percent": 2,
"final_review_amount": 87.00
},
"totals": {
"material_cost": 900.00, // Med material markup
"labor_cost": 4350.00,
"subtotal": 5250.00,
"final_review_markup": 87.00, // 2% af subtotal
"total_cost": 5337.00 // Alt inkluderet
}
}
💡 Beregningseksempler
Eksempel 1: Standard (20% + 2%)
Materialer (indkøb): 750 kr
+ Material markup (20%): +150 kr
= Materialer til kunde: 900 kr
Arbejde: 4350 kr
─────────────────────────
Subtotal: 5250 kr
+ Final review markup (2%): +105 kr
═════════════════════════
TOTAL: 5355 kr
Eksempel 2: Lav margin (10% + 1%)
Materialer (indkøb): 750 kr
+ Material markup (10%): +75 kr
= Materialer til kunde: 825 kr
Arbejde: 4350 kr
─────────────────────────
Subtotal: 5175 kr
+ Final review markup (1%): +51.75 kr
═════════════════════════
TOTAL: 5226.75 kr
Eksempel 3: Høj margin (30% + 5%)
Materialer (indkøb): 750 kr
+ Material markup (30%): +225 kr
= Materialer til kunde: 975 kr
Arbejde: 4350 kr
─────────────────────────
Subtotal: 5325 kr
+ Final review markup (5%): +266.25 kr
═════════════════════════
TOTAL: 5591.25 kr
🎨 UI Implementation Guide
1. Material Markup Slider
Placering: Når bruger tilføjer SmartPackage til tilbud
<div className="markup-control">
<label>Material Markup</label>
<input
type="range"
min="0"
max="50"
value={materialMarkup}
onChange={(e) => setMaterialMarkup(e.target.value)}
/>
<span>{materialMarkup}%</span>
<p className="help-text">
Avance på materialer (standard: 20%)
</p>
</div>
Når skal den vises:
- Ved tilføjelse af SmartPackage til tilbud
- I tilbudsredigering
- Som standard værdi ved oprettelse af nyt tilbud
2. Final Review Markup Slider
Placering: I final review trinnet før tilbuddet sendes
<div className="final-markup-control">
<label>Final Review Markup</label>
<input
type="range"
min="0"
max="10"
step="0.1"
value={finalReviewMarkup}
onChange={(e) => setFinalReviewMarkup(e.target.value)}
/>
<span>{finalReviewMarkup}%</span>
<p className="help-text">
Ekstra margin på total pris (standard: 2%)
</p>
<div className="markup-preview">
<p>Subtotal: {formatCurrency(subtotal)}</p>
<p>Final markup (+{finalReviewMarkup}%): {formatCurrency(finalMarkupAmount)}</p>
<p className="total">Total: {formatCurrency(total)}</p>
</div>
</div>
Når skal den vises:
- I final review trinnet
- Kun hvis brugeren vil justere den
- Kan være skjult bag "Avancerede indstillinger"
📝 Workflow
Trin 1: Opret tilbud
// Når tilbud oprettes, sæt default markup værdier
const newQuote = {
customer_name: "Kunde Navn",
material_markup_percent: 20.00, // Default
final_review_markup_percent: 2.00 // Default
};
Trin 2: Tilføj SmartPackage
// Bruger kan justere material markup
const addPackageResponse = await axios.post(
`/api/smart-packages/97/calculate-with-geometry`,
{
projectId: quoteId,
materialMarkupPercent: 25 // Bruger satte 25%
}
);
// Gem i quote
await axios.put(`/api/quotes/${quoteId}`, {
material_markup_percent: 25
});
Trin 3: Final Review
// Bruger kan justere final review markup
const updateFinalMarkup = async (newMarkup) => {
await axios.put(`/api/quotes/${quoteId}`, {
final_review_markup_percent: newMarkup
});
// Genberegn totals
await recalculateTotals();
};
✅ Test
Kør test script:
node test-markup-sliders.js
Dette tester 4 scenarier:
- Standard (20% + 2%)
- Lav margin (10% + 1%)
- Høj margin (30% + 5%)
- Ingen final markup (20% + 0%)
🔄 Næste Skridt
-
Frontend Implementation
- Tilføj material markup slider ved package tilføjelse
- Tilføj final review markup slider i review trin
- Vis markup breakdown tydeligt i UI
-
Quote Management
- Gem markup værdier når quote opdateres
- Hent markup værdier når quote loades
- Vis aktuel markup i quote oversigt
-
Material Import
- Import Bygma materialer med korrekte indkøbspriser
- Så markup kan beregnes på reelle priser
-
Rapportering
- Vis markup breakdown i PDF tilbud
- Vis profit margin i analytics
- Track gennemsnitlig markup per kunde/projekt