Files
odoo-at-payroll/addons/l10n_at_hr_payroll/tests/test_sozialversicherung.py
T
fegger a2a823ad35 [IMP] l10n_at_hr_payroll: GP4 SV/DB-Kern (DG-Beiträge, Geringfügigkeit, § 49, Beitragsmonat, DAG)
AP4-Kernbau (D3-Vorfinanzierung, freigegebener GP4-Bauplan): Die
Dienstgeberseite der Sozialversicherung wird sektorneutral im Kern
gebaut, damit sowohl das General-AT-Produkt als auch die GemBG-Schiene
sie konsumieren (keine Fork-Werte, payroll-Skill-Architekturregel).

Neu in models/sozialversicherung.py:
- SVDG laufend (ÖGK Normalbetriebe 2026: 20,98 %; Wien 21,23 %) und auf
  Sonderzahlungen (§ 54 ASVG: 20,48 % inkl. UV 1,10 und IESG 0,10);
- Geringfügigkeit § 5 Abs 2 ASVG mit Hochrechnung bei untermonatiger
  Beschäftigung (SZ zählen nicht) und §-53a-Abs-1-UV als Monatspauschale;
- beitragsfreie Bezüge § 49 Abs 3 ASVG als Jahres-Kumulative je DN
  (8 €/AT, 1.000/365/186/300/2.000 €/J, Homeoffice 3 €/Tag × 100);
- altersabhängige Satzausschaltungen als Stichtags-Datumfelder am
  Vertrag: AlVG § 1 Abs 2 lit e (AV DN+DG und IESG), ASVG § 51 Abs 6
  (UV ab 60/Lehrlinge), § 51 Abs 7 (PV in der Bonusphase je hälftig
  DG+DN), FLAG § 41 Abs 4 lit f (LNK-Freiheit ab 60);
- ALV-DN-Staffel § 2a AMPFG, WF-Satzvektor Bundesland × Jahr (Wien
  0,75/0,75 ab 1.1.2026, löst die KB-Protokollnotiz), Beitragsmonats-
  Allokation (Anspruchsprinzip: Sätze/HBG historisch je Gruppe) und
  DAG-Bewertung § 1 DAG (19,4 %, Schwelle 1,5 × GFG, ≥ 2 Geringfügige).

Quellenverifikation (verbindlich): ÖGK-Beitragstarifsystem gültig ab
01.07.2026, TASY-LSWH-Export 2026-03-24, Beitragsrechtliche Werte 2026
und RIS-Normtexte. GFG 2026 = 551,10 € (Aufwertung ausgesetzt gem.
§ 810 Abs 3 ASVG — löst KB-Konflikt A7-Rest); §-19a-Selbstversicherung
2026 = 83,49 €/Monat, DG-UV daraus abgeleitet 6,50 €/Monat.

Rechtskorrektur § 2a AMPFG: Die Staffel mindert nur den DN-Anteil
(ÖGK-Abschläge 'Mind. AV auf 0/1/2 %') und gilt auch für SZ-Beiträge;
bei 2.059,41 € BG sinkt DN-SV von pauschal 18,07 % auf 15,12 %.
test_lohnsteuer wurde entsprechend angepasst (Rechenfälle RF-L1 ff.).

Tests: test_sozialversicherung (14 Fälle); Suite 74/74 grün auf
odoo_dev. Rechenfälle: l10n_at_hr_payroll_private/docs/rechenfaelle/
sozialversicherung.md.
2026-09-11 23:21:55 +02:00

