[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:
@@ -47,12 +47,33 @@ Privatwirtschaft (KV)", AZG-Fenster-WETs, Regelinventar
|
||||
KVGEO/NACHT_SV/UE_*/MEHR_*/URL_UE/B13/B14/B14_RUECK/NETTO —
|
||||
vollständig `kv.wert`-getrieben (Rechenfälle `docs/rechenfaelle/`).
|
||||
|
||||
**Offen (GP3+):** Lohnsteuer/SV im Bundes-Kern (D3-Vorfinanzierung),
|
||||
Abfertigung Neu, Meldewesen/Belege, FI-Buchung UGB; All-in-UI-Bericht
|
||||
(GP8); B14 längster-Urlaubs-Teil-Verfeinerung.
|
||||
**GP3 Lohnsteuer (umgesetzt 2026-09-11):** dünne Regeln
|
||||
SVDN_KV/PV/AV/AK/WF + LST_LFD/LST_SZ auf dem AP3-Kern (§ 66
|
||||
kumulativ mit Rollung, § 67 Sechstel/Fixsätze mit Günstig-
|
||||
Aufrollung, § 68-Steuerfreiheiten; Rechenfälle `docs/rechenfaelle/
|
||||
lohnsteuer.md`).
|
||||
|
||||
Tests: `test_kv_katalog` + `test_entgelt_private` (GP2-Rechenfälle) —
|
||||
**GP4 SV/DB (umgesetzt 2026-09-11):** SVDN_SZ-Nachtrag (§ 67 Abs 12 —
|
||||
Netto-Korrektur in §-67-Monaten), DG-Block SVDG_KV/PV/AV/UV/WF/IESG +
|
||||
SVDG_SZ_* + §-53a-UV Geringfügiger (Kategorie ATP_DG, ohne
|
||||
Nettoeffekt; ÖGK 2026: DG 20,98 % / Wien 21,23 %), Lohnnebenkosten
|
||||
FLAFDB (§ 41 FLAG), KOMMST (§ 9 KommStG) und DZ (§§ 122/126 WKG,
|
||||
company-flag-gated) mit Freibetragsstaffel 1.095/1.460 € — Logik/Werte
|
||||
im Bundes-Kern (`models/sozialversicherung.py`, D3-Vorfinanzierung):
|
||||
§-2a-ALV-DN-Staffel, Geringfügigkeit (§ 5 Abs 2 iVm § 810 Abs 3 ASVG),
|
||||
beitragsfreie Bezüge § 49 Abs 3 mit Jahres-Kumulativen,
|
||||
altersabhängige Satzausschaltungen (§ 1 Abs 2 lit e AlVG, § 51
|
||||
Abs 6/7 ASVG, § 12 IESG), WF-Satzvektor Wien, Beitragsmonats-
|
||||
Allokation (Anspruchsprinzip) und DAG-Bewertung (§ 1 DAG).
|
||||
Rechenfälle `docs/rechenfaelle/sozialversicherung.md`.
|
||||
|
||||
**Offen (GP5+):** Abfertigung Neu (BMSVG), Meldewesen/Belege,
|
||||
FI-Buchung UGB; All-in-UI-Bericht (GP8); B14 längster-Urlaubs-Teil-
|
||||
Verfeinerung; DZ-WKO-Verifikation (8.11) vor Wien-Mandanten.
|
||||
|
||||
Tests: `test_kv_katalog` + `test_entgelt_private` (GP2) +
|
||||
`test_lst_private` (GP3) + `test_sv_private` (GP4) —
|
||||
`.venv/bin/python -m odoo -d <testdb> -u l10n_at_hr_payroll,l10n_at_hr_payroll_private
|
||||
--test-tags /l10n_at_hr_payroll_private --test-enable --stop-after-init
|
||||
--test-tags /l10n_at_hr_payroll,/l10n_at_hr_payroll_private --test-enable --stop-after-init
|
||||
--addons-path=odoo_19.0+e.20260910/odoo-19.0+e.20260910/odoo/addons,addons`
|
||||
(Lokal grün am 2026-09-11: 29/29 Tests.)
|
||||
(Lokal grün am 2026-09-11: **74/74 Tests**.)
|
||||
@@ -1,7 +1,7 @@
|
||||
# Part of the odoo-at-payroll project. License: LGPL-3.
|
||||
{
|
||||
'name': 'Österreich - Privatwirtschaft Personalverrechnung (General-AT)',
|
||||
'version': '19.0.3.0.0',
|
||||
'version': '19.0.4.0.0',
|
||||
'author': 'ixsol / gem360',
|
||||
'website': 'https://gem360.at',
|
||||
'category': 'Human Resources/Payroll',
|
||||
@@ -31,12 +31,21 @@ Grundlagen: ``personalverrechnung/IMPLEMENTIERUNGSPLAN-Privat.md`` und
|
||||
(Vorlauf 2026-09-11 verifiziert; Rechenfälle unter ``docs/rechenfaelle/``).
|
||||
All-in-Vertragsmodell (§ 2g AVRAG): Pauschale/Grundlohn-Ausweis am
|
||||
Vertrag + Deckungsrechnung.
|
||||
- **GP3 Lohnsteuer (umgesetzt):** dünne Regeln SVDN_KV/PV/AV/AK/WF +
|
||||
LST_LFD/LST_SZ auf dem AP3-Kern (§ 66 kumulativ, § 67 Sechstel/
|
||||
Fixsätze, § 68-Steuerfreiheiten).
|
||||
- **GP4 SV/DB (dieser Stand):** SVDN_SZ-Nachtrag (§ 67 Abs 12 — Netto-
|
||||
Korrektur in §-67-Monaten), DG-Block SVDG_KV/PV/AV/UV/WF/IESG +
|
||||
SVDG_SZ_* + §-53a-UV Geringfügiger (ATP_DG, ohne Nettoeffekt;
|
||||
ÖGK 2026: DG 20,98 % / Wien 21,23 %), Lohnnebenkosten FLAFDB
|
||||
(§ 41 FLAG), KOMMST (§ 9 KommStG) und DZ (§§ 122/126 WKG,
|
||||
company-flag-gated) mit Freibetragsstaffel 1.095/1.460 € —
|
||||
Logik/Werte im Bundes-Kern (D3-Vorfinanzierung).
|
||||
- **Seed D2 (Referenz-KVs R1):** SI-2203 „Handwerk und Gewerbe" +
|
||||
SI-2748 „Metallgewerbe" (Gehaltstabellen ab 1. 1. 2026, kuratiert aus
|
||||
den KV-Library-Volltexten).
|
||||
- **Folgen (GP2+):** Entgelt-Engine (KVGEO, AZG-Zuschläge, 13./14.
|
||||
Bezüge), Lohnsteuer/SV im Bundes-Kern (D3-Vorfinanzierung),
|
||||
Abfertigung Neu, Meldewesen/Belege, FI-Buchung UGB.
|
||||
- **Folgen (GP5+):** Abfertigung Neu (BMSVG), Meldewesen/Belege,
|
||||
FI-Buchung UGB, Jahreswechsel.
|
||||
|
||||
Kein VRV-Bezug (Gemeinde-Schiene bleibt ``l10n_at_gemeinde_payroll`` +
|
||||
gem360-Brücke).
|
||||
@@ -53,6 +62,7 @@ gem360-Brücke).
|
||||
'data/input_types_private.xml',
|
||||
'data/salary_rules_private.xml',
|
||||
'data/salary_rules_lst_private.xml',
|
||||
'data/salary_rules_sv_private.xml',
|
||||
'views/kv_views.xml',
|
||||
],
|
||||
'countries': ['at'],
|
||||
|
||||
@@ -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>
|
||||
@@ -1,4 +1,4 @@
|
||||
# Rechenfälle Lohnsteuer (GP3) — Kern + privatwirtschaftliche Structure
|
||||
## Rechenfälle Lohnsteuer (GP3) — Kern + privatwirtschaftliche Structure
|
||||
|
||||
**Quellen (✅ P0-GP3 2026-09-11):** EStG-Volltext RIS-Fassung
|
||||
10. 09. 2026 (lokal `.firecrawl/ris/`); RECHTSQUELLEN-Privat
|
||||
@@ -6,6 +6,13 @@ Abschnitt 5 (§-Anker je Wert). Kern: `l10n_at_hr_payroll`
|
||||
(`models/lohnsteuer.py`, `data/rule_parameters_lst_2026.xml`);
|
||||
privat: dünne Regeln `SVDN_*`/`LST_LFD`/`LST_SZ`.
|
||||
|
||||
> **GP4-Korrektur (2026-09-11):** Die ALV-DN-Staffel § 2a AMPFG
|
||||
> (bis 2.225 € BG: 0 %) ist ab GP4 in der SV-Basis wirksam — für die
|
||||
> RF-Bezüge 2.059,41/2.199,15 € entfällt der DN-AV auf laufenden
|
||||
> Bezügen und SZ (14,12 % statt 17,07 %); DN-Gesamt 15,12 statt
|
||||
> 18,07 %. Die GP3-Beispielwerte sind unten entsprechend korrigiert;
|
||||
> Details `sozialversicherung.md` RF-SV-1.
|
||||
|
||||
## Systematik (user-Entscheidungen 2026-09-11)
|
||||
|
||||
- **Lohnsteuertage:** 30 je vollem Monat; Teilmonat = Kalendertage
|
||||
@@ -23,41 +30,44 @@ privat: dünne Regeln `SVDN_*`/`LST_LFD`/`LST_SZ`.
|
||||
|
||||
## RF-L1: Vollmonat November mit B13 (VG II Stufe 1)
|
||||
|
||||
- KVGEO 2.059,41 €; SVDN = 18,07 % × 2.059,41 = **372,91 €**
|
||||
(KV 79,70 · PV 211,08 · ALV 60,75 · AK 10,30 · WF 10,30).
|
||||
- Bemessung laufend = 2.059,41 − 372,91 = **1.686,50 €**;
|
||||
JBG = 1.686,50 × 12 − 192 = 20.046,06 → Tarif 20 % × 6.507,06 =
|
||||
1.301,41 − 496 = 805,41 ÷ 12 → **LST_LFD 67,12 €**.
|
||||
- B13: SV-SZ = 2.059,41 × 17,07 % = **351,54 €**; Bemessung
|
||||
1.707,87; Sechstel = 2.059,41 × 60/30 = 4.118,82 > 2.615 ✓
|
||||
pauschal → LST_SZ = (1.707,87 − 620) × 6 % = **65,27 €**.
|
||||
- KVGEO 2.059,41 €; SVDN = 15,12 % × 2.059,41 = **311,38 €**
|
||||
(KV 79,70 · PV 211,08 · ALV 0 (§ 2a: 2.059,41 ≤ 2.225) · AK 10,30 ·
|
||||
WF 10,30).
|
||||
- Bemessung laufend = 2.059,41 − 311,38 = **1.748,03 €**;
|
||||
JBG = 1.748,03 × 12 − 192 = 20.784,36 → Tarif 20 % × 7.245,36 =
|
||||
1.450,87 − 496 = 954,87 ÷ 12 → **LST_LFD 79,57 €**.
|
||||
- B13: SV-SZ = 2.059,41 × 14,12 % = **290,79 €**; Bemessung
|
||||
1.768,62; Sechstel = 2.059,41 × 60/30 = 4.118,82 > 2.615 ✓
|
||||
pauschal → LST_SZ = (1.768,62 − 620) × 6 % = **68,92 €**.
|
||||
|
||||
## RF-L2: Kumulative Rollung (Zuflussprinzip)
|
||||
|
||||
- Januar LST_LFD 67,12; Februar: JBG unverändert → Soll kumuliert
|
||||
134,24 − bereits 67,12 = **67,12** — Korrekturen Vormonat
|
||||
- Januar LST_LFD 79,57; Februar: JBG unverändert → Soll kumuliert
|
||||
159,14 − bereits 79,57 = **79,57** — Korrekturen Vormonat
|
||||
(Nachzahlung, Gehaltsänderung) rollen automatisch in den
|
||||
Folgelauf (§ 66 kumulativ = Rollungsprinzip § 77 Abs 3).
|
||||
|
||||
## RF-L3: Günstig-Aufrollung bei zweiter SZ
|
||||
|
||||
- Okt (nur laufend), Nov B13 (LST_SZ 65,27 bezahlt), Dez B14
|
||||
- Okt (nur laufend), Nov B13 (LST_SZ 68,92 bezahlt), Dez B14
|
||||
(Dezember-Fallback ohne Urlaub): Jahres-SZ-Bemessung
|
||||
2 × 1.707,87 = 3.415,74 ≤ Sechstel 4.118,82 → Soll-Jahr
|
||||
(3.415,74 − 620) × 6 % = 167,74 − 65,27 = **LST_SZ(Dez) 102,47 €**
|
||||
2 × 1.768,62 = 3.537,24 ≤ Sechstel 4.118,82 → Soll-Jahr
|
||||
(3.537,24 − 620) × 6 % = 175,03 − 68,92 = **LST_SZ(Dez) 106,11 €**
|
||||
(Neuberechnung bei jeder SZ-Zahlung, lb-son-04).
|
||||
|
||||
## RF-L4: Sechstel-Freigrenze (2.615 €) — SZ tarifisch
|
||||
|
||||
- Laufend 500 €/Monat: Sechstel = 500 × 60/30 = 1.000 ≤ 2.615 →
|
||||
B14 läuft tarifisch über LST_LFD (LST_SZ = 0).
|
||||
- Laufend 500 €/Monat (GP4: geringfügig → keine SV-Beiträge):
|
||||
Sechstel = 500 × 60/30 = 1.000 ≤ 2.615 → B14 läuft tarifisch
|
||||
über LST_LFD (LST_SZ = 0) — Mechanik-Demonstration der
|
||||
Freigrenze (geringfügige B14-Fälle in der Praxis unüblich).
|
||||
|
||||
## RF-L5: Sechstel-Überschuss (§ 67 Abs 10)
|
||||
|
||||
- Laufend 2.000 €/Monat (Sechstel 4.000), SZ 6.000 €:
|
||||
SV-SZ = 6.000 × 17,07 % = 1.024,20 → Bemessung 4.975,80;
|
||||
- Laufend 2.000 €/Monat (§ 2a: ALV-DN 0), Sechstel 4.000, SZ
|
||||
6.000 €: SV-SZ = 6.000 × 14,12 % = 847,20 → Bemessung 5.152,80;
|
||||
4.000 im Sechstel → Fixsteuer (4.000 − 620) × 6 % = **202,80 €**;
|
||||
Überschuss 975,80 läuft dem laufenden Arbeitslohn des
|
||||
Überschuss 1.152,80 läuft dem laufenden Arbeitslohn des
|
||||
Auszahlungsmonats zu (LSt-lfd-Kette).
|
||||
|
||||
## RF-L6: § 68-Freibeträge (Buckets über Regel-Flags)
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
# Rechenfälle Sozialversicherung/Dienstgeberabgaben (GP4) — Kern + privatwirtschaftliche Structure
|
||||
|
||||
**Quellen (✅ verifiziert 2026-09-11):** ÖGK-Beitragstarifsystem
|
||||
„Normalbetriebe Allgemeiner Teil", gültig ab 01.07.2026
|
||||
(`.additional_docs/oegk/`); TASY-LSWH-Export 2026-03-24
|
||||
(`personalverrechnung/quellen/`); „Beitragsrechtliche Werte 2026"
|
||||
(sozialversicherung.at, `.firecrawl/ris/sv-at/`); RIS-Normtexte
|
||||
ASVG §§ 5/45/49/51/53a/54/810, AKG § 61, AlVG § 1 Abs 2 lit e,
|
||||
AMPFG § 2a, IESG § 12, FLAG § 41, KommStG §§ 5/9, WKG §§ 122/126,
|
||||
DAG § 1; Layer-2-Belege lb-sva-03/04/06/12, lb-son-03, lb-lnk-01/02/
|
||||
06/07, lb-bes-06 (Stand 2026-07/08). Kern:
|
||||
`l10n_at_hr_payroll` (`models/sozialversicherung.py`,
|
||||
`rule_parameters_sv_2026.xml`); privat: dünne Regeln `SVDG_*`/
|
||||
`SVDN_SZ`/`FLAFDB`/`KOMMST`/`DZ` + LNK-Basis in `payslip_private.py`.
|
||||
|
||||
## Systematik (GP4, verifiziert)
|
||||
|
||||
- **Sätze 2026 (ÖGK):** DN 18,07 % gesamt = KV 3,87 · PV 10,25 ·
|
||||
ALV 2,95 · UV 0 + AK 0,50 + WF 0,50; **DG 20,98 %** = KV 3,78 ·
|
||||
PV 12,55 · ALV 2,95 · UV 1,10 + WF 0,50 + IESG 0,10.
|
||||
**Wien: DN 18,32 / DG 21,23 %** (WF gesamt 1,5 % = 0,75/0,75 ab
|
||||
1.1.2026, Wiener WF-Beitragstarif 2018 § 1 — SV-Werte-2026 Fn. 5).
|
||||
- **ALV-DN-Staffel § 2a AMPFG** (DN-seitig! ÖGK-Abschläge „Mind. AV
|
||||
auf 0/1/2 %" = −2,95/−1,95/−0,95): BG bis **2.225 €: 0 %** ·
|
||||
2.225–2.427 €: 1 % · 2.427–2.630 €: 2 % · darüber 2,95 % — DG-AV
|
||||
bleibt stets 2,95 %; Grenzen **nicht zu aliquotieren**; gilt auch
|
||||
für SZ-Beiträge (lb-son-03); § 2a mit 31.12.2026 aufgehoben
|
||||
(BGBl I 62/2026) — ab 2027 voller DN-Satz.
|
||||
- **SZ-Beiträge (§ 54 ASVG):** DN 14,12 % (KV+PV; AV nach Staffel);
|
||||
DG **20,48 %** = KV 3,78 + PV 12,55 + AV 2,95 + UV 1,10 + IESG 0,10
|
||||
(IESG folgt dem AV-Beitrag; ⚠ §-5-AMPFG-Volltext offen); **ohne
|
||||
AK/WF**; Deckel: HBG monatlich (2026: 6.930 €) und 60faches HBG je
|
||||
Kalenderjahr (SZ-Jahreshöchstbetrag 13.860 €) minus YTD-SZ-Basen.
|
||||
- **Geringfügigkeit (§ 5 Abs 2 ASVG):** 2026 **551,10 €** — die
|
||||
Aufwertung ist gem. **§ 810 Abs 3 ASVG ausgesetzt** (deshalb kein
|
||||
2026-Eintrag in der RIS-Anmerkungsreihe; A7-Rest gelöst). SZ zählen
|
||||
nicht zur Ermittlung; **untermonatiger Beginn/Ende → Hochrechnung**
|
||||
(Entgelt × 30 ÷ Kalendertage); Verhältnis < 1 Naturalmonat →
|
||||
Gesamtentgelt direkt gegen die Monatsgrenze (lb-bes-06); Lehrlinge
|
||||
nie geringfügig (§ 5 Abs 3).
|
||||
- **Geringfügig Beschäftigte:** nur UV-Pflicht; **DG-UV = 1,1 % der
|
||||
allgemeinen Beitragsgrundlage** (§ 53a Abs 1 ASVG) als Monatspauschale
|
||||
**6,50 €** 2026 (aBG = 83,49 ÷ 14,12 % = 591,29 € abgeleitet ⚠);
|
||||
Selbstversicherung KV+PV **83,49 €/Monat** (§ 77 Abs 2a ASVG; TASY
|
||||
KVPVBTG19A: 2024: 73,20 · 2025: 77,81 · 2026: 83,49) — **Direct-
|
||||
Zahlung der Person an den Träger, kein Lohnabzug**; Pauschalbeitrag
|
||||
auch von SZ (§ 53a Abs 5).
|
||||
- **DAG (§ 1 DAG):** 19,4 % der Lohnsumme (Beitragsgrundlagen ohne SZ)
|
||||
aller geringfügig Beschäftigten je Kalendermonat, wenn Lohnsumme >
|
||||
**826,65 €** (= 1,5 × GFG; TASY MINGRDAGP1) und ≥ 2 Geringfügige
|
||||
(„mit UV 20,5 %" = Summensicht; UV läuft separat über § 53a Abs 1;
|
||||
ab 60. LJ entfällt der UV-Anteil); Ausweis/Veranlagung GP8.
|
||||
- **Altersabhängige Satzausschaltungen** (Stichtags-Datumfelder am
|
||||
Vertrag, Wirken ab Beitragsmonat): ALV DN+DG **und** IESG entfallen
|
||||
(§ 1 Abs 2 lit e AlVG; § 12 Abs 1 Z 4 iVm Abs 2 IESG; ab 2027 inkl.
|
||||
Korridorpension, NOR40280219); UV entfällt (§ 51 Abs 6 ASVG); PV je
|
||||
hälftig DG+DN in der Bonusphase (§ 51 Abs 7 ASVG, „A 15"; Konto-
|
||||
gutschrift bleibt ungekürzt — mBGM GP7); FLAF+DZ ohne lit-f-AN ab
|
||||
Folgemonat nach 60 (§ 41 Abs 4 lit f FLAG — KommSt ohne Befreiung).
|
||||
- **Beitragsfreie Bezüge § 49 Abs 3 ASVG** (Grenzen `at_sv49_grenzen`,
|
||||
Stand 2026-07): Mahlzeiten-Gutscheine 8 €/AT (Lebensmittel 2 €/AT),
|
||||
Mitarbeiterrabatte ≤ 20 % je Fall ODER 1.000 €/Jahr (R1: Jahrespool),
|
||||
Betriebsveranstaltungen 365 €/Jahr, Jubiläums-Sachzuwendungen 186 €/Jahr,
|
||||
Zukunftssicherung 300 €/Jahr, Kinderbetreuungszuschuss 2.000 €/Kind/Jahr
|
||||
(R1: Pool je DN), Homeoffice-Pauschale 3 €/Tag max 100 Tage — als
|
||||
Jahres-Kumulative je DN mit Umwidmung des Überschusses.
|
||||
- **LNK (FLAF/KommSt/DZ):** BG = monatlich gezahlte Arbeitslöhne
|
||||
(laufend + im Monat gezahlte §-67-Bezüge, Zufluss; kein SV-Abzug)
|
||||
ohne §-67-Abs-3/6-Bezüge; **FLAF 3,7 %** (§ 41 Abs 5 FLAG; 2,7 % ab
|
||||
2028), **KommSt 3 %** (§ 9 KommStG), **DZ** nur WKO-Mitglieder
|
||||
(§§ 122/126 WKG; Landeskammersatz je BL inkl. Bundesanteil 0,12 %,
|
||||
2026: 0,31–0,40 %, ⚠ WKO-Verifikation 8.11 offen); Freibetragsstaffel
|
||||
ident: ≤ 1.095 € keine Abgabe · bis 1.460 € → BG − 1.095 € · darüber
|
||||
voll.
|
||||
- **Beitragsmonat (Anspruchsprinzip):** Regel-Feld
|
||||
`l10n_at_beitragsmonat` (default Abrechnungsmonat) — Sätze, HBG und
|
||||
GFG werden je Beitragsmonat historisch versioniert aufgelöst
|
||||
(Nachzahlungslinien); Lohnsteuer rollt kumulativ in den Zuflussmonat
|
||||
(GP3). mBGM-Nachträge (Storno+Neuanmeldung): GP7.
|
||||
|
||||
## RF-SV-1: Vollmonat November mit B13 (VG II Stufe 1, 2.059,41 €)
|
||||
|
||||
Erweitert GP3-RF-L1 um DG-Seite und LNK; **GP4-Korrektur: §-2a-Staffel
|
||||
mindert den DN-AV auf 0 %** (2.059,41 ≤ 2.225) — DN-SV 15,12 % statt
|
||||
pauschal 18,07 %.
|
||||
|
||||
| Posten | Betrag |
|
||||
|---|---|
|
||||
| DN-SV laufend (15,12 %: KV 79,70 · PV 211,08 · ALV 0 · AK 10,30 · WF 10,30) | **311,38 €** |
|
||||
| SV-DN auf B13 (SVDN_SZ, 14,12 % = 290,79) | **290,79 €** |
|
||||
| DG-SV laufend (20,98 % = 432,04) | **432,04 €** |
|
||||
| DG-SV auf B13 (20,48 % = 421,77) | **421,77 €** |
|
||||
| FLAF-DB (3,7 % × 4.118,82) | **152,40 €** |
|
||||
| KommSt (3 % × 4.118,82) | **123,56 €** |
|
||||
| DZ (kein WKO-Mitglied) | 0,00 € |
|
||||
|
||||
- LSt-lfd: Bemessung 2.059,41 − 311,38 = 1.748,03 → JBG 20.784,36 →
|
||||
Tarif 1.450,87 − 496 = 954,87 ÷ 12 → **79,57 €**; LSt-SZ:
|
||||
(2.059,41 − 290,79 − 620) × 6 % = **68,92 €**.
|
||||
- Netto = 4.118,82 − (311,38 + 290,79 + 79,57 + 68,92) =
|
||||
**3.368,16 €** (SVDN_SZ-Nachtrag; GP3 hatte den SV-DN auf der B13
|
||||
nicht als Abzugszeile — Netto war um 290,79 € zu hoch).
|
||||
|
||||
## RF-SV-2: Wien (WF-Zuschlag ab 1.1.2026)
|
||||
|
||||
- SVDN_WF/SVDG_WF je 0,75 % (statt 0,50) → DN-SV 18,37 %, DG-SV
|
||||
21,23 %; vor 1.1.2026 gilt der Bundesstandard (Satzvektor-Zeilen
|
||||
`at_sv_wf_vektor`: 2019 default; 2026 wien+default).
|
||||
|
||||
## RF-SV-3: Geringfügige Beschäftigung (500 €/Monat)
|
||||
|
||||
- Hochgerechnetes Entgelt 500 ≤ 551,10 → geringfügig: **keine**
|
||||
SVDN-/SVDG-Beiträge (KV/PV/AV/AK/WF entfallen); stattdessen
|
||||
**SVDG_UV_GFG 6,50 €** (§ 53a Abs 1); keine LSt (Tarifzone).
|
||||
Selbstversicherung KV+PV 83,49 €/Monat zahlt die Person direkt an
|
||||
den Träger (kein Lohnabzug; SV-Werte-2026 Fn. 9).
|
||||
- Untermonatiger Beginn 16.1.: 400 € → 750 € hochgerechnet → **nicht**
|
||||
geringfügig (Vollversicherung); 250 € → 468,75 → geringfügig.
|
||||
|
||||
## RF-SV-4: DAG (§ 1 DAG)
|
||||
|
||||
- 2 Geringfügige à 500/550 € im Jänner: Lohnsumme 1.050 > 826,65
|
||||
(Schwelle = 1,5 × 551,10) → DAG = 1.050 × 19,4 % = **204,30 €**
|
||||
(Company-Bewertung `_l10n_at_dag`; Ausweis GP8). 2 × 400 € = 800 →
|
||||
unter der Schwelle → keine DAG; nur 1 Geringfügige(r) → keine DAG.
|
||||
|
||||
## RF-SV-5: Altersabhängige Satzausschaltungen
|
||||
|
||||
- **63 + Pensionsanspruch** (`l10n_at_alv_entfall_ab`): ALV DN+DG und
|
||||
IESG entfallen → DG 17,93 % statt 20,98 %; Nachzahlungslinie mit
|
||||
Beitragsmonat vor dem Stichtag zahlt weiter ALV (Anspruchsprinzip).
|
||||
- **60** (`l10n_at_uv_entfall_ab`): UV entfällt laufend und auf SZ
|
||||
→ DG 19,88 %; geringfügige 61-Jährige: keine UV-Pauschale.
|
||||
- **Bonusphase** (`l10n_at_pv_bonusphase_ab`): PV hälftig → DN 5,125 /
|
||||
DG 6,275 % (§ 51 Abs 7 ASVG); Pensionskonto-Gutschrift mit voller
|
||||
BG (mBGM-A 15, GP7).
|
||||
- **Lit f** (`l10n_at_lnkp_frei_ab`): FLAF und DZ entfallen ab
|
||||
Folgemonat nach 60; KommSt bleibt.
|
||||
|
||||
## RF-SV-6: § 49 Abs 3 Kumulative
|
||||
|
||||
- Mahlzeiten: 110 € auf 10 Arbeitstagen → 8 € × 10 = 80 € beitragsfrei,
|
||||
30 € Umwidmung → SV-BG 2.059,41 + 110 − 80 = 2.089,41.
|
||||
- Betriebsveranstaltung: März 300 € frei (Rest 65), April wieder 300 €
|
||||
→ nur 65 frei; Mai Pool verbraucht → 0.
|
||||
- Homeoffice: April 70 Tage à 3 € frei; Mai Rest 30 Tage → 90 € frei.
|
||||
- Lehrling (§ 61 AKG / § 51 Abs 6 / § 12 Abs 2 IESG): keine AK-, UV-,
|
||||
IESG-Beiträge; nie geringfügig (§ 5 Abs 3); DN 14,62 % (AV 0 nach
|
||||
Staffel bei 300 €), DG 19,78 %.
|
||||
|
||||
## RF-SV-7: Beitragsmonats-Allokation (Nachzahlung)
|
||||
|
||||
- Jänner 2026: laufend 7.000 € + Nachzahlungslinie 7.000 € mit
|
||||
Beitragsmonat 6/2025 → zwei Gruppen mit je eigener HBG: 6.930 €
|
||||
(2026) und **6.450 €** (2025 = 30 × 215 €/Kalendertag, KB A8);
|
||||
SVDG_KV = (6.930 + 6.450) × 3,78 %.
|
||||
|
||||
## Offen / Verifikationspunkte (GP7/GP8)
|
||||
|
||||
- **UV-Pauschale 6,50 €** abgeleitet (aBG 591,29 = 83,49 ÷ 14,12 %;
|
||||
§ 53a Abs 1/3) — direkter Beleg (SV-Werte-Tabellenzug) bei der
|
||||
GP8-Parameterpflege nachziehen.
|
||||
- **IESG auf SZ** (0,10 %) aus der ÖGK-Tarifsystematik (IE-Spalte auf
|
||||
allen Beitragsgrundlagen des Tarifs) — §-5-AMPFG/§-12-IESG-Volltext-
|
||||
Verifikation offen.
|
||||
- **DZ-Landeskammersätze** (lb-lnk-07, Stand 2026-08) — WKO/WKG-Volltext
|
||||
vor Freischaltung von Wien-Mandanten (8.11).
|
||||
- DAG-Zahlungsrhythmus („jährlich", lb-bes-06) aus dem §-1-DAG-Volltext
|
||||
(RIS) für den GP8-Ausweis; Geringfügigkeits-Bewertung bei Nachzahlung
|
||||
je Beitragsmonat (Stichtagslogik) als GP8-Verfeinerung.
|
||||
- Formel 7 (A3): konservative GP3-Verteilung (§-68-Zuschläge verbleiben
|
||||
in der laufenden SV-BG); Prämienoptimierung offener Designpunkt.
|
||||
@@ -305,6 +305,78 @@ class HrPayslip(models.Model):
|
||||
monate = {l.slip_id.id for l in linien}
|
||||
return len(monate) >= 7, sum(l.total for l in linien) / 12.0
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Lohnnebenkosten FLAF-DG-Beitrag / KommSt / DZ (GP4; § 41 FLAG,
|
||||
# § 5+§ 9 KommStG, §§ 122/126 WKG — Werte/Staffeln im Kern)
|
||||
# ------------------------------------------------------------------
|
||||
def _at_lnk_basis(self, steuer, result_rules=None):
|
||||
"""LNK-Bemessungsgrundlage nach Freibetragsstaffel: monatlich
|
||||
gezahlte Arbeitslöhne (laufend + im Monat gezahlte §-67-Bezüge,
|
||||
Zuflussprinzip; kein SV-Abzug), ohne §-67-Abs-3/6-Bezüge
|
||||
(Abfertigung/Abfindung). 'flaf'/'dz' zusätzlich ohne lit-f-AN
|
||||
(Arbeitslöhne ab Folgemonat nach Vollendung des 60. Lebensjahres,
|
||||
§ 41 Abs 4 lit f FLAG — die Kommunalsteuer hat KEINE lit-f-
|
||||
Befreiung). Freibetrag: ≤ 1.095 € keine Abgabe, bis 1.460 € →
|
||||
Freibetrag 1.095 €, darüber volle BG (at_lnk_freibetrag)."""
|
||||
self.ensure_one()
|
||||
basis = (self._l10n_at_brutto('laufend', result_rules)
|
||||
+ self._l10n_at_brutto('sonstig', result_rules))
|
||||
for rule in self.struct_id.rule_ids:
|
||||
if rule.l10n_at_s67_abs in ('abs3', 'abs6'):
|
||||
if result_rules is not None and rule.code in result_rules:
|
||||
basis -= result_rules[rule.code]['total']
|
||||
elif result_rules is None:
|
||||
linie = self.line_ids.filtered(
|
||||
lambda l: l.code == rule.code)
|
||||
basis -= sum(linie.mapped('total'))
|
||||
basis = max(basis, 0.0)
|
||||
if steuer in ('flaf', 'dz'):
|
||||
version = self.version_id
|
||||
if (version.l10n_at_lnkp_frei_ab
|
||||
and self.date_from >= version.l10n_at_lnkp_frei_ab):
|
||||
return 0.0
|
||||
freibetrag = self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_lnk_freibetrag', self.date_to, raise_if_not_found=False) or {}
|
||||
grenze = float(freibetrag.get('grenze', 0.0))
|
||||
if basis <= 0.0:
|
||||
return 0.0
|
||||
if basis <= grenze:
|
||||
basis -= float(freibetrag.get('freibetrag', 0.0))
|
||||
return max(basis, 0.0)
|
||||
|
||||
def _at_flaf_db(self, result_rules=None):
|
||||
"""FLAF-Dienstgeberbeitrag § 41 FLAG (3,7 % ab 2025, 2,7 % ab
|
||||
2028 — at_flaf_db; BG s. _at_lnk_basis)."""
|
||||
self.ensure_one()
|
||||
basis = self._at_lnk_basis('flaf', result_rules)
|
||||
satz = float(self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_flaf_db', self.date_to, raise_if_not_found=False) or 0.0)
|
||||
return basis * satz / 100.0
|
||||
|
||||
def _at_kommst(self, result_rules=None):
|
||||
"""Kommunalsteuer § 9 KommStG 1993 (3 % — at_kommst_satz; BG
|
||||
§ 5 Abs 2: ohne §-67-Abs-3/6-Bezüge, ohne lit-f-Befreiung)."""
|
||||
self.ensure_one()
|
||||
basis = self._at_lnk_basis('kommst', result_rules)
|
||||
satz = float(self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_kommst_satz', self.date_to, raise_if_not_found=False) or 0.0)
|
||||
return basis * satz / 100.0
|
||||
|
||||
def _at_dz(self, result_rules=None):
|
||||
"""Zuschlag zum Dienstgeberbeitrag (§§ 122/126 WKG) für WKO-
|
||||
Mitgliedsbetriebe: Landeskammersatz je Betriebsstätten-Bundesland
|
||||
inkl. Bundeskammeranteil (at_dz_vektor; ⚠ WKO-Verifikation 8.11);
|
||||
BG identisch FLAF-DB inkl. lit f (lb-lnk-07)."""
|
||||
self.ensure_one()
|
||||
if not self.company_id.l10n_at_wk_mitglied:
|
||||
return 0.0
|
||||
basis = self._at_lnk_basis('dz', result_rules)
|
||||
vektor = self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_dz_vektor', self.date_to, raise_if_not_found=False) or {}
|
||||
satz = float((vektor.get('laender') or {}).get(
|
||||
self.company_id.l10n_at_bundesland or '', 0.0))
|
||||
return basis * satz / 100.0
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# All-in-Deckungsrechnung (§ 2g AVRAG) — minimale GP2-Umsetzung:
|
||||
# Jahresvergleich geschuldete ÜStd-Vergütung vs. erhaltene Pauschale
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# Part of the odoo-at-payroll project. License: LGPL-3.
|
||||
from . import test_kv_katalog
|
||||
from . import test_entgelt_private
|
||||
from . import test_lst_private
|
||||
from . import test_lst_private
|
||||
from . import test_sv_private
|
||||
@@ -369,8 +369,8 @@ class EntgeltPrivateTest(TransactionCase):
|
||||
# Netto / All-in
|
||||
# ------------------------------------------------------------------
|
||||
def test_20_netto_mit_dn_abzuegen(self):
|
||||
"""GP3: Netto = ATP_BRUTTO − ATP_ABZUG — SVDN + LSt laufen
|
||||
real mit (AP3-Kern angebunden)."""
|
||||
"""GP3/GP4: Netto = ATP_BRUTTO − ATP_ABZUG — SVDN (inkl. SVDN_SZ
|
||||
auf der B13/B14, § 67 Abs 12) + LSt laufen real mit."""
|
||||
employee = self._employee(stufe=1)
|
||||
slip = self._compute(employee, 11)
|
||||
brutto = sum(
|
||||
@@ -383,9 +383,9 @@ class EntgeltPrivateTest(TransactionCase):
|
||||
abzug = sum(
|
||||
self._total(slip, code)
|
||||
for code in ('SVDN_KV', 'SVDN_PV', 'SVDN_AV', 'SVDN_AK',
|
||||
'SVDN_WF', 'LST_LFD', 'LST_SZ'))
|
||||
'SVDN_WF', 'SVDN_SZ', 'LST_LFD', 'LST_SZ'))
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'NETTO'), brutto - abzug, places=2)
|
||||
self._total(slip, 'NETTO'), brutto - abzug, places=1)
|
||||
|
||||
def test_21_allin_deckungsrechnung(self):
|
||||
"""§ 2g AVRAG: Jahresdeckung = 12 × Pauschale vs. geschuldete
|
||||
|
||||
@@ -88,32 +88,35 @@ class LstPrivateTest(TransactionCase):
|
||||
self._total(slip, 'SVDN_KV'), 2059.41 * 0.0387, places=2)
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'SVDN_PV'), 2059.41 * 0.1025, places=2)
|
||||
# § 2a AMPFG: DN-AV 0 % bei BG 2.059,41 ≤ 2.225 (GP4-Staffel;
|
||||
# DG-AV bleibt 2,95 %) → DN-Gesamt 15,12 %
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'SVDN_AV'), 2059.41 * 0.0295, places=2)
|
||||
self._total(slip, 'SVDN_AV'), 0.0, places=2)
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'SVDN_AK'), 2059.41 * 0.005, places=2)
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'SVDN_WF'), 2059.41 * 0.005, places=2)
|
||||
self.assertAlmostEqual(self._total(slip, 'B13'), 2059.41, places=2)
|
||||
# LSt-lfd: Bemessung 1686,50 → JBG 20.046,06 → (1301,41 − 496)/12
|
||||
bem = 2059.41 - 2059.41 * 0.1807
|
||||
# LSt-lfd: Bemessung 1.748,03 → JBG 20.784,36 → (1.450,87 − 496)/12
|
||||
bem = 2059.41 - 2059.41 * 0.1512
|
||||
jbg = bem * 12 - 132 - 60
|
||||
erwartet_lfd = (max(0.0, 0.20 * (jbg - 13539.0) - 496.0)) / 12
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'LST_LFD'), erwartet_lfd, places=1)
|
||||
# LSt-SZ (§ 67): 2059,41 − SV-SZ (17,07 %) − 620 → 6 %
|
||||
sz_bem = 2059.41 - 2059.41 * 0.1707
|
||||
# LSt-SZ (§ 67): 2.059,41 − SV-SZ (14,12 %: KV+PV, AV 0) − 620 → 6 %
|
||||
sz_bem = 2059.41 - 2059.41 * 0.1412
|
||||
erwartet_sz = (sz_bem - 620.0) * 0.06
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'LST_SZ'), erwartet_sz, places=1)
|
||||
# Netto-Konsistenz: ATP_BRUTTO − ATP_ABZUG
|
||||
# Netto-Konsistenz: ATP_BRUTTO − ATP_ABZUG (inkl. SVDN_SZ auf
|
||||
# der B13 — § 67 Abs 12, GP4-Nachtrag)
|
||||
brutto = (self._total(slip, 'KVGEO') + self._total(slip, 'B13'))
|
||||
abzug = sum(
|
||||
self._total(slip, code) for code in
|
||||
('SVDN_KV', 'SVDN_PV', 'SVDN_AV', 'SVDN_AK', 'SVDN_WF',
|
||||
'LST_LFD', 'LST_SZ'))
|
||||
'SVDN_SZ', 'LST_LFD', 'LST_SZ'))
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'NETTO'), brutto - abzug, places=2)
|
||||
self._total(slip, 'NETTO'), brutto - abzug, places=1)
|
||||
|
||||
def test_02_rollung_zweiter_monat(self):
|
||||
"""Kumulative §-66-Rollung: Februar zahlt die Differenz."""
|
||||
@@ -131,7 +134,7 @@ class LstPrivateTest(TransactionCase):
|
||||
self._slip(employee, 10, confirm=True)
|
||||
slip_nov = self._slip(employee, 11, confirm=True)
|
||||
sz_nov = self._total(slip_nov, 'LST_SZ')
|
||||
sz_bem = 2059.41 - 2059.41 * 0.1707
|
||||
sz_bem = 2059.41 - 2059.41 * 0.1412
|
||||
self.assertAlmostEqual(sz_nov, (sz_bem - 620.0) * 0.06, places=1)
|
||||
slip_dez = self._slip(employee, 12)
|
||||
self.assertAlmostEqual(
|
||||
@@ -183,6 +186,8 @@ class LstPrivateTest(TransactionCase):
|
||||
self.assertAlmostEqual(self._total(slip, 'B13'), 2199.15, places=2)
|
||||
# B14-Dezember-Fallback (kein Urlaub im Jahr) — läuft mit
|
||||
self.assertAlmostEqual(self._total(slip, 'B14'), 2199.15, places=2)
|
||||
sz_bem = 2 * 2199.15 - 2 * 2199.15 * 0.1707
|
||||
# B14-Dezember-Fallback (kein Urlaub im Jahr) — läuft mit;
|
||||
# 2.199,15 ≤ 2.225 → DN-AV 0 (§ 2a) → SV-SZ 14,12 %
|
||||
sz_bem = 2 * 2199.15 - 2 * 2199.15 * 0.1412
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'LST_SZ'), (sz_bem - 620.0) * 0.06, places=1)
|
||||
@@ -0,0 +1,245 @@
|
||||
# Part of the odoo-at-payroll project. License: LGPL-3.
|
||||
"""GP4 SV/DB-Integration auf der privatwirtschaftlichen Structure:
|
||||
DG-Beitragsblock (SVDG_*, SVDG_SZ_*, §-53a-UV), SVDN_SZ-Nachtrag
|
||||
(§ 67 Abs 12 — Netto-Korrektur), FLAF-Dienstgeberbeitrag (§ 41 FLAG),
|
||||
Kommunalsteuer (§ 9 KommStG) und Zuschlag zum DG-Beitrag (§§ 122/126
|
||||
WKG) mit Freibetragsstaffel 1.095/1.460 € und lit-f-Befreiung."""
|
||||
from datetime import date, timedelta
|
||||
|
||||
from odoo.tests import TransactionCase, tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class SvPrivateTest(TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.structure = self.env.ref(
|
||||
'l10n_at_hr_payroll_private.structure_at_privat')
|
||||
self.kv2203 = self.env.ref(
|
||||
'l10n_at_hr_payroll_private.kv_si_2203')
|
||||
self.gruppe_ii = self.env.ref(
|
||||
'l10n_at_hr_payroll_private.kv2203_grp_ii')
|
||||
self.calendar = self.env['resource.calendar'].create({
|
||||
'name': 'AT Test 40h Mo-Fr',
|
||||
'tz': 'Europe/Vienna',
|
||||
'hours_per_day': 8,
|
||||
'attendance_ids': [
|
||||
(0, 0, {'name': 'Tag %d' % wd, 'dayofweek': str(wd),
|
||||
'hour_from': 8.0, 'hour_to': 16.0})
|
||||
for wd in range(5)
|
||||
],
|
||||
})
|
||||
self.env.company.resource_calendar_id = self.calendar
|
||||
|
||||
def _employee(self, version_vals=None):
|
||||
employee = self.env['hr.employee'].create({
|
||||
'name': 'Test SV privat',
|
||||
})
|
||||
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),
|
||||
'kv_id': self.kv2203.id,
|
||||
'kv_gruppe_id': self.gruppe_ii.id,
|
||||
'erfahrungsstufe': 1,
|
||||
'resource_calendar_id': self.calendar.id,
|
||||
})
|
||||
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-Privat %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
|
||||
|
||||
def _total(self, slip, code):
|
||||
return sum(slip.line_ids.filtered(
|
||||
lambda l: l.code == code).mapped('total'))
|
||||
|
||||
# Hilfsstruktur für LNK-Staffel-/Ausnahmetests (Fixbeträge statt
|
||||
# KV-Katalog, um die Freibetragszonen gezielt zu erreichen).
|
||||
def _lnk_struktur(self, code, regeln):
|
||||
struktur = self.env['hr.payroll.structure'].create({
|
||||
'name': 'Test AT LNK %s' % code,
|
||||
'code': 'TEST_AT_LNK_%s' % code,
|
||||
'type_id': self.structure.type_id.id,
|
||||
'country_id': self.env.ref('base.at').id,
|
||||
})
|
||||
category = self.env.ref(
|
||||
'l10n_at_hr_payroll_private.category_atp_brutto')
|
||||
for regel_code, betrag, bemessung, s67 in regeln:
|
||||
self.env['hr.salary.rule'].create({
|
||||
'name': regel_code,
|
||||
'code': regel_code,
|
||||
'struct_id': struktur.id,
|
||||
'category_id': category.id,
|
||||
'condition_select': 'none',
|
||||
'l10n_at_bemessung': bemessung,
|
||||
'l10n_at_s67_abs': s67,
|
||||
'amount_select': 'fix',
|
||||
'amount_fix': betrag,
|
||||
})
|
||||
return struktur
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# RF-L1 erweitert: DG-Block + LNK auf dem November-Lauf mit B13
|
||||
# ------------------------------------------------------------------
|
||||
def test_01_dg_block_und_lnk(self):
|
||||
"""November mit B13: SVDG 20,98 % + SVDG_SZ 20,48 % (ATP_DG,
|
||||
ohne Nettoeffekt); FLAF 3,7 % und KommSt 3 % auf der LNK-BG
|
||||
(laufend + gezahlte SZ, > 1.460 € → volle BG)."""
|
||||
employee = self._employee()
|
||||
slip = self._slip(employee, 11)
|
||||
self.assertAlmostEqual(self._total(slip, 'KVGEO'), 2059.41, places=2)
|
||||
self.assertAlmostEqual(self._total(slip, 'B13'), 2059.41, places=2)
|
||||
# DG laufend (ÖGK 2026: 20,98 %)
|
||||
for code, satz in (('SVDG_KV', 0.0378), ('SVDG_PV', 0.1255),
|
||||
('SVDG_AV', 0.0295), ('SVDG_UV', 0.011),
|
||||
('SVDG_WF', 0.005), ('SVDG_IESG', 0.001)):
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, code), 2059.41 * satz, places=2)
|
||||
# DG auf der B13 (§ 54 ASVG: KV/PV/AV/UV + IESG)
|
||||
for code, satz in (('SVDG_SZ_KV', 0.0378), ('SVDG_SZ_PV', 0.1255),
|
||||
('SVDG_SZ_AV', 0.0295), ('SVDG_SZ_UV', 0.011),
|
||||
('SVDG_SZ_IESG', 0.001)):
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, code), 2059.41 * satz, places=2)
|
||||
# LNK: BG = 2.059,41 + 2.059,41 = 4.118,82 > 1.460 → voll
|
||||
flaf = 2 * 2059.41 * 0.037
|
||||
kommst = 2 * 2059.41 * 0.03
|
||||
self.assertAlmostEqual(self._total(slip, 'FLAFDB'), flaf, places=2)
|
||||
self.assertAlmostEqual(self._total(slip, 'KOMMST'), kommst, places=2)
|
||||
# DZ nur für WKO-Mitglieder (Default aus)
|
||||
self.assertAlmostEqual(self._total(slip, 'DZ'), 0.0, places=2)
|
||||
|
||||
def test_02_netto_mit_svdn_sz(self):
|
||||
"""SVDN_SZ-Nachtrag (§ 67 Abs 12): die SV-DN auf der B13 ist
|
||||
eigene Abzugszeile — §-2a-Staffel: SV-SZ 14,12 % (AV-DN 0)
|
||||
= 290,79 € statt der GP3-Pauschale 18,07 %."""
|
||||
employee = self._employee()
|
||||
slip = self._slip(employee, 11)
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'SVDN_SZ'), 2059.41 * 0.1412, places=2)
|
||||
brutto = (self._total(slip, 'KVGEO') + self._total(slip, 'B13'))
|
||||
abzug = sum(
|
||||
self._total(slip, code) for code in
|
||||
('SVDN_KV', 'SVDN_PV', 'SVDN_AV', 'SVDN_AK', 'SVDN_WF',
|
||||
'SVDN_SZ', 'LST_LFD', 'LST_SZ'))
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'NETTO'), brutto - abzug, places=1)
|
||||
|
||||
def test_03_wien_dg(self):
|
||||
"""Wien: SVDG_WF 0,75 % (Satzvektor, Wiener WF-Beitragstarif
|
||||
2018 § 1; DG-Gesamt 21,23 %)."""
|
||||
employee = self._employee()
|
||||
slip = self._slip(employee, 1)
|
||||
slip.company_id.write({'l10n_at_wf_wien': True})
|
||||
slip.compute_sheet()
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'SVDG_WF'), 2059.41 * 0.0075, places=2)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# LNK-Mechanik: Freibetragsstaffel, §-67-Abs-3/6, lit f
|
||||
# ------------------------------------------------------------------
|
||||
def test_04_lnk_freibetragsstaffel(self):
|
||||
"""Staffel § 41 Abs 4 FLAG (wortgleich § 9 KommStG): ≤ 1.095 €
|
||||
keine Abgabe · 1.095–1.460 € → Freibetrag 1.095 € · darüber voll."""
|
||||
employee = self._employee()
|
||||
struktur = self._lnk_struktur('A', [('LFD', 1000.0, 'laufend', 'keine')])
|
||||
slip_a = self._slip(employee, 1, struct=struktur)
|
||||
self.assertAlmostEqual(slip_a._at_lnk_basis('flaf'), 0.0, places=2)
|
||||
struktur_b = self._lnk_struktur(
|
||||
'B', [('LFD', 1000.0, 'laufend', 'keine'),
|
||||
('SZ', 300.0, 'sonstig', 'keine')])
|
||||
employee_b = self._employee()
|
||||
slip_b = self._slip(employee_b, 2, struct=struktur_b)
|
||||
# 1.300 € → Freibetrag: 1.300 − 1.095 = 205 €
|
||||
self.assertAlmostEqual(slip_b._at_lnk_basis('kommst'), 205.0, places=2)
|
||||
self.assertAlmostEqual(
|
||||
slip_b._at_flaf_db(), 205.0 * 0.037, places=2)
|
||||
self.assertAlmostEqual(slip_b._at_kommst(), 205.0 * 0.03, places=2)
|
||||
struktur_c = self._lnk_struktur(
|
||||
'C', [('LFD', 5000.0, 'laufend', 'keine')])
|
||||
employee_c = self._employee()
|
||||
slip_c = self._slip(employee_c, 3, struct=struktur_c)
|
||||
self.assertAlmostEqual(slip_c._at_lnk_basis('flaf'), 5000.0, places=2)
|
||||
|
||||
def test_05_lnk_s67_abs3(self):
|
||||
"""Abfertigungen (§ 67 Abs 3 EStG) und Abfindungen (Abs 6) sind
|
||||
aus der FLAF-/KommSt-BG ausgenommen (§ 41 Abs 4 FLAG, § 5 Abs 2
|
||||
KommStG)."""
|
||||
employee = self._employee()
|
||||
struktur = self._lnk_struktur(
|
||||
'D', [('LFD', 2000.0, 'laufend', 'keine'),
|
||||
('ABF', 10000.0, 'sonstig', 'abs3')])
|
||||
slip = self._slip(employee, 1, struct=struktur)
|
||||
self.assertAlmostEqual(slip._at_lnk_basis('flaf'), 2000.0, places=2)
|
||||
self.assertAlmostEqual(slip._at_lnk_basis('kommst'), 2000.0, places=2)
|
||||
|
||||
def test_06_lnk_lit_f(self):
|
||||
"""§ 41 Abs 4 lit f FLAG: Arbeitslöhne ab dem Folgemonat nach
|
||||
Vollendung des 60. LJ entfallen aus FLAF- und DZ-BG — die
|
||||
Kommunalsteuer bleibt pflichtig."""
|
||||
employee = self._employee(
|
||||
{'l10n_at_lnkp_frei_ab': date(2026, 1, 1)})
|
||||
struktur = self._lnk_struktur(
|
||||
'E', [('LFD', 2000.0, 'laufend', 'keine')])
|
||||
slip = self._slip(employee, 1, struct=struktur)
|
||||
self.assertAlmostEqual(slip._at_lnk_basis('flaf'), 0.0, places=2)
|
||||
self.assertAlmostEqual(slip._at_lnk_basis('dz'), 0.0, places=2)
|
||||
self.assertAlmostEqual(
|
||||
slip._at_lnk_basis('kommst'), 2000.0, places=2)
|
||||
|
||||
def test_07_dz_wko(self):
|
||||
"""DZ (§§ 122/126 WKG): 2026 Landeskammersatz inkl. Bundesanteil
|
||||
je Betriebsstätten-Bundesland (Wien 0,36 %; lb-lnk-07)."""
|
||||
employee = self._employee()
|
||||
slip = self._slip(employee, 1) # Jänner: nur laufender Bezug
|
||||
slip.company_id.write({
|
||||
'l10n_at_wk_mitglied': True, 'l10n_at_bundesland': 'wien'})
|
||||
slip.compute_sheet()
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'DZ'), 2059.41 * 0.0036, places=2)
|
||||
# Ohne WKO-Mitgliedschaft entfällt der DZ vollständig
|
||||
slip.company_id.write({'l10n_at_wk_mitglied': False})
|
||||
slip.compute_sheet()
|
||||
self.assertAlmostEqual(self._total(slip, 'DZ'), 0.0, places=2)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Geringfügiger AN end-to-end (§ 53a Abs 1 ASVG)
|
||||
# ------------------------------------------------------------------
|
||||
def test_08_geringfuegig_ende_zu_ende(self):
|
||||
"""Geringfügig Beschäftigter (Überzahlung 500 € ≤ GFG): keine
|
||||
SVDN/SVDG-Zeilen, nur §-53a-UV 6,50 € (ATP_DG); kein SV-Abzug
|
||||
und keine LSt → Netto = Brutto."""
|
||||
employee = self._employee({'ueberzahlung': 500.0})
|
||||
slip = self._slip(employee, 1)
|
||||
self.assertAlmostEqual(self._total(slip, 'KVGEO'), 500.0, places=2)
|
||||
self.assertTrue(slip.l10n_at_geringfuegig)
|
||||
for code in ('SVDN_KV', 'SVDN_PV', 'SVDN_AV', 'SVDN_AK',
|
||||
'SVDN_WF', 'SVDG_KV', 'SVDG_PV', 'SVDG_AV',
|
||||
'SVDG_UV', 'SVDG_WF', 'SVDG_IESG'):
|
||||
self.assertAlmostEqual(self._total(slip, code), 0.0, places=2)
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'SVDG_UV_GFG'), 6.50, places=2)
|
||||
# LSt: Bemessung 500 − 0 → Tarif unterhalb der Belastungszone
|
||||
self.assertAlmostEqual(self._total(slip, 'LST_LFD'), 0.0, places=1)
|
||||
self.assertAlmostEqual(
|
||||
self._total(slip, 'NETTO'), 500.0, places=2)
|
||||
Reference in New Issue
Block a user