Files
tilbudgivern/docs/features/MARKUP_SLIDER_SYSTEM.md
T
2025-10-30 18:28:58 +00:00

276 lines
6.5 KiB
Markdown

# 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:
```sql
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:**
```json
{
"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:**
```json
{
"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
```jsx
<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
```jsx
<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
```javascript
// 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
```javascript
// 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
```javascript
// 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:
```bash
node test-markup-sliders.js
```
Dette tester 4 scenarier:
1. Standard (20% + 2%)
2. Lav margin (10% + 1%)
3. Høj margin (30% + 5%)
4. Ingen final markup (20% + 0%)
---
## 🔄 Næste Skridt
1. **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
2. **Quote Management**
- Gem markup værdier når quote opdateres
- Hent markup værdier når quote loades
- Vis aktuel markup i quote oversigt
3. **Material Import**
- Import Bygma materialer med korrekte indkøbspriser
- Så markup kan beregnes på reelle priser
4. **Rapportering**
- Vis markup breakdown i PDF tilbud
- Vis profit margin i analytics
- Track gennemsnitlig markup per kunde/projekt