[IMP] l10n_at_hr_payroll_private: GP4 SV/DB-Anbindung (SVDN_SZ-Nachtrag, DG-Regelblock, FLAF/KommSt/DZ)

Anbindung der privatwirtschaftlichen Structure an den GP4-Kern nach
dem bewährten GP3-Muster (dünne 1-Zeilen-Regeln; Logik und Werte
verbleiben im Kern — hr.salary.rule.struct_id ist required, geteilte
Kern-Regeln sind mechanisch unmöglich).

SVDN_SZ-Nachtrag (§ 67 Abs 12): Die SV-DN auf sonstigen Bezügen war in
GP3 nur als Bemessungsbestandteil der §-67-Lohnsteuer wirksam, fehlte
aber als eigene Abzugszeile — das Netto in §-67-Monaten war um den
SV-DN(SZ) zu hoch (RF-L1: 290,79 € nach §-2a-Korrektur). Die Erwartungen
in test_01/test_20 wurden entsprechend korrigiert.

DG-Block (Kategorie ATP_DG, ohne Nettoeffekt): SVDG_KV/PV/AV/UV/WF/IESG
laufend, SVDG_SZ_* auf Sonderzahlungen, SVDG_UV_GFG (§-53a-Pauschale
geringfügig Beschäftigter) sowie die Lohnnebenkosten FLAFDB (§ 41
FLAG), KOMMST (§ 9 KommStG) und DZ (§§ 122/126 WKG, nur bei Company-
Flag l10n_at_wk_mitglied; Satz je Betriebsstätten-Bundesland).

Gemeinsame LNK-Basis in payslip_private.py (_at_lnk_basis): monatlich
gezahlte Arbeitslöhne nach Zufluss, ohne §-67-Abs-3/6-Bezüge (Kern-Flag
l10n_at_s67_abs), lit-f-Befreiung nur für FLAF und DZ (KommSt ohne),
Freibetragsstaffel 1.095/1.460 €.