400 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Part of the odoo-at-payroll project. License: LGPL-3.
"""GP4 SV/DB-Kern: DG-Beiträge (ÖGK 2026), SZ-Beiträge (§ 54 ASVG),
Geringfügigkeit (§ 5 Abs 2 iVm § 810 Abs 3 ASVG) + §-53a-UV,
beitragsfreie Bezüge § 49 Abs 3 mit Jahres-Kumulativen, Altersstichtage
(AlVG § 1 Abs 2 lit e, ASVG § 51 Abs 6/7, IESG § 12), ALV-DN-Staffel
(§ 2a AMPFG), Beitragsmonats-Allokation und DAG (§ 1 DAG). Rechenfälle
s. addons/l10n_at_hr_payroll_private/docs/rechenfaelle/
sozialversicherung.md und RECHTSQUELLEN-Privat Abschnitt 4."""
from datetime import date, timedelta
from odoo.tests import TransactionCase, tagged
@tagged('post_install', '-at_install')
class SozialversicherungTest(TransactionCase):
def setUp(self):
super().setUp()
self.category = self.env['hr.salary.rule.category'].create({
'name': 'Test AT SV',
'code': 'TEST_AT_SV',
})
self.structure_type = self.env['hr.payroll.structure.type'].create({
'name': 'Test AT Kern Type',
})
self.structure = self.env['hr.payroll.structure'].create({
'name': 'Test AT SV',
'code': 'TEST_AT_SV',
'type_id': self.structure_type.id,
})
def _struktur(self, code):
"""Eigene Structure je Testfall-Stufe (Regeln kumulieren auf
geteilten Structures — Muster test_lohnsteuer.py)."""
return self.env['hr.payroll.structure'].create({
'name': 'Test AT %s' % code,
'code': 'TEST_AT_%s' % code,
'type_id': self.structure_type.id,
})
def _regel(self, code, betrag, bemessung='laufend', sv49='keine',
beitragsmonat=None, quantity='1.0', struct=None):
return self.env['hr.salary.rule'].create({
'name': code,
'code': code,
'struct_id': (struct or self.structure).id,
'category_id': self.category.id,
'condition_select': 'none',
'l10n_at_bemessung': bemessung,
'l10n_at_sv49_frei': sv49,
'l10n_at_beitragsmonat': beitragsmonat,
'amount_select': 'fix',
'amount_fix': betrag,
'quantity': quantity,
})
def _employee(self, version_vals=None):
employee = self.env['hr.employee'].create({'name': 'Test SV'})
version = self.env['hr.version'].search(
[('employee_id', '=', employee.id)], limit=1)
if not version:
version = self.env['hr.version'].create({
'employee_id': employee.id,
'date_start': date(2020, 1, 1)})
version.write({'contract_date_start': date(2020, 1, 1)})
if version_vals:
version.write(version_vals)
return employee
def _slip(self, employee, monat, jahr=2026, confirm=False,
struct=None):
erster = date(jahr, monat, 1)
naechster = (erster + timedelta(days=32)).replace(day=1)
slip = self.env['hr.payslip'].create({
'name': 'Test-SV %d/%d' % (monat, jahr),
'employee_id': employee.id,
'struct_id': (struct or self.structure).id,
'date_from': erster,
'date_to': naechster - timedelta(days=1),
})
slip.compute_sheet()
if confirm:
slip.action_payslip_done()
return slip
# ------------------------------------------------------------------
# DG-Beiträge (ÖGK „Normalbetriebe" 2026: DG 20,98 % / Wien 21,23)
# ------------------------------------------------------------------
def test_01_svdg_gesamt(self):
"""DG-Summe 20,98 % = KV 3,78 + PV 12,55 + AV 2,95 + UV 1,10 +
WF 0,50 + IESG 0,10 auf laufender, HBG-gecappter Basis."""
employee = self._employee()
self._regel('LFD', 2059.41)
slip = self._slip(employee, 1)
self.assertAlmostEqual(
slip._l10n_at_svdg('kv'), 2059.41 * 0.0378, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg('pv'), 2059.41 * 0.1255, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg('av'), 2059.41 * 0.0295, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg('uv'), 2059.41 * 0.011, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg('wf'), 2059.41 * 0.005, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg('iesg'), 2059.41 * 0.001, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg_gesamt(), 2059.41 * 0.2098, places=2)
def test_02_svdg_wien(self):
"""WF-Wien 0,75 % DG ab 1.1.2026 (Satzvektor); 2025 nur 0,5 %."""
employee = self._employee()
self._regel('LFD', 2059.41)
slip = self._slip(employee, 1)
slip.company_id.write({'l10n_at_wf_wien': True})
self.assertAlmostEqual(
slip._l10n_at_svdg('wf'), 2059.41 * 0.0075, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg_gesamt(), 2059.41 * 0.2123, places=2)
# 2025: Vektor-Zeile ohne 'wien'-Eintrag → Bundesstandard 0,5 %
slip_2025 = self._slip(employee, 3, jahr=2025)
self.assertAlmostEqual(
slip_2025._l10n_at_svdg('wf'), 2059.41 * 0.005, places=2)
# HBG 2025 = 30 × 215 € = 6.450 € (KB A8, VO-Reihe § 108 Abs 3)
self.assertAlmostEqual(
slip_2025._l10n_at_svdn_basis_laufen(), 2059.41, places=2)
# Bundesland-Schlüssel wirkt identisch zum Company-Flag
slip.company_id.write(
{'l10n_at_wf_wien': False, 'l10n_at_bundesland': 'wien'})
self.assertAlmostEqual(
slip._l10n_at_svdg('wf'), 2059.41 * 0.0075, places=2)
def test_03_svdg_sz(self):
"""DG auf sonstigen Bezügen: KV/PV/AV/UV/IESG = 20,48 %
(§ 54 ASVG; HBG monatlich + SZ-Jahreshöchstbetrag 13.860)."""
employee = self._employee()
self._regel('LFD', 2059.41)
slip_okt = self._slip(employee, 10, confirm=True)
self._regel('SZ', 2059.41, bemessung='sonstig')
slip_nov = self._slip(employee, 11)
for komp, satz in (('kv', 0.0378), ('pv', 0.1255),
('av', 0.0295), ('uv', 0.011),
('iesg', 0.001)):
self.assertAlmostEqual(
slip_nov._l10n_at_svdg_sz(komp), 2059.41 * satz, places=2)
self.assertAlmostEqual(
slip_nov._l10n_at_svdg_sz_gesamt(), 2059.41 * 0.2048, places=2)
# Dezember: Jahresrest 13.860 2.059,41 lässt die zweite SZ zu
slip_dez = self._slip(employee, 12)
self.assertAlmostEqual(
slip_dez._l10n_at_svdn_basis_sz(), 2059.41, places=2)
# Deckel: SZ 20.000 im Januar 2027 (Jahresrest voll) → HBG 6.930
self._regel('SZ2', 20000.0, bemessung='sonstig')
slip_2027 = self._slip(employee, 1, jahr=2027)
self.assertAlmostEqual(
slip_2027._l10n_at_svdn_basis_sz(),
min(20000.0 + 2059.41, 6930.0, 13860.0), places=2)
# ------------------------------------------------------------------
# Geringfügigkeit (§ 5 Abs 2 ASVG; Aufwertung 2026 ausgesetzt) + § 53a
# ------------------------------------------------------------------
def test_04_geringfuegig_uv(self):
"""Laufendes Entgelt ≤ GFG 551,10 €: keine SVDN/SVDG; stattdessen
§-53a-Abs-1-UV 6,50 €/Monat (1,1 % der allgemeinen BG)."""
employee = self._employee()
self._regel('LFD', 500.0)
slip = self._slip(employee, 1)
self.assertTrue(slip._l10n_at_geringfuegig())
self.assertAlmostEqual(slip._l10n_at_svdn_gesamt(), 0.0, places=2)
self.assertAlmostEqual(slip._l10n_at_svdg_gesamt(), 0.0, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg_uv_geringfuegig(), 6.50, places=2)
self.assertTrue(slip.l10n_at_geringfuegig) # stored (DAG-Suche)
# Über der Grenze: Vollversicherung, kein §-53a-UV
employee_b = self._employee()
struktur = self._struktur('GFG2')
self._regel('LFD', 600.0, struct=struktur)
slip_b = self._slip(employee_b, 1, struct=struktur)
self.assertFalse(slip_b._l10n_at_geringfuegig())
self.assertAlmostEqual(
slip_b._l10n_at_svdg_uv_geringfuegig(), 0.0, places=2)
self.assertAlmostEqual(
slip_b._l10n_at_svdg_gesamt(), 600.0 * 0.2098, places=2)
def test_05_geringfuegig_hochrechnung(self):
"""Untermonatiger Beginn: Hochrechnung auf den Monat (lb-bes-06);
Verhältnis < 1 Naturalmonat: Gesamtentgelt direkt gegen die GFG."""
employee = self._employee(
{'contract_date_start': date(2026, 1, 16)})
self._regel('LFD', 400.0)
slip = self._slip(employee, 1)
# 400 × 30/16 = 750 > 551,10 → voll versichert; DN-AV 0 (§ 2a:
# 400 ≤ 2.225) → DN-Gesamt 15,12 %
self.assertFalse(slip._l10n_at_geringfuegig())
self.assertAlmostEqual(
slip._l10n_at_svdn_gesamt(), 400.0 * 0.1512, places=2)
# 250 × 30/16 = 468,75 ≤ 551,10 → geringfügig
struktur = self._struktur('HGR')
employee_b = self._employee(
{'contract_date_start': date(2026, 1, 16)})
self._regel('LFD', 250.0, struct=struktur)
slip_b = self._slip(employee_b, 1, struct=struktur)
self.assertTrue(slip_b._l10n_at_geringfuegig())
# auf unter einen Naturalmonat befristet: direkt gegen die GFG
employee_c = self._employee({
'contract_date_start': date(2026, 1, 16),
'contract_date_end': date(2026, 1, 25)})
struktur_c = self._struktur('KURZ')
self._regel('LFD', 500.0, struct=struktur_c)
slip_c = self._slip(employee_c, 1, struct=struktur_c)
self.assertTrue(slip_c._l10n_at_geringfuegig())
def test_06_lehrling(self):
"""Lehrling: keine AK-Umlage (§ 61 AKG), kein UV (§ 51 Abs 6
ASVG); nie geringfügig (§ 5 Abs 3 ASVG)."""
employee = self._employee({'l10n_at_lehrling': True})
self._regel('LFD', 300.0)
slip = self._slip(employee, 1)
self.assertFalse(slip._l10n_at_geringfuegig())
self.assertAlmostEqual(slip._l10n_at_svdn('ak'), 0.0, places=2)
self.assertAlmostEqual(slip._l10n_at_svdg('uv'), 0.0, places=2)
self.assertAlmostEqual(slip._l10n_at_svdg_uv_geringfuegig(), 0.0)
# KV/PV/WF regulär; AV 0 (§ 2a), AK 0, IESG 0 (§ 12 Abs 2 IESG):
# DN 14,62 % / DG 19,78 %
self.assertAlmostEqual(
slip._l10n_at_svdn_gesamt(), 300.0 * 0.1462, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg_gesamt(), 300.0 * 0.1978, places=2)
# ------------------------------------------------------------------
# § 49 Abs 3 ASVG — beitragsfreie Bezugsbestandteile (Kumulative)
# ------------------------------------------------------------------
def test_07_sv49_mahlzeit(self):
"""Mahlzeiten-Gutscheine 8 €/Arbeitstag (Z 12): 110 € auf
10 Arbeitstage → 80 € beitragsfrei, 30 € Umwidmung."""
employee = self._employee()
self._regel('LFD', 2059.41)
self._regel('MAH', 11.0, sv49='mahlzeit', quantity='10.0')
slip = self._slip(employee, 1)
self.assertAlmostEqual(
slip._l10n_at_sv49_freie_laufen(), 80.0, places=2)
basis = slip._l10n_at_sv_basis_roh()
self.assertAlmostEqual(basis, 2059.41 + 110.0 - 80.0, places=2)
# DN-AV 0 (§ 2a: Basis 2.089,41 ≤ 2.225) → DN-Gesamt 15,12 %
self.assertAlmostEqual(
slip._l10n_at_svdn_gesamt(), basis * 0.1512, places=2)
def test_08_sv49_jahrespools(self):
"""Jahres-Kumulative: Betriebsveranstaltung 365 €/Jahr und
Homeoffice-Pauschale 3 €/Tag max 100 Tage (YTD-Verbrauch)."""
employee = self._employee()
self._regel('LFD', 2059.41)
self._regel('BVER', 300.0, sv49='betriebsveranstaltung')
slip_a = self._slip(employee, 3, confirm=True)
self.assertAlmostEqual(
slip_a._l10n_at_sv49_freie_laufen(), 300.0, places=2)
# April: BVER-Rest 65 €; Homeoffice 70 Tage frei (3 × 70 = 210)
self._regel('HO', 3.0, sv49='homeoffice', quantity='70.0')
slip_b = self._slip(employee, 4, confirm=True)
self.assertAlmostEqual(
slip_b._l10n_at_sv49_freie_laufen(), 65.0 + 210.0, places=2)
# Mai: BVER-Pool verbraucht; Homeoffice-Rest 30 Tage → 90 €
slip_c = self._slip(employee, 5)
self.assertAlmostEqual(
slip_c._l10n_at_sv49_freie_laufen(), 90.0, places=2)
# ------------------------------------------------------------------
# Altersabhängige Satzausschaltungen (Stichtags-Regeln am Vertrag)
# ------------------------------------------------------------------
def test_09_alv_entfall(self):
"""§ 1 Abs 2 lit e AlVG: AV DN+DG und IESG entfallen ab
Stichtag (§ 12 Abs 1 Z 4 iVm Abs 2 IESG); Nachzahlungslinien mit
früherem Beitragsmonat zahlen weiter AV (Anspruchsprinzip)."""
employee = self._employee(
{'l10n_at_alv_entfall_ab': date(2026, 1, 1)})
self._regel('LFD', 2059.41)
slip = self._slip(employee, 1)
self.assertAlmostEqual(slip._l10n_at_svdn('av'), 0.0, places=2)
self.assertAlmostEqual(slip._l10n_at_svdg('av'), 0.0, places=2)
self.assertAlmostEqual(slip._l10n_at_svdg('iesg'), 0.0, places=2)
# DG ohne AV+IESG: 20,98 2,95 0,10 = 17,93 %
self.assertAlmostEqual(
slip._l10n_at_svdg_gesamt(), 2059.41 * 0.1793, places=2)
# DN ohne AV: 18,07 2,95 = 15,12 %
self.assertAlmostEqual(
slip._l10n_at_svdn_gesamt(), 2059.41 * 0.1512, places=2)
# Nachzahlungslinie Beitragsmonat 6/2025: AV greift weiter
self._regel('NACH', 1000.0, beitragsmonat=date(2025, 6, 1))
slip2 = self._slip(employee, 2)
self.assertAlmostEqual(
slip2._l10n_at_svdg('av'), 1000.0 * 0.0295, places=2)
def test_10_uv_entfall(self):
"""§ 51 Abs 6 ASVG: UV entfällt ab 60. LJ — laufend und SZ."""
employee = self._employee(
{'l10n_at_uv_entfall_ab': date(2026, 1, 1)})
self._regel('LFD', 2059.41)
self._regel('SZ', 2059.41, bemessung='sonstig')
slip = self._slip(employee, 1)
self.assertAlmostEqual(slip._l10n_at_svdg('uv'), 0.0, places=2)
self.assertAlmostEqual(slip._l10n_at_svdg_sz('uv'), 0.0, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg_gesamt(), 2059.41 * 0.1988, places=2)
def test_11_pv_bonusphase(self):
"""§ 51 Abs 7 ASVG: PV je zur Hälfte reduziert (DG und DN)."""
employee = self._employee(
{'l10n_at_pv_bonusphase_ab': date(2026, 1, 1)})
self._regel('LFD', 2059.41)
slip = self._slip(employee, 1)
self.assertAlmostEqual(
slip._l10n_at_svdn('pv'), 2059.41 * 0.05125, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg('pv'), 2059.41 * 0.06275, places=2)
# ------------------------------------------------------------------
# ALV-DN-Staffel (§ 2a AMPFG — reduziert nur den DN-Anteil)
# ------------------------------------------------------------------
def test_12_av_staffel(self):
"""Bis 2.225 €: DN-AV 0 %; bis 2.427: 1 %; bis 2.630: 2 %
DG-AV bleibt stets 2,95 % (ÖGK „Mind. AV auf 0/1/2 %")."""
employee_a = self._employee()
struktur_a = self._struktur('ST1')
self._regel('LFD', 2000.0, struct=struktur_a)
slip_a = self._slip(employee_a, 1, struct=struktur_a)
self.assertAlmostEqual(slip_a._l10n_at_svdn('av'), 0.0, places=2)
self.assertAlmostEqual(
slip_a._l10n_at_svdg('av'), 2000.0 * 0.0295, places=2)
employee_b = self._employee()
struktur_b = self._struktur('ST2')
self._regel('LFD', 2500.0, struct=struktur_b)
slip_b = self._slip(employee_b, 1, struct=struktur_b)
self.assertAlmostEqual(
slip_b._l10n_at_svdn('av'), 2500.0 * 0.02, places=2)
self.assertAlmostEqual(
slip_b._l10n_at_svdg('av'), 2500.0 * 0.0295, places=2)
employee_c = self._employee()
struktur_c = self._struktur('ST3')
self._regel('LFD', 3000.0, struct=struktur_c)
slip_c = self._slip(employee_c, 1, struct=struktur_c)
self.assertAlmostEqual(
slip_c._l10n_at_svdn('av'), 3000.0 * 0.0295, places=2)
self.assertAlmostEqual(
slip_c._l10n_at_svdg('av'), 3000.0 * 0.0295, places=2)
# ------------------------------------------------------------------
# Beitragsmonats-Allokation (Anspruchsprinzip)
# ------------------------------------------------------------------
def test_13_beitragsmonat_hbg(self):
"""Nachzahlungslinie mit Beitragsmonat 2025: HBG historisch
versioniert (2025: 6.450 € statt 6.930 €), je Gruppe gecapped."""
employee = self._employee()
self._regel('LFD', 7000.0)
self._regel('NACH', 7000.0, beitragsmonat=date(2025, 6, 1))
slip = self._slip(employee, 1)
monate = dict(slip._l10n_at_sv_basis_laufen_monate())
self.assertAlmostEqual(
monate[date(2026, 1, 1)], 6930.0, places=2)
self.assertAlmostEqual(
monate[date(2025, 6, 1)], 6450.0, places=2)
self.assertAlmostEqual(
slip._l10n_at_svdg('kv'),
(6930.0 + 6450.0) * 0.0378, places=2)
# ------------------------------------------------------------------
# Dienstgeberabgabe geringfügig Beschäftigter (§ 1 DAG)
# ------------------------------------------------------------------
def test_14_dag(self):
"""DAG 19,4 %: Lohnsumme (BG ohne SZ) aller Geringfügigen >
826,65 € (= 1,5 × GFG 551,10, TASY MINGRDAGP1) und ≥ 2 Personen."""
employee_a = self._employee()
struktur_a = self._struktur('DAGA')
self._regel('LFD', 500.0, struct=struktur_a)
self._slip(employee_a, 1, confirm=True, struct=struktur_a)
employee_b = self._employee()
struktur_b = self._struktur('DAGB')
self._regel('LFD', 550.0, struct=struktur_b)
self._slip(employee_b, 1, confirm=True, struct=struktur_b)
company = self.env.company
dag = company._l10n_at_dag(date(2026, 1, 1))
self.assertAlmostEqual(dag['schwelle'], 826.65, places=2)
self.assertEqual(dag['anzahl'], 2)
self.assertAlmostEqual(dag['lohnsumme'], 1050.0, places=2)
self.assertAlmostEqual(dag['abgabe'], 1050.0 * 0.194, places=2)
# Zwei Geringfügige unter der Schwelle: keine DAG
employee_c = self._employee()
struktur_c = self._struktur('DAGC')
self._regel('LFD', 400.0, struct=struktur_c)
self._slip(employee_c, 2, confirm=True, struct=struktur_c)
employee_d = self._employee()
struktur_d = self._struktur('DAGD')
self._regel('LFD', 400.0, struct=struktur_d)
self._slip(employee_d, 2, confirm=True, struct=struktur_d)
dag_tief = company._l10n_at_dag(date(2026, 2, 1))
self.assertEqual(dag_tief['anzahl'], 2)
self.assertAlmostEqual(dag_tief['lohnsumme'], 800.0, places=2)
self.assertAlmostEqual(dag_tief['abgabe'], 0.0, places=2)
# Nur ein Geringfügiger: keine DAG
dag_einzel = company._l10n_at_dag(date(2026, 3, 1))
self.assertAlmostEqual(dag_einzel['abgabe'], 0.0, places=2)