276 lines
6.5 KiB
Markdown
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
|