Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions Dienstplan_Portable.html
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ <h2>Monatsauswertung</h2>
<h4>Berechnungsregeln (Variante 2 - Streng)</h4>
<p>
<strong>Schwelle:</strong> Gesamter Bonus wird nur gezahlt, wenn WE-Einheiten &ge; 2,0.<br>
<strong>Bei Erreichen:</strong> WT = 250 EUR/Einheit, WE = 450 EUR/Einheit (abzgl. 1,0 Einheit Abzug).<br>
<strong>Bei Erreichen:</strong> WT = 250 EUR/Einheit, WE = 450 EUR/Einheit (abzgl. 2,0 Einheiten Abzug).<br>
<strong>Unter Schwelle:</strong> Keine Auszahlung (weder WT noch WE).<br>
<strong>WE-Tage:</strong> Fr, Sa, So, Feiertage und Vortage von Feiertagen.
</p>
Expand Down Expand Up @@ -576,7 +576,7 @@ <h4 style="color: #dc3545;">Gefahrenzone</h4>
RATE_WT: 250,
RATE_WE: 450,
THRESHOLD: 2.0,
DEDUCTION: 1.0,
DEDUCTION: 2.0,
TOLERANCE: 0.0001
};

Expand Down Expand Up @@ -1071,7 +1071,7 @@ <h4 style="color: #dc3545;">Gefahrenzone</h4>
csv += 'WT;Werktag (Montag-Donnerstag ohne Feiertag/Vortag)\n';
csv += 'WE-Tag;"Freitag, Samstag, Sonntag, Feiertag oder Tag vor Feiertag"\n';
csv += 'Schwelle;"Mindestens 2,0 WE-Einheiten für Bonuszahlung erforderlich"\n';
csv += 'Sätze;"WT = 250 EUR/Einheit, WE = 450 EUR/Einheit (abzgl. 1,0 Abzug)"\n';
csv += 'Sätze;"WT = 250 EUR/Einheit, WE = 450 EUR/Einheit (abzgl. 2,0 Abzug)"\n';

// Download CSV file
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
Expand Down Expand Up @@ -1296,20 +1296,23 @@ <h5>Monat ${MONTHS[m]} ${y} mit Auszahlung Ende ${MONTHS[payoutMonth]} ${payoutY

totalBonus += bonus;

// Generate note for this employee
// Generate note for this employee - cleaner, more professional format
const safeName = this.sanitizeName(name);
let note = `<b>${safeName}</b>: `;
let note = '';

if (!thresholdReached) {
note += `Erreicht das Bonussystem nicht (nur ${we_total.toFixed(1)} WE-Einheiten, mind. 2,0 erforderlich).`;
note = `<b>${safeName}</b> erreicht die Mindestschwelle nicht (${we_total.toFixed(1)} von ${CONFIG.THRESHOLD.toFixed(1)} WE-Einheiten) und erhält daher keine Bonuszahlung.`;
} else {
const details = [];
if (data.wt > 0) details.push(`${data.wt.toFixed(1)} WT × 250€`);
if (data.we_fr > 0 || data.we_other > 0) {
const paid_we = we_total - 1.0;
details.push(`${paid_we.toFixed(1)} WE × 450€ (abzgl. 1,0 Abzug von ${deductedFrom})`);
const paid_we = we_total - CONFIG.DEDUCTION;
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code correctly uses CONFIG.DEDUCTION for calculating paid WE units, but the CONFIG constant definition on line 579 (not shown in this diff) still has DEDUCTION: 1.0 instead of DEDUCTION: 2.0. This means the portable HTML file will calculate bonuses using the old 1.0 deduction value, creating an inconsistency with all other implementations (webapp/calculator.js, Android app, Python scripts) which use 2.0. The CONFIG.DEDUCTION value needs to be updated to 2.0 to match the PR's stated purpose.

Copilot uses AI. Check for mistakes.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes were already applied in commit af4473f. CONFIG.DEDUCTION is now set to 2.0 on line 579 of Dienstplan_Portable.html, and all related text references have been updated.

let breakdown = [];
if (data.wt > 0) breakdown.push(`${data.wt.toFixed(1)} WT-Einheiten à ${CONFIG.RATE_WT} €`);
if (paid_we > 0) breakdown.push(`${paid_we.toFixed(1)} WE-Einheiten à ${CONFIG.RATE_WE} €`);

note = `<b>${safeName}</b> erhält eine Bonuszahlung von <span style="color: #28a745; font-weight: bold;">${this.formatCurrency(bonus)}</span>`;
if (breakdown.length > 0) {
note += ` (${breakdown.join(' + ')})`;
}
note += `Erhält ${this.formatCurrency(bonus)}. ${details.join(', ')}.`;
note += '.';
}
employeeNotes.push(note);

Expand Down Expand Up @@ -1370,7 +1373,7 @@ <h4>Erläuterungen zu den einzelnen Mitarbeitern:</h4>
<li><strong>Vergütung bei Erreichen der Schwelle:</strong>
<ul>
<li>Werktage (WT): 250 € pro Einheit</li>
<li>WE-Tage: 450 € pro Einheit (abzüglich 1,0 Einheit Abzug, Freitag zuerst)</li>
<li>WE-Tage: 450 € pro Einheit (abzüglich 2,0 Einheiten Abzug, Freitag zuerst)</li>
</ul>
</li>
<li><strong>Unter Schwelle:</strong> Keine Bonuszahlung (weder WT noch WE)</li>
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Die Datei landet in `output/Dienstplan_YYYY_MM_NRW.xlsx`.

- **WE-Tag**: Fr/Sa/So + Feiertag + Vortag Feiertag
- **WT-Tag**: Alle anderen Tage (250 € pro Einheit)
- **WE-Vergütung**: Nur wenn Monatssumme ≥ 2,0 WE-Einheiten → 450 €/Einheit, dann Abzug 1,0 (zuerst von Freitag)
- **WE-Vergütung**: Nur wenn Monatssumme ≥ 2,0 WE-Einheiten → 450 €/Einheit, dann Abzug 2,0 (zuerst von Freitag)
- **Unter Schwelle**: WE-Dienste = 0 € (nicht als WT vergütet)

Details siehe `SPECIFICATION.md`.
Expand Down
20 changes: 10 additions & 10 deletions SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Stand: 14.11.2025 (Deutschland)

## Ziel

Diese README beschreibt vollständig, wie eine Excel-Arbeitsmappe aufgebaut wird, die Monatsdienste erfasst und automatisch die Vergütung ermittelt – inkl. Erkennung von Wochenend-/Feiertagsdiensten (inkl. Vortag), Schwellenlogik und Abzug 1,0 WE-Einheit. Variante 2 (streng) ist aktiv: WE-Dienste werden nur vergütet, wenn im Monat mindestens 2,0 WE-Einheiten erreicht werden; sonst 0 €. Wochentage (kein WE) werden stets vergütet.
Diese README beschreibt vollständig, wie eine Excel-Arbeitsmappe aufgebaut wird, die Monatsdienste erfasst und automatisch die Vergütung ermittelt – inkl. Erkennung von Wochenend-/Feiertagsdiensten (inkl. Vortag), Schwellenlogik und Abzug 2,0 WE-Einheiten nach Erreichen der Schwelle. Variante 2 (streng) ist aktiv: WE-Dienste werden nur vergütet, wenn im Monat mindestens 2,0 WE-Einheiten erreicht werden; sonst 0 €. Wochentage (kein WE) werden ebenfalls nur bei Erreichen der WE-Schwelle vergütet.
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While line 7 correctly states "Abzug 2,0 WE-Einheiten" for the main description, the SPECIFICATION.md file contains multiple test cases and references later in the document (lines 282, 285, 288, 291, 303, 305, 327, 332) that still reference "Abzug 1,0" instead of "Abzug 2,0". These sections are not included in this PR's changes but should be updated in a follow-up to ensure consistency across the entire specification document. The test cases will produce incorrect expected values with a 1.0 deduction when the actual implementation uses 2.0.

Copilot uses AI. Check for mistakes.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes were already applied in commit af4473f. All SPECIFICATION.md test cases (lines 282, 285, 288, 291, 303, 305, 327, 332) now use Abzug 2,0 instead of Abzug 1,0.


Hinweise:
- Region: Deutschland, Bundesland wählbar (steuert Feiertage).
Expand Down Expand Up @@ -279,17 +279,17 @@ Beispiel-Formel (als hilfsweise Matrix in Checks):
A hat 1,75 WE und 1,0 WT → Auszahlung_WE = 0 €; Auszahlung_WT = 0 €; Auszahlung_Gesamt = 0 €.

2) **Genau Schwelle**:
A hat 2,0 WE (Fr 1,0 + Sa 1,0) → Abzug 1,0 (zuerst Fr) → WE_bezahlt = 1,0 → 450 €.
A hat 2,0 WE (Fr 1,0 + Sa 1,0) → Abzug 2,0 (zuerst Fr) → WE_bezahlt = 0,0 → 0 €.

3) **Über Schwelle ohne Freitag**:
A hat 2,0 WE (nur Sa+So) → Abzug 1,0 aus „Andere" → WE_bezahlt = 1,0 → 450 €.
A hat 2,0 WE (nur Sa+So) → Abzug 2,0 aus „Andere" → WE_bezahlt = 0,0 → 0 €.

4) **Starke Überdeckung**:
A hat 3,5 WE → Abzug 1,0 → WE_bezahlt = 2,5 → 2,5×450 €.
A hat 3,5 WE → Abzug 2,0 → WE_bezahlt = 1,5 → 1,5×450 € = 675 €.

5) **Splits rund um 2,0**:
A hat Fr 0,4 + Sa 0,6 + So 1,0 → Summe 2,0 → Abzug 1,0
(0,4 von Fr, 0,6 von Andere) → WE_bezahlt = 1,0 → 450 €.
A hat Fr 0,4 + Sa 0,6 + So 1,0 → Summe 2,0 → Abzug 2,0
(0,4 von Fr, 1,6 von Andere) → WE_bezahlt = 0,0 → 0 €.

6) **Unter Schwelle, nur WE-Tage**:
A hat 1,0 WE, 0 WT → Auszahlung_WE = 0 €; Auszahlung_Gesamt = 0 €.
Expand All @@ -300,9 +300,9 @@ Beispiel-Formel (als hilfsweise Matrix in Checks):

## Edge-Cases und Präzisierungen

- Abzug nur einmal pro Person/Monat (fix 1,0), und nur wenn Schwelle erreicht.
- Abzug nur einmal pro Person/Monat (fix 2,0), und nur wenn Schwelle erreicht.
- Der Vortag eines Feiertags ist WE-Tag – unabhängig davon, welcher Wochentag er ist.
- Wenn WE_Freitag < 1,0, wird der restliche Abzug (bis 1,0) von WE_Andere genommen.
- Wenn WE_Freitag < 2,0, wird der restliche Abzug (bis 2,0) von WE_Andere genommen.
- Monatswechsel: Daten genau per >=Monat_Auswahl und <=EOMONAT(Monat_Auswahl;0) filtern.
- Rundungstoleranz 1e-4 bei Schwelle und Datumssummen (Splits wie 0,33/0,67).
- Tabellen-Namen („tblPlan", „tblFeiertage", „tblAuswertung") konsequent verwenden.
Expand All @@ -324,11 +324,11 @@ Lieferumfang (empfohlen):
- 18.11.2025: Korrektur Variante 2: **Gesamter Bonus (WT + WE) wird nur gezahlt, wenn WE_Summe ≥ 2,0**.
Unter Schwelle: Auszahlung_Gesamt = 0 € (weder WT noch WE).
- 14.11.2025: Umstellung auf Variante 2 (streng). WE-Vergütung nur bei WE_Summe ≥ 2,0,
anschließend Abzug 1,0 (Freitag zuerst). Unterhalb der Schwelle: WE-Auszahlung = 0 €.
anschließend Abzug 2,0 (Freitag zuerst). Unterhalb der Schwelle: WE-Auszahlung = 0 €.
- 13.11.2025: Vorversion (Variante 1) mit WE-Auszahlung ab erstem WE-Dienst und Abzug nach Schwelle (ersetzt).

## Kurztext (für Blatt „Regeln" als Readme-Hinweis)

„WE-Tag = Fr/Sa/So/Feiertag/Vortag (BL-abhängig). Variante 2 (streng): Gesamter Bonus (WT + WE) wird nur gezahlt, wenn im Monat ≥ 2,0 WE-Einheiten erreicht werden. Bei Erreichen der Schwelle: WT 250 €/Einheit, WE 450 €/Einheit mit Abzug 1,0 (Freitag zuerst). Unter Schwelle: 0 € Auszahlung. Splits anteilig. Monat und Bundesland oben wählen."
„WE-Tag = Fr/Sa/So/Feiertag/Vortag (BL-abhängig). Variante 2 (streng): Gesamter Bonus (WT + WE) wird nur gezahlt, wenn im Monat ≥ 2,0 WE-Einheiten erreicht werden. Bei Erreichen der Schwelle: WT 250 €/Einheit, WE 450 €/Einheit mit Abzug 2,0 (Freitag zuerst). Unter Schwelle: 0 € Auszahlung. Splits anteilig. Monat und Bundesland oben wählen."

— Ende der README —
4 changes: 2 additions & 2 deletions android-app/IMPLEMENTATION_SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ Implements NRW Variante 2 (streng) rules:
#### Unit Tests (PayrollCalculatorTest.kt)
Comprehensive test coverage including:
1. **Under threshold test**: 1.75 WE + 1.0 WT → WE payout 0€, WT payout 250€
2. **Exactly at threshold test**: 2.0 WE → WE payout 450€ (1.0 unit after deduction)
3. **Over threshold test**: 3.5 WE → WE payout 1125€ (2.5 units after deduction)
2. **Exactly at threshold test**: 2.0 WE → WE payout 0€ (0.0 units after 2.0 deduction)
3. **Over threshold test**: 3.5 WE → WE payout 675€ (1.5 units after 2.0 deduction)
4. **Friday deduction priority test**: Verifies deduction comes from Friday first
5. **Multiple employees test**: Separate calculations per employee

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import kotlin.math.min
* Business rules:
* - WE-Tag (Weekend/Holiday): Friday, Saturday, Sunday, public holiday, day before public holiday
* - WT-Tag (Weekday): All other days
* - WT compensation: Always 250€ per unit
* - WT compensation: 250€ per unit (only if threshold reached)
* - WE compensation: Only paid if monthly total >= 2.0 WE units (threshold)
* - If threshold reached: 450€ per WE unit, then deduct exactly 2.0 WE units
* - Deduction priority: Friday first, then other WE days
* - Below threshold: 0€ for WE shifts (NOT converted to WT)
* - Below threshold: 0€ for all shifts (neither WT nor WE)
*/
class PayrollCalculator {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class PayrollCalculatorTest {

/**
* Test Case 2: Exactly at threshold (2.0 WE)
* Expected: WE payout = 0€ (0.0 units after deduction), threshold reached
* Expected: WE payout = 0€ (0.0 units after 2.0 deduction), threshold reached
*/
@Test
fun testExactlyAtThreshold() {
Expand All @@ -74,7 +74,7 @@ class PayrollCalculatorTest {

/**
* Test Case 3: Over threshold (3.5 WE)
* Expected: WE payout = 675€ (1.5 units after deduction)
* Expected: WE payout = 675€ (1.5 units after 2.0 deduction)
*/
@Test
fun testOverThreshold() {
Expand Down Expand Up @@ -117,6 +117,7 @@ class PayrollCalculatorTest {
assertEquals(0.4, result.deductionFriday, 0.001) // All Friday deducted first
assertEquals(1.6, result.deductionOther, 0.001) // Rest from other (1.6 to reach 2.0 total)
assertEquals(0.0, result.wePaid, 0.001)
assertEquals(0.0, result.payoutWE, 0.001)
}

/**
Expand Down Expand Up @@ -144,7 +145,7 @@ class PayrollCalculatorTest {
assertFalse(resultA.thresholdReached)
assertEquals(0.0, resultA.payoutWE, 0.001)

// B: above threshold
// B: above threshold (2.5 WE - 2.0 deduction = 0.5 paid)
assertTrue(resultB.thresholdReached)
assertEquals(2.5, resultB.weTotal, 0.001)
assertEquals(0.5, resultB.wePaid, 0.001)
Expand Down
15 changes: 5 additions & 10 deletions claude.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ Die ältere Implementierung nutzt eine andere Logik:
- **WE-Tag** (Weekend): Fr-So + Feiertag + Vortag Feiertag

2. **Bonusberechnung**:
- **WT-Tage** werden **immer** mit 250€ vergütet
- **WT-Tage** werden bei Erreichen der Schwelle mit 250€ vergütet
- **WE-Tage** nur vergütet wenn ≥ 2.0 WE-Einheiten:
- Bei Erreichen: 450€ pro WE-Tag
- Dann Abzug von 2.0 WE-Einheiten (Freitag-Priorität)
- Unter Schwellenwert: WE-Dienste = 0€ (nicht als WT vergütet)
- Unter Schwellenwert: Keine Bonuszahlung (weder WE noch WT)

### Wichtiger Unterschied - Beispiel

Expand Down Expand Up @@ -203,18 +203,13 @@ this.RATE_WEEKEND = 500; // Statt 450
```

### Abzug ändern (Web-App)
Aktuell ist der Abzug fest auf 2.0 kodiert in `webapp/calculator.js`, Zeile 112:
```javascript
qualifyingDaysDeducted = 2.0;
```

Um dies flexibel zu machen, könnte man hinzufügen:
Der Abzug ist als Konstante in `webapp/calculator.js` definiert:
```javascript
this.DEDUCTION_AMOUNT = 2.0; // Im Constructor
// Dann verwenden:
qualifyingDaysDeducted = this.DEDUCTION_AMOUNT;
```

Um den Abzugswert zu ändern, einfach diesen Wert anpassen.

## Code-Architektur

### Web-App (MVC-ähnlich)
Expand Down
2 changes: 1 addition & 1 deletion src/build_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def _populate_readme(ws):
rules = [
"WE-Tag = Fr/Sa/So/Feiertag/Vortag (BL-abhängig).",
"Variante 2 (streng): WE werden nur vergütet, wenn im Monat ≥ 2,0 WE-Einheiten erreicht werden;",
"dann 450 €/WE und Abzug 2,0 (Freitag zuerst). WT werden immer mit 250 € vergütet.",
"dann 450 €/WE und Abzug 2,0 (Freitag zuerst). WT werden bei Erreichen der WE-Schwelle mit 250 € vergütet.",
"Splits anteilig. Monat und Bundesland in 'Regeln' wählen.",
"",
"Schritte:",
Expand Down
2 changes: 1 addition & 1 deletion webapp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Eine Web-Anwendung zur Berechnung von Bonuszahlungen für Wochenend- und Feierta

### Bonusberechnung
1. **Schwellenwert**: Mindestens **2.0 qualifizierende Tage** im Monat erforderlich
2. **Abzug**: Bei Erreichen des Schwellenwerts werden **2.0 qualifizierende Tage** abgezogen
2. **Abzug**: Bei Erreichen des Schwellenwerts werden **2.0 qualifizierende Tage** abgezogen (Freitag-Priorität)
3. **Vergütung**:
- Normale Tage: **250€** pro Tag
- Qualifizierende Tage (WE/Feiertag): **450€** pro Tag
Expand Down
4 changes: 2 additions & 2 deletions webapp/TEST_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ Dienste:

Erwartung:
- Normale Tage: 0.5 × 250€ = 125€
- Qualifizierende Tage: (2.5 - 1.0) × 450€ = 675
- Gesamt: 800
- Qualifizierende Tage: (2.5 - 2.0) × 450€ = 225
- Gesamt: 350
```

## Tests erweitern
Expand Down
27 changes: 15 additions & 12 deletions webapp/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ class DienstplanApp {
csv += 'WE/Feiertag Tage;"Freitag, Samstag, Sonntag, Feiertag oder Tag vor Feiertag"\n';
csv += 'Schwelle;"Mindestens 2,0 WE-Einheiten für Bonuszahlung erforderlich"\n';
csv += 'Sätze;"Normale Tage = 250 EUR/Einheit, WE/Feiertag = 450 EUR/Einheit"\n';
csv += 'Abzug;"Bei Erreichen der Schwelle wird 1,0 WE-Einheit abgezogen"\n';
csv += 'Abzug;"Bei Erreichen der Schwelle werden 2,0 WE-Einheiten abgezogen"\n';

// Download CSV file
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
Expand Down Expand Up @@ -738,7 +738,7 @@ class DienstplanApp {

if (thresholdReached) {
const wt_pay = data.wt * this.calculator.RATE_NORMAL;
let deduct = 1.0;
let deduct = this.calculator.DEDUCTION_AMOUNT;
const deduct_fr = Math.min(deduct, data.we_fr);
const deduct_other = Math.max(0, deduct - deduct_fr);
const paid_fr = Math.max(0, data.we_fr - deduct_fr);
Expand All @@ -757,20 +757,23 @@ class DienstplanApp {

totalBonus += bonus;

// Generate note
// Generate note - cleaner, more professional format
const safeName = escapeHtml(name);
let note = `<b>${safeName}</b>: `;
let note = '';

if (!thresholdReached) {
note += `Erreicht das Bonussystem nicht (nur ${we_total.toFixed(1)} WE-Einheiten, mind. 2,0 erforderlich).`;
note = `<b>${safeName}</b> erreicht die Mindestschwelle nicht (${we_total.toFixed(1)} von ${this.calculator.MIN_QUALIFYING_DAYS.toFixed(1)} WE-Einheiten) und erhält daher keine Bonuszahlung.`;
} else {
const details = [];
if (data.wt > 0) details.push(`${data.wt.toFixed(1)} WT × 250€`);
if (data.we_fr > 0 || data.we_other > 0) {
const paid_we = we_total - 1.0;
details.push(`${paid_we.toFixed(1)} WE × 450€ (abzgl. 1,0 Abzug von ${deductedFrom})`);
const paid_we = we_total - this.calculator.DEDUCTION_AMOUNT;
let breakdown = [];
if (data.wt > 0) breakdown.push(`${data.wt.toFixed(1)} WT-Einheiten à ${this.calculator.RATE_NORMAL} €`);
if (paid_we > 0) breakdown.push(`${paid_we.toFixed(1)} WE-Einheiten à ${this.calculator.RATE_WEEKEND} €`);

note = `<b>${safeName}</b> erhält eine Bonuszahlung von <span style="color: #28a745; font-weight: bold;">${this.calculator.formatCurrency(bonus)}</span>`;
if (breakdown.length > 0) {
note += ` (${breakdown.join(' + ')})`;
}
note += `Erhält ${this.calculator.formatCurrency(bonus)}. ${details.join(', ')}.`;
note += '.';
}
employeeNotes.push(note);

Expand Down Expand Up @@ -832,7 +835,7 @@ class DienstplanApp {
<li><strong>Vergütung bei Erreichen der Schwelle:</strong>
<ul>
<li>Werktage (WT): 250 € pro Einheit</li>
<li>WE-Tage: 450 € pro Einheit (abzüglich 1,0 Einheit Abzug, Freitag zuerst)</li>
<li>WE-Tage: 450 € pro Einheit (abzüglich 2,0 Einheiten Abzug, Freitag zuerst)</li>
</ul>
</li>
<li><strong>Unter Schwelle:</strong> Keine Bonuszahlung (weder WT noch WE)</li>
Expand Down
5 changes: 3 additions & 2 deletions webapp/calculator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class BonusCalculator {
this.RATE_NORMAL = 250; // Normal day rate (not weekend/holiday)
this.RATE_WEEKEND = 450; // Weekend/holiday rate
this.MIN_QUALIFYING_DAYS = 2.0; // Minimum qualifying days to trigger bonus
this.DEDUCTION_AMOUNT = 2.0; // Deduction after reaching threshold
}

/**
Expand Down Expand Up @@ -108,8 +109,8 @@ class BonusCalculator {
let totalDeduction = 0;

if (thresholdReached) {
// Deduct 2.0 qualifying days with Friday priority
totalDeduction = 2.0;
// Deduct qualifying days with Friday priority
totalDeduction = this.DEDUCTION_AMOUNT;

// First deduct from Friday
deductionFromFriday = Math.min(totalDeduction, qualifyingDaysFriday);
Expand Down
Loading
Loading