Rechenfälle docs/rechenfaelle/sozialversicherung.md (RF-SV-1 bis -7)
und §-2a-Korrekturvermerk in lohnsteuer.md. Tests: test_sv_private
(8 Fälle); gesamt 74/74 grün auf odoo_dev.
This commit is contained in:
2026-09-11 23:22:13 +02:00
parent a2a823ad35
commit 04099fef39
10 changed files with 833 additions and 44 deletions
@@ -0,0 +1,253 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- GP4: Dünne SV-/LNK-Regeln für die privatwirtschaftliche -->
<!-- Structure. Logik/Werte vollständig im Kern (models/ -->
<!-- sozialversicherung.py + rule_parameters_sv_2026.xml); hier nur -->
<!-- 1-Zeilen-Bindungen (kein Wertefork, keine Logikfork). -->
<!-- DG-Beiträge und Lohnnebenkosten: Kategorie ATP_DG — reine -->
<!-- Dienstgeberkosten ohne Nettoeffekt. -->
<!-- ============================================================ -->
<!-- GP3-Nachtrag: SV-DN auf sonstigen Bezügen (§ 67 Abs 12 — -->
<!-- KV/PV/AV 17,07 %) als eigene Abzugszeile. Fehlte in GP3; -->
<!-- ohne sie wäre das Netto in §-67-Monaten um den SV-DN(SZ) -->
<!-- zu hoch (RF-L1: 351,54 €). -->
<record id="rule_svdn_sz" model="hr.salary.rule">
<field name="name">SV-DN auf sonstigen Bezügen (§ 67 Abs 12; KV/PV/AV)</field>
<field name="code">SVDN_SZ</field>
<field name="sequence" eval="65"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_abzug"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdn_sz(result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdn_sz(result_rules)
]]></field>
</record>
<!-- DG-SV laufend (ÖGK Normalbetriebe 2026: 20,38 % + WF 0,5 + -->
<!-- IESG 0,1 = 20,98 % gesamt; Wien 21,23 %). -->
<record id="rule_svdg_kv" model="hr.salary.rule">
<field name="name">SV-DG Krankenversicherung (§ 51 Abs 1 Z 1 ASVG)</field>
<field name="code">SVDG_KV</field>
<field name="sequence" eval="80"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg('kv', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg('kv', result_rules)
]]></field>
</record>
<record id="rule_svdg_pv" model="hr.salary.rule">
<field name="name">SV-DG Pensionsversicherung (§ 51 Abs 1 Z 3 ASVG)</field>
<field name="code">SVDG_PV</field>
<field name="sequence" eval="81"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg('pv', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg('pv', result_rules)
]]></field>
</record>
<record id="rule_svdg_av" model="hr.salary.rule">
<field name="name">SV-DG Arbeitslosenversicherung (§ 2 AMPFG; entfällt § 1 Abs 2 lit e AlVG)</field>
<field name="code">SVDG_AV</field>
<field name="sequence" eval="82"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg('av', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg('av', result_rules)
]]></field>
</record>
<record id="rule_svdg_uv" model="hr.salary.rule">
<field name="name">SV-DG Unfallversicherung (§ 51 Abs 1 Z 2 ASVG; entfällt ab 60)</field>
<field name="code">SVDG_UV</field>
<field name="sequence" eval="83"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg('uv', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg('uv', result_rules)
]]></field>
</record>
<record id="rule_svdg_wf" model="hr.salary.rule">
<field name="name">WF-Beitrag DG (Wohnbauförderung; Wien 0,75 % ab 1.1.2026)</field>
<field name="code">SVDG_WF</field>
<field name="sequence" eval="84"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg('wf', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg('wf', result_rules)
]]></field>
</record>
<record id="rule_svdg_iesg" model="hr.salary.rule">
<field name="name">IESG-Zuschlag DG (§ 12 Abs 1 Z 4 IESG; entfällt ab 63)</field>
<field name="code">SVDG_IESG</field>
<field name="sequence" eval="85"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg('iesg', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg('iesg', result_rules)
]]></field>
</record>
<!-- DG-SV auf sonstigen Bezügen (§ 54 ASVG: KV/PV/AV/UV + IESG; -->
<!-- SZ-Jahreshöchstbetrag 13.860 €, 60faches HBG je Jahr). -->
<record id="rule_svdg_sz_kv" model="hr.salary.rule">
<field name="name">SV-DG KV auf sonstigen Bezügen (§ 54 ASVG)</field>
<field name="code">SVDG_SZ_KV</field>
<field name="sequence" eval="86"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg_sz('kv', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg_sz('kv', result_rules)
]]></field>
</record>
<record id="rule_svdg_sz_pv" model="hr.salary.rule">
<field name="name">SV-DG PV auf sonstigen Bezügen (§ 54 ASVG)</field>
<field name="code">SVDG_SZ_PV</field>
<field name="sequence" eval="87"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg_sz('pv', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg_sz('pv', result_rules)
]]></field>
</record>
<record id="rule_svdg_sz_av" model="hr.salary.rule">
<field name="name">SV-DG AV auf sonstigen Bezügen (§ 3 AMPFG)</field>
<field name="code">SVDG_SZ_AV</field>
<field name="sequence" eval="88"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg_sz('av', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg_sz('av', result_rules)
]]></field>
</record>
<record id="rule_svdg_sz_uv" model="hr.salary.rule">
<field name="name">SV-DG UV auf sonstigen Bezügen (§ 51 iVm § 54 ASVG)</field>
<field name="code">SVDG_SZ_UV</field>
<field name="sequence" eval="89"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg_sz('uv', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg_sz('uv', result_rules)
]]></field>
</record>
<record id="rule_svdg_sz_iesg" model="hr.salary.rule">
<field name="name">IESG-Zuschlag DG auf sonstigen Bezügen (folgt dem AV-Beitrag)</field>
<field name="code">SVDG_SZ_IESG</field>
<field name="sequence" eval="90"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg_sz('iesg', result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg_sz('iesg', result_rules)
]]></field>
</record>
<!-- § 53a Abs 1 ASVG: DG-UV geringfügig Beschäftigter — -->
<!-- Monatspauschale 1,1 % der allgemeinen Beitragsgrundlage -->
<!-- (2026: 6,50 €; nur UV-Pflicht, lb-bes-06/ÖGK-Tarifsystem). -->
<record id="rule_svdg_uv_gfg" model="hr.salary.rule">
<field name="name">UV-Beitrag geringfügig Beschäftigter (§ 53a Abs 1 ASVG)</field>
<field name="code">SVDG_UV_GFG</field>
<field name="sequence" eval="91"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._l10n_at_svdg_uv_geringfuegig(result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._l10n_at_svdg_uv_geringfuegig(result_rules)
]]></field>
</record>
<!-- Lohnnebenkosten FLAF/KommSt/DZ (BG § 41 Abs 3 FLAG, § 5 -->
<!-- KommStG, §§ 122/126 WKG; Freibetragsstaffel 1.095/1.460 €). -->
<record id="rule_flafdb" model="hr.salary.rule">
<field name="name">FLAF-Dienstgeberbeitrag (§ 41 FLAG)</field>
<field name="code">FLAFDB</field>
<field name="sequence" eval="92"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._at_flaf_db(result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._at_flaf_db(result_rules)
]]></field>
</record>
<record id="rule_kommst" model="hr.salary.rule">
<field name="name">Kommunalsteuer (§ 9 KommStG 1993)</field>
<field name="code">KOMMST</field>
<field name="sequence" eval="93"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._at_kommst(result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._at_kommst(result_rules)
]]></field>
</record>
<record id="rule_dz" model="hr.salary.rule">
<field name="name">Zuschlag zum Dienstgeberbeitrag (§§ 122/126 WKG; WKO-Mitglieder)</field>
<field name="code">DZ</field>
<field name="sequence" eval="94"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_dg"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
<field name="condition_select">python</field>
<field name="condition_python">result = payslip._at_dz(result_rules) > 0</field>
<field name="amount_select">code</field>
<field name="l10n_at_bemessung">neutral</field>
<field name="amount_python_compute"><![CDATA[
result = payslip._at_dz(result_rules)
]]></field>
</record>
</odoo>