diff --git a/README.md b/README.md index 686aa29..67069c1 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,19 @@ Die deutschen Monatsabkürzungen entsprechen den Tabellenblatt-Namen in der Exce | `Nov` | November | | `Dez` | Dezember | +### Sonderfall `P = Praktikum` + +Wenn im Excel-Sheet für einen Tag `P` steht, bleibt der Status im PDF `P`, aber die Stundenfelder werden mit 6 Stunden befüllt: + +| Feld | Wert | +|---|---| +| `anwesend.N` | `P` | +| `ist.N` | `6,00` | +| `plan.N` | `6` | +| `pauschale_5.N` | `1` | + +`P = Praktikum` wird damit wie ein regulärer Anwesenheitstag mit 6 Stunden abgerechnet und zählt auch für die 5-Euro-Pauschale. + --- ## Ausgabe diff --git a/src/pdf_filler.py b/src/pdf_filler.py index 07a9e9d..f87a5bd 100644 --- a/src/pdf_filler.py +++ b/src/pdf_filler.py @@ -59,6 +59,8 @@ def build_field_dict( datum_field: creation_date.strftime("%d.%m.%Y"), } + internship_hours = f"{plan_threshold:.2f}".replace(".", ",") + qualifying_attendance_count: int = 0 pauschale_5_count: int = 0 for idx, entry in enumerate(attendance.entries): @@ -68,12 +70,20 @@ def build_field_dict( if entry.is_present: fields[f"ist.{idx}"] = entry.hours_german() fields[f"plan.{idx}"] = plan_value + if entry.hours is not None and entry.hours >= plan_threshold: + qualifying_attendance_count += 1 # Pauschale only if actual hours >= planned threshold if entry.hours is not None and entry.hours >= plan_threshold: fields[f"{pauschale_prefix}.{idx}"] = pauschale_present_value pauschale_5_count += 1 else: fields[f"{pauschale_prefix}.{idx}"] = "0" + elif entry.status == "P": + fields[f"ist.{idx}"] = internship_hours + fields[f"plan.{idx}"] = plan_value + qualifying_attendance_count += 1 + fields[f"{pauschale_prefix}.{idx}"] = pauschale_present_value + pauschale_5_count += 1 else: fields[f"ist.{idx}"] = "" fields[f"plan.{idx}"] = "" @@ -86,7 +96,7 @@ def build_field_dict( fields["pauschale_5_sum"] = f"{pauschale_5_euro:.2f}" fields["pauschale_25_sum"] = "0.00" fields["pauschale_sum"] = f"{pauschale_5_euro:.2f}" - fields["anwesend_sum"] = str(pauschale_5_count) + fields["anwesend_sum"] = str(qualifying_attendance_count) return fields diff --git a/tests/test_pdf_filler.py b/tests/test_pdf_filler.py index 36d6bb9..7d7ece1 100644 --- a/tests/test_pdf_filler.py +++ b/tests/test_pdf_filler.py @@ -128,21 +128,30 @@ class TestAbsentDay: fields = build_field_dict(_make_attendance(_absent(4, status)), cfg, date(2026, 2, 1)) assert fields["anwesend.0"] == status - @pytest.mark.parametrize("status", ["K", "KK", "E", "F", "P", "U"]) + @pytest.mark.parametrize("status", ["K", "KK", "E", "F", "U"]) def test_ist_empty(self, cfg, status): fields = build_field_dict(_make_attendance(_absent(4, status)), cfg, date(2026, 2, 1)) assert fields["ist.0"] == "" - @pytest.mark.parametrize("status", ["K", "KK", "E", "F", "P", "U"]) + @pytest.mark.parametrize("status", ["K", "KK", "E", "F", "U"]) def test_plan_empty(self, cfg, status): fields = build_field_dict(_make_attendance(_absent(4, status)), cfg, date(2026, 2, 1)) assert fields["plan.0"] == "" - @pytest.mark.parametrize("status", ["K", "KK", "E", "F", "P", "U"]) + @pytest.mark.parametrize("status", ["K", "KK", "E", "F", "U"]) def test_pauschale_empty(self, cfg, status): fields = build_field_dict(_make_attendance(_absent(4, status)), cfg, date(2026, 2, 1)) assert fields["pauschale_5.0"] == "0" + def test_praktikum_sets_fixed_hours(self, cfg): + fields = build_field_dict(_make_attendance(_absent(4, "P")), cfg, date(2026, 2, 1)) + assert fields["ist.0"] == "6,00" + assert fields["plan.0"] == "6" + + def test_praktikum_sets_pauschale(self, cfg): + fields = build_field_dict(_make_attendance(_absent(4, "P")), cfg, date(2026, 2, 1)) + assert fields["pauschale_5.0"] == "1" + # --------------------------------------------------------------------------- # Multi-row indexing @@ -177,6 +186,17 @@ class TestSummaryFields: # Day 1 (6h) and day 2 (7h) qualify, day 3 (5h) does not assert fields["anwesend_sum"] == "2" + def test_anwesend_sum_counts_praktikum_as_6h(self, cfg): + entries = [_present(1, 6.0), _absent(2, "P"), _present(3, 5.0)] + fields = build_field_dict(_make_attendance(*entries), cfg, date(2026, 2, 1)) + assert fields["anwesend_sum"] == "2" + + def test_praktikum_increases_pauschale_sum(self, cfg): + entries = [_absent(1, "P")] + fields = build_field_dict(_make_attendance(*entries), cfg, date(2026, 2, 1)) + assert fields["pauschale_5_sum"] == "8.60" + assert fields["pauschale_sum"] == "8.60" + def test_pauschale_5_sum_euro(self, cfg): """pauschale_5_sum = qualifying days * 8.60 (period decimal for JS).""" entries = [_present(1, 6.0), _present(2, 7.0), _present(3, 5.0)]