Compare commits
3 Commits
f638f5100d
...
c8d080f371
| Author | SHA1 | Date | |
|---|---|---|---|
| c8d080f371 | |||
| 04099fef39 | |||
| a2a823ad35 |
+63
-24
@@ -2,22 +2,36 @@
|
||||
|
||||
## Current focus
|
||||
|
||||
**GP3 Lohnsteuer im Kern umgesetzt und grün (52/52 Tests) — GP4
|
||||
SV/DB (AP4) als Nächstes** (2026-09-11): Kern 19.0.2.0.0
|
||||
(`lohnsteuer.py` § 33/§ 66 kumulativ-Rollung/§ 67 Sechstel-Aufrollung/
|
||||
§ 68, Lohnsteuertage 30/Monat, user-Bemessungsformeln) +
|
||||
`rule_parameters_lst_2026.xml` + Flags; privat 19.0.3.0.0 (dünne
|
||||
SVDN_*/LST-Regeln, B13/B14/UE-§-68-Flags). P0: AN-AB entfallen
|
||||
(Reform), Verkehrs-AB 496 €, SV monatlich stets voll (60 % = nur
|
||||
Veranlagung — RQ-5 korrigiert), § 124b Z 440: 15 ÜStd/170 € 2026.
|
||||
D4: result_rules-Threading (Zeilen erst nach Regelschleife),
|
||||
result_qty für Stundendarstellung; TASY-Wizard-Latenzfehler
|
||||
behoben (b64-Dekode + Werte-Records-API), TASY-Suite erstmals
|
||||
grün. Parallel lief die 3. RIS-Runde des Konflikt-Agents:
|
||||
|
||||
**3. RIS-Runde integriert (11.09.2026, `.additional_docs/ris_normtexte/`)**
|
||||
— A-Punkte gegen die Tagesfassung textverifiziert; Integration in RQ/
|
||||
PLAN/RUNBOOK/KB-KONFLIKTE + 5 Layer-2-Abgleichnotizen. **A1-Korrektur:**
|
||||
**GP4 SV/DB umgesetzt und grün (74/74 Tests) — GP5 Abfertigung Neu
|
||||
(BMSVG) ist der nächste Bauabschnitt** (2026-09-11): Kern 19.0.3.0.0
|
||||
(`models/sozialversicherung.py`: DG-Beiträge 20,98 %/Wien 21,23,
|
||||
§-54-SZ 20,48 %, Geringfügigkeit § 5/§ 810-3 mit Hochrechnung +
|
||||
§-53a-UV 6,50 €, §-49-Abs-3-Jahreskumulative, Altersstichtage als
|
||||
Datumsfelder am Vertrag, ALV-DN-Staffel § 2a DN-seitig, WF-Vektor,
|
||||
Beitragsmonats-Allokation mit 2025-HBG 6.450, DAG § 1 DAG) +
|
||||
`rule_parameters_sv_2026.xml`; privat 19.0.4.0.0 (SVDN_SZ-Nachtrag
|
||||
§ 67 Abs 12, DG-Block ATP_DG, FLAFDB/KOMMST/DZ flag-gated, LNK-Basis
|
||||
§ 41/§ 5 mit Freibetragsstaffel 1.095/1.460). **P0-Rechtsfund GP4:**
|
||||
GFG 2026 = 551,10 € — Aufwertung per **§ 810 Abs 3 ASVG ausgesetzt**
|
||||
(A7-Rest gelöst; RIS-Anmerkungsreihe hat deshalb keinen 2026-
|
||||
Eintrag); DAG-Grenze 826,65 = 1,5×GFG (TASY MINGRDAGP1, § 1 DAG als
|
||||
Normzitat per ÖGK-Tarifsystem — lb-sva-12-⚠ erledigt); §-19a-
|
||||
Selbstversicherung 2026 = 83,49 € (TASY KVPVBTG19A; Zahlung DIREKT
|
||||
an den Träger — kein Lohnabzug, SV-Werte Fn. 9); aBG 591,29
|
||||
abgeleitet → UV 6,50 €/Monat ⚠. **Rechtskorrektur § 2a AMPFG:**
|
||||
Staffel ist DN-seitig (ÖGK „Mind. AV auf 0/1/2 %" = −2,95/−1,95/
|
||||
−0,95) und gilt auch für SZ — DN-SV bei 2.059,41 € BG = 15,12 %
|
||||
statt 18,07 % → GP3-Rechenfälle RF-L1/L3/L5 + betroffene Tests
|
||||
nachgezogen („862,25“ des Nutzers war Zifferndreher; 1,5×551,10 =
|
||||
826,65). Offen aus GP4: UI der Vertrags-/Company-Felder (GP8),
|
||||
DAG-Ausweis/Veranlagung + UV-Pauschalen-Direktbeleg (GP8), DZ-
|
||||
WKO-Satzverifikation (8.11) vor Wien-Mandanten, IESG-auf-SZ-§-5-
|
||||
AMPFG-Volltext, mBGM-Nachtragslogik (GP7). Vor GP5: DZ-8.11-
|
||||
Entscheidung gilt als erledigt (flag-gated umgesetzt); Formel-7 (A3)
|
||||
bleibt Change-Request-Optimierung. **3. RIS-Runde integriert**
|
||||
(11.09.2026, `.additional_docs/ris_normtexte/`) — A-Punkte gegen die
|
||||
Tagesfassung textverifiziert; Integration in RQ/PLAN/RUNBOOK/KB-
|
||||
KONFLIKTE + 5 Layer-2-Abgleichnotizen. **A1-Korrektur:**
|
||||
§-124b-ÜStd-Maßnahme 2026 = **Z 440 lit c idF BGBl I 4/2026** (15 ÜStd/
|
||||
170 € durchgehend 2026, Aufrollung 31.05.2026); „Z 476 lit c idgF
|
||||
BGBl I 43/2026“ = Fehlzitat (Z 476 = Pendlerpauschale); Z 492/494 =
|
||||
@@ -792,7 +806,29 @@ B17-Inhalt/B18; Kleinverifikationen s. KB-KONFLIKTE „Nächste Schritte“).
|
||||
|
||||
## Decisions & conventions
|
||||
|
||||
- **D4-Runtime-Mechanik Odoo 19 (GP2-Verifikationen 2026-09-11)**:
|
||||
- **GP4-Konventionen (2026-09-11, Nutzer-freigegebener Bauplan +**
|
||||
**Quellenverifikation):** (1) **§ 2a AMPFG wirkt nur DN-seitig**
|
||||
(tiers+dn_voll im Parameter; Grenzen nicht aliquotieren; gilt auch
|
||||
für SZ-Beiträge; ab 2027 tiers=[] = voller Satz); (2) Gering-
|
||||
führigkeitsprüfung auf §-49-bereinigter laufender BG mit Hoch-
|
||||
rechnung ×30/Kalendertage bei untermonatiger Beschäftigung, ohne
|
||||
SZ, Lehrlinge nie geringfügig; (3) §-19a-Selbstversicherung ist
|
||||
KEIN Lohnabzug (Direct-Zahlung an den Träger) — Engine zeigt nur
|
||||
§-53a-Abs-1-UV (6,50 €) als DG-Zeile; (4) SVDN_SZ = eigene
|
||||
Abzugszeile (§ 67 Abs 12, Netto-Korrektur); (5) DG-/LNK-Zeilen in
|
||||
Kategorie ATP_DG ohne Nettoeffekt; (6) DZ nur bei Company-Flag
|
||||
`l10n_at_wk_mitglied`, Satzvektor je `l10n_at_bundesland` (WKO-
|
||||
Verifikation 8.11 offen); (7) Altersstichtage als DATUMS-Felder
|
||||
`l10n_at_*_ab` am Vertrag, Wirken je Beitragsmonat (Anspruchs-
|
||||
prinzip), UI GP8; (8) Beitragsmonat je Regel (`l10n_at_beitrags-
|
||||
monat`) + Lohnkontolinie (stored compute), historische Sätze/HBG
|
||||
je Gruppe; (9) §-49-Mengen = Arbeitstage über quantity; (10) DAG
|
||||
als Company-Bewertung `_l10n_at_dag(monat)` ohne Lohnzettelzeile
|
||||
(Ausweis GP8); (11) LNK-Freibetragsstaffel zentral `_at_lnk_basis`
|
||||
(Zufluss; §-67-Abs-3/6 über Kern-Flag `l10n_at_s67_abs`; lit f nur
|
||||
FLAF/DZ — KommSt ohne Befreiung).
|
||||
|
||||
- **D4-Runtime-Mechanik Odoo 19 (GP2-Verifikationen 2026-09-11):**
|
||||
`hr.work.entry` ist **tageweise** (`date` + `duration` ≤ 24 h,
|
||||
kein datetime-Bereich; create braucht explizites `employee_id`);
|
||||
worked-days zählen **draft und validated** Entries; `hr.version`:
|
||||
@@ -969,11 +1005,14 @@ B17-Inhalt/B18; Kleinverifikationen s. KB-KONFLIKTE „Nächste Schritte“).
|
||||
- `.venv/` — Python-3.14-venv mit editable install (lokal,
|
||||
unversioniert); Dev-DB `odoo_dev` (PostgreSQL lokal)
|
||||
- `addons/l10n_at_hr_payroll_private/` — General-AT (GP1 KV-Framework
|
||||
+ Seed D2; **GP2 Entgelt-Engine umgesetzt 2026-09-11** —
|
||||
`test_kv_katalog` 8/8 + `test_entgelt_private` 21/21 auf
|
||||
`odoo_dev`; Rechenfall-Fixtures unter `docs/rechenfaelle/`;
|
||||
GP3 Kern-Bau als Nächstes)
|
||||
- `addons/l10n_at_hr_payroll/` — Bundes-Kern (SV/TASY + **GP3
|
||||
Lohnsteuer**: `models/lohnsteuer.py`, `rule_parameters_lst_2026.xml`;
|
||||
52/52 grün; GP4 SV/DB als Nächstes)
|
||||
+ Seed D2; GP2 Entgelt-Engine; GP3 LSt-Anbindung; **GP4 SV/DB
|
||||
umgesetzt 2026-09-11** — `test_kv_katalog` 8 + `test_entgelt_private`
|
||||
21 + `test_lst_private` 6 + `test_sv_private` 8 grün auf `odoo_dev`;
|
||||
Rechenfall-Fixtures unter `docs/rechenfaelle/` inkl.
|
||||
sozialversicherung.md; GP5 Abfertigung Neu als Nächstes)
|
||||
- `addons/l10n_at_hr_payroll/` — Bundes-Kern (SV/TASY + GP3 Lohnsteuer
|
||||
`models/lohnsteuer.py` + **GP4 SV/DB `models/sozialversicherung.py`**
|
||||
(DG/Geringfügigkeit/§ 49/Altersstichtage/§ 2a-Staffel/WF-Vektor/
|
||||
Beitragsmonat/DAG), `rule_parameters_lst_2026.xml` +
|
||||
`rule_parameters_sv_2026.xml`; **74/74 grün**)
|
||||
- `addons/l10n_at_gemeinde_payroll/` — GemBG (AP1+AP2)
|
||||
@@ -1,7 +1,7 @@
|
||||
# Part of the odoo-at-payroll project. License: LGPL-3.
|
||||
{
|
||||
'name': 'Österreich - Personalverrechnung Kern (AT Payroll Core)',
|
||||
'version': '19.0.2.0.0',
|
||||
'version': '19.0.3.0.0',
|
||||
'author': 'ixsol',
|
||||
'website': 'https://gem360.at',
|
||||
'category': 'Human Resources/Payroll',
|
||||
@@ -19,10 +19,21 @@ Produkt (``l10n_at_hr_payroll_private``). Grundlagen: ``personalverrechnung/``
|
||||
generiert und gegen den offiziellen SV-Werte-Report gespiegelt):
|
||||
KV/PV/UV/AV/AK/WF/BV/IESG-Beitragssätze, Geringfügigkeitsgrenze,
|
||||
Höchstbeitragsgrundlagen (monatlich/SZ), AV-Staffel § 2a AMPFG;
|
||||
- **Lohnsteuer (AP3, GP3)**: ``models/lohnsteuer.py`` (§ 66 kumulativ mit
|
||||
Rollung, § 67 Sechstel/Fixsätze, § 68-Steuerfreiheiten),
|
||||
``rule_parameters_lst_2026.xml``;
|
||||
- **SV/DB (AP4, GP4)**: ``models/sozialversicherung.py`` — DG-Beiträge
|
||||
(SVDG, ÖGK 2026: 20,98 %), Geringfügigkeit (§ 5 Abs 2 iVm § 810 Abs 3
|
||||
ASVG) + § 53a-UV, beitragsfreie Bezüge § 49 Abs 3 mit Jahres-
|
||||
Kumulativen, altersabhängige Satzausschaltungen (AlVG § 1 Abs 2 lit e,
|
||||
ASVG § 51 Abs 6/7, IESG § 12), WF-Satzvektor Bundesland × Jahr
|
||||
(Wien 1,5 % ab 2026), ALV-DN-Staffel § 2a AMPFG, Beitragsmonats-
|
||||
Allokation (Anspruchsprinzip), DAG-Bewertung § 1 DAG —
|
||||
``rule_parameters_sv_2026.xml``;
|
||||
- deklarative TASY-Mapping-Tabelle und Import-Wizard (Preview,
|
||||
Sprungwarnung > 10 %, explizite Bestätigung, versionierte Werte);
|
||||
- folgen nach Freigabe der Bgld.-APs: Lohnsteuer (§ 33/§ 68 EStG, AP3),
|
||||
Meldewesen (L16/FinanzOnline, eSV/ELDA, AP5), Belege (AP6).
|
||||
- folgen nach Freigabe der Bgld.-APs: Meldewesen (L16/FinanzOnline,
|
||||
eSV/ELDA, AP5), Belege (AP6).
|
||||
|
||||
Kein VRV-Bezug: die Gemeinde-Buchhaltung (Anlage 3b, Ansatz/MVAG) läuft
|
||||
über die Brücke ``l10n_at_gemeinde_payroll_vrv`` im gem360-Repo (AP7).
|
||||
@@ -32,6 +43,7 @@ Kein VRV-Bezug: die Gemeinde-Buchhaltung (Anlage 3b, Ansatz/MVAG) läuft
|
||||
'security/ir.model.access.csv',
|
||||
'data/rule_parameters_2026.xml',
|
||||
'data/rule_parameters_lst_2026.xml',
|
||||
'data/rule_parameters_sv_2026.xml',
|
||||
'data/tasy_mapping.xml',
|
||||
'views/tasy_views.xml',
|
||||
],
|
||||
|
||||
@@ -65,15 +65,31 @@
|
||||
<field name="date_from">2024-01-01</field>
|
||||
<field name="parameter_value">2.95</field>
|
||||
</record>
|
||||
<!-- ALV-Staffel § 2a Abs 1 Z 1-3 AMPFG: mindert NUR den DN-Anteil
|
||||
(ÖGK-Tarifsystem Abschläge „Mind. AV auf 0/1/2 %" = -2,95/-1,95/
|
||||
-0,95); Grenzen nicht zu aliquotieren; gilt auch für SZ-Beiträge
|
||||
(lb-son-03). Werte 2025: 2.074/2.262/2.451 € (lb-son-03);
|
||||
2026: 2.225/2.427/2.630 € (Beitragsrechtliche Werte 2026, Fn. 3);
|
||||
§ 2a mit 31.12.2026 aufgehoben (BGBl I 62/2026, KB A6). -->
|
||||
<record id="hr_rule_parameter_at_sv_av_staffel_ampfg" model="hr.rule.parameter">
|
||||
<field name="name">SV AV-Beitragsstaffel bei geringem Einkommen (§ 2a AMPFG)</field>
|
||||
<field name="name">SV ALV-DN-Staffel bei geringem Einkommen (§ 2a AMPFG)</field>
|
||||
<field name="code">at_sv_av_staffel_ampfg</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv_av_staffel_2025" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_av_staffel_ampfg"/>
|
||||
<field name="date_from">2025-01-01</field>
|
||||
<field name="parameter_value">{'tiers': [(0.0, 2074.00, 0.0), (2074.00, 2262.00, 1.0), (2262.00, 2451.00, 2.0)], 'dn_voll': 2.95}</field>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv_av_staffel_ampfg" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_av_staffel_ampfg"/>
|
||||
<field name="date_from">2026-07-01</field>
|
||||
<field name="parameter_value">{'tiers': [(0.0, 2225.00, 0.0), (2225.00, 2427.00, 1.0), (2427.00, 2630.00, 2.0)], 'av_total': 5.9}</field>
|
||||
<field name="date_from">2026-01-01</field>
|
||||
<field name="parameter_value">{'tiers': [(0.0, 2225.00, 0.0), (2225.00, 2427.00, 1.0), (2427.00, 2630.00, 2.0)], 'dn_voll': 2.95}</field>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv_av_staffel_2027" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_av_staffel_ampfg"/>
|
||||
<field name="date_from">2027-01-01</field>
|
||||
<field name="parameter_value">{'tiers': [], 'dn_voll': 2.95}</field>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_at_sv_bv_dg" model="hr.rule.parameter">
|
||||
<field name="name">Betriebliche Vorsorge Dienstgeberanteil</field>
|
||||
@@ -110,6 +126,12 @@
|
||||
<field name="code">at_sv_hbg_monatlich</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<!-- 2025: 30 × 215 €/Kalendertag (§ 108 Abs 3 VO-Reihe, KB A8) -->
|
||||
<record id="hr_rule_parameter_value_at_sv_hbg_2025" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_hbg_monatlich"/>
|
||||
<field name="date_from">2025-01-01</field>
|
||||
<field name="parameter_value">6450.0</field>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv_hbg_monatlich" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_hbg_monatlich"/>
|
||||
<field name="date_from">2026-01-01</field>
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- ============================================================ -->
|
||||
<!-- GP4 SV/DB-Parameter (AP4). Quellen (verbindlich, 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 -->
|
||||
<!-- ============================================================ -->
|
||||
|
||||
<!-- Wohnbauförderungsbeitrag: Satzvektor Bundesland × Jahr. -->
|
||||
<!-- Bundesstandard 0,5/0,5; Wien ab 1.1.2026 gesamt 1,5 % = -->
|
||||
<!-- 0,75 DN + 0,75 DG (Wiener WF-Beitragstarif 2018 § 1; -->
|
||||
<!-- Beitragsrechtliche Werte 2026, Fn. 5; A2). Ohne 'wien'-Eintrag -->
|
||||
<!-- greift 'default' (Wien-Zuschlag erst ab 1.1.2026). -->
|
||||
<record id="hr_rule_parameter_at_sv_wf_vektor" model="hr.rule.parameter">
|
||||
<field name="name">WF-Beitrag Satzvektor (Bundesland × Jahr)</field>
|
||||
<field name="code">at_sv_wf_vektor</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv_wf_vektor_2019" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_wf_vektor"/>
|
||||
<field name="date_from">2019-01-01</field>
|
||||
<field name="parameter_value">{'default': {'dn': 0.5, 'dg': 0.5}}</field>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv_wf_vektor_2026" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_wf_vektor"/>
|
||||
<field name="date_from">2026-01-01</field>
|
||||
<field name="parameter_value">{'wien': {'dn': 0.75, 'dg': 0.75}, 'default': {'dn': 0.5, 'dg': 0.5}}</field>
|
||||
</record>
|
||||
|
||||
<!-- Beitragsfreie Bezüge § 49 Abs 3 ASVG (Stand 2026-07, -->
|
||||
<!-- lb-sva-03/lb-sva-04): Mahlzeiten-Gutscheine 8 €/Arbeitstag -->
|
||||
<!-- (Z 12; Lebensmittel-Gutscheine 2 €/AT), Mitarbeiterrabatte -->
|
||||
<!-- bis 20 % je Fall ODER 1.000 €/Jahr (Z 29; R1: Jahrespool), -->
|
||||
<!-- Betriebsveranstaltungen 365 €/Jahr und Jubiläums-Sach- -->
|
||||
<!-- zuwendungen 186 €/Jahr (Z 17), Zukunftssicherung 300 €/Jahr -->
|
||||
<!-- (Z 18 lit a), Kinderbetreuungszuschuss 2.000 €/Kind/Jahr -->
|
||||
<!-- (Z 11 lit d; R1: Pool je DN), Homeoffice-Pauschale 3 €/Tag -->
|
||||
<!-- max 100 Tage (Z 31 iVm § 26 Z 9 EStG). Überschreiten = -->
|
||||
<!-- beitragspflichtiger Sachbezug (Umwidmung). -->
|
||||
<record id="hr_rule_parameter_at_sv49_grenzen" model="hr.rule.parameter">
|
||||
<field name="name">Beitragsfreie Bezüge § 49 Abs 3 ASVG (Grenzen)</field>
|
||||
<field name="code">at_sv49_grenzen</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv49_grenzen" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv49_grenzen"/>
|
||||
<field name="date_from">2026-01-01</field>
|
||||
<field name="parameter_value">{'mahlzeit_tag': 8.0, 'lebensmittel_tag': 2.0, 'rabatt_jahr': 1000.0, 'betriebsveranstaltung_jahr': 365.0, 'jubilaeum_jahr': 186.0, 'zukunftssicherung_jahr': 300.0, 'kinderbetreuung_jahr': 2000.0, 'homeoffice_tag': 3.0, 'homeoffice_tage': 100}</field>
|
||||
</record>
|
||||
|
||||
<!-- § 53a ASVG geringfügig Beschäftigte: DG-UV 1,1 % der -->
|
||||
<!-- allgemeinen Beitragsgrundlage (Abs 1) als Monatspauschale; -->
|
||||
<!-- Selbstversicherung KV+PV 14,12 % der aBG (Abs 3) = -->
|
||||
<!-- 83,49 €/Monat 2026 (§ 77 Abs 2a ASVG; TASY KVPVBTG19A: -->
|
||||
<!-- 2024: 73,20 · 2025: 77,81 · 2026: 83,49). Direct-Zahlung der -->
|
||||
<!-- versicherten Person an den Träger — KEIN Lohnabzug (GP4). -->
|
||||
<!-- beitrag_uv abgeleitet: aBG 2026 = 83,49 ÷ 0,1412 = 591,29 → -->
|
||||
<!-- 1,1 % = 6,50 €/Monat ⚠ direkter Beleg folgt (GP8-Parameter- -->
|
||||
<!-- pflege). GFG 2026 = 551,10 € (Aufwertung ausgesetzt, -->
|
||||
<!-- § 810 Abs 3 ASVG — A7-Rest gelöst). -->
|
||||
<record id="hr_rule_parameter_at_sv_geringfuegig" model="hr.rule.parameter">
|
||||
<field name="name">Geringfügig Beschäftigte — § 53a ASVG (UV/Selbstversicherung)</field>
|
||||
<field name="code">at_sv_geringfuegig</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv_geringfuegig_2025" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_geringfuegig"/>
|
||||
<field name="date_from">2025-01-01</field>
|
||||
<field name="parameter_value">{'beitrag_uv': 6.06, 'beitrag_selbstversicherung': 77.81}</field>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_sv_geringfuegig_2026" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_sv_geringfuegig"/>
|
||||
<field name="date_from">2026-01-01</field>
|
||||
<field name="parameter_value">{'beitrag_uv': 6.50, 'beitrag_selbstversicherung': 83.49}</field>
|
||||
</record>
|
||||
|
||||
<!-- PV-Halbierung in der Bonusphase (§ 51 Abs 7 ASVG): normativer -->
|
||||
<!-- Faktor 0,5 für DG- und DN-Anteil („A 15"; Pensionskonto- -->
|
||||
<!-- Gutschrift bleibt ungekürzt — mBGM-Auswertung GP7/GP8). -->
|
||||
<record id="hr_rule_parameter_at_pv_bonus_faktor" model="hr.rule.parameter">
|
||||
<field name="name">PV-Faktor Bonusphase (§ 51 Abs 7 ASVG)</field>
|
||||
<field name="code">at_pv_bonus_faktor</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_pv_bonus_faktor" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_pv_bonus_faktor"/>
|
||||
<field name="date_from">2019-01-01</field>
|
||||
<field name="parameter_value">0.5</field>
|
||||
</record>
|
||||
|
||||
<!-- FLAF-Dienstgeberbeitrag § 41 Abs 5 FLAG: 3,7 % ab 2025, -->
|
||||
<!-- 2,7 % ab 2028 (RQ Abschn. 6 ✅; lb-lnk-02: Satzhistorie -->
|
||||
<!-- 2016: 4,5 · 2017: 4,1 · 2018: 3,9 · ab 2025 dauerhaft 3,7). -->
|
||||
<record id="hr_rule_parameter_at_flaf_db" model="hr.rule.parameter">
|
||||
<field name="name">FLAF-Dienstgeberbeitrag (§ 41 Abs 5 FLAG)</field>
|
||||
<field name="code">at_flaf_db</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_flaf_db_2018" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_flaf_db"/>
|
||||
<field name="date_from">2018-01-01</field>
|
||||
<field name="parameter_value">3.9</field>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_flaf_db" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_flaf_db"/>
|
||||
<field name="date_from">2025-01-01</field>
|
||||
<field name="parameter_value">3.7</field>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_flaf_db_2028" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_flaf_db"/>
|
||||
<field name="date_from">2028-01-01</field>
|
||||
<field name="parameter_value">2.7</field>
|
||||
</record>
|
||||
|
||||
<!-- Kommunalsteuer § 9 KommStG 1993: 3 % (RQ Abschn. 7 ✅). -->
|
||||
<record id="hr_rule_parameter_at_kommst_satz" model="hr.rule.parameter">
|
||||
<field name="name">Kommunalsteuer (§ 9 KommStG 1993)</field>
|
||||
<field name="code">at_kommst_satz</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_kommst_satz" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_kommst_satz"/>
|
||||
<field name="date_from">2025-01-01</field>
|
||||
<field name="parameter_value">3.0</field>
|
||||
</record>
|
||||
|
||||
<!-- LNK-Freibetragsstaffel (§ 41 Abs 4 FLAG wortgleich § 9 -->
|
||||
<!-- KommStG; ident auch für den DZ, lb-lnk-07): monatliche BG -->
|
||||
<!-- ≤ 1.095 € → keine Abgabe · 1.095–1.460 € → Freibetrag 1.095 € -->
|
||||
<!-- · > 1.460 € → volle BG. -->
|
||||
<record id="hr_rule_parameter_at_lnk_freibetrag" model="hr.rule.parameter">
|
||||
<field name="name">LNK-Freibetrag (FLAF/KommSt/DZ; § 41 Abs 4 FLAG)</field>
|
||||
<field name="code">at_lnk_freibetrag</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_lnk_freibetrag" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_lnk_freibetrag"/>
|
||||
<field name="date_from">2025-01-01</field>
|
||||
<field name="parameter_value">{'freibetrag': 1095.0, 'grenze': 1460.0}</field>
|
||||
</record>
|
||||
|
||||
<!-- Zuschlag zum Dienstgeberbeitrag (§§ 122/126 WKG): Landeskammer- -->
|
||||
<!-- sätze 2026 INKL. Bundeskammeranteil 0,12 % (lb-lnk-07, Stand -->
|
||||
<!-- 2026-08; ⚠ WKO/WKG-Volltext-Verifikation offen — 8.11). BG -->
|
||||
<!-- identisch FLAF-DB inkl. §-41-Abs-4-Ausnahmen. -->
|
||||
<record id="hr_rule_parameter_at_dz_vektor" model="hr.rule.parameter">
|
||||
<field name="name">Zuschlag zum Dienstgeberbeitrag (WKG; je Bundesland)</field>
|
||||
<field name="code">at_dz_vektor</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_dz_vektor" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_dz_vektor"/>
|
||||
<field name="date_from">2026-01-01</field>
|
||||
<field name="parameter_value">{'laender': {'burgenland': 0.40, 'kaernten': 0.37, 'niederoesterreich': 0.33, 'oberoesterreich': 0.31, 'salzburg': 0.35, 'steiermark': 0.34, 'tirol': 0.39, 'vorarlberg': 0.33, 'wien': 0.36}}</field>
|
||||
</record>
|
||||
|
||||
<!-- Dienstgeberabgabe geringfügig Beschäftigter (§ 1 DAG; ÖGK- -->
|
||||
<!-- Tarifsystem „Dienstgeberabgabe gem. § 1 DAG"): 19,4 % der -->
|
||||
<!-- Lohnsumme (Beitragsgrundlagen ohne SZ) aller Geringfügigen je -->
|
||||
<!-- Kalendermonat, wenn Lohnsumme > 1,5 × GFG (2026: 826,65 € — -->
|
||||
<!-- TASY MINGRDAGP1, offene Gültigkeit ab 2025-01-01) und -->
|
||||
<!-- mindestens 2 Geringfügige. UV läuft separat über § 53a Abs 1 -->
|
||||
<!-- („mit UV 20,5 %"); ab 60. LJ entfällt der UV-Anteil. -->
|
||||
<!-- Ausweis/Veranlagung: GP8. -->
|
||||
<record id="hr_rule_parameter_at_dag" model="hr.rule.parameter">
|
||||
<field name="name">Dienstgeberabgabe geringfügig Beschäftigter (§ 1 DAG)</field>
|
||||
<field name="code">at_dag</field>
|
||||
<field name="country_id" ref="base.at"/>
|
||||
</record>
|
||||
<record id="hr_rule_parameter_value_at_dag" model="hr.rule.parameter.value">
|
||||
<field name="rule_parameter_id" ref="hr_rule_parameter_at_dag"/>
|
||||
<field name="date_from">2025-01-01</field>
|
||||
<field name="parameter_value">{'satz': 19.4, 'schwelle_faktor': 1.5}</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,3 +1,5 @@
|
||||
# Part of the odoo-at-payroll project. License: LGPL-3.
|
||||
from . import tasy
|
||||
from . import lohnsteuer
|
||||
from . import lohnsteuer
|
||||
from . import sozialversicherung
|
||||
from . import sozialversicherung
|
||||
@@ -198,29 +198,15 @@ class HrPayslip(models.Model):
|
||||
return ergebnis
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# DN-SV (Bemessungsbestandteil § 62; Werte at_sv_* — GP4 baut
|
||||
# DG-Seite/Geringfügigkeit/beitragsfreie Kumulative darauf)
|
||||
# DN-SV (Bemessungsbestandteil § 62) — Basis/Sätze/Geringfügigkeit/
|
||||
# §-49-Kumulative/DG-Seite: models/sozialversicherung.py (GP4)
|
||||
# ------------------------------------------------------------------
|
||||
def _l10n_at_svdn_basis_laufen(self, result_rules=None):
|
||||
"""SV-Beitragsgrundlage laufend (HBG-capped, at_sv_*)."""
|
||||
self.ensure_one()
|
||||
hbg = float(self._l10n_at_param('at_sv_hbg_monatlich'))
|
||||
return min(max(self._l10n_at_brutto('laufend', result_rules), 0.0), hbg)
|
||||
|
||||
def _l10n_at_svdn(self, komponente, result_rules=None):
|
||||
"""DN-SV-Komponente auf laufender Basis: kv/pv/av/ak/wf —
|
||||
AK § 61 AKG und WF § 62 Z 5 nur laufend (nicht auf §-67-Bezüge);
|
||||
WF-Wien über Company-Flag (DN 0,75 statt 0,50)."""
|
||||
Wien-WF über Satzvektor (l10n_at_wf_wien/Bundesland, GP4)."""
|
||||
self.ensure_one()
|
||||
basis = self._l10n_at_svdn_basis_laufen(result_rules)
|
||||
codes = {'kv': 'at_sv_kv_dn', 'pv': 'at_sv_pv_dn',
|
||||
'av': 'at_sv_av_dn', 'ak': 'at_sv_ak_dn'}
|
||||
if komponente == 'wf':
|
||||
satz = 0.75 if self.company_id.l10n_at_wf_wien \
|
||||
else float(self._l10n_at_param('at_sv_wf_dn'))
|
||||
else:
|
||||
satz = float(self._l10n_at_param(codes[komponente]))
|
||||
return basis * satz / 100.0
|
||||
return self._l10n_at_sv_beitrag('dn', komponente, result_rules)
|
||||
|
||||
def _l10n_at_svdn_gesamt(self, result_rules=None):
|
||||
self.ensure_one()
|
||||
@@ -240,11 +226,15 @@ class HrPayslip(models.Model):
|
||||
|
||||
def _l10n_at_svdn_sz(self, result_rules=None):
|
||||
"""SV-DN auf sonstigen Bezügen (§ 67 Abs 12 — vor Fixsätzen
|
||||
abzuziehen): KV/PV/AV, ohne AK/WF (§ 62 Z 3/Z 5)."""
|
||||
abzuziehen): KV/PV/AV, ohne AK/WF (§ 62 Z 3/Z 5); Satzausschal-
|
||||
tungen/Steffel über _l10n_at_sv_satz (GP4)."""
|
||||
self.ensure_one()
|
||||
if self._l10n_at_geringfuegig(result_rules):
|
||||
return 0.0
|
||||
basis = self._l10n_at_svdn_basis_sz(result_rules)
|
||||
satz = sum(float(self._l10n_at_param(code)) for code in
|
||||
('at_sv_kv_dn', 'at_sv_pv_dn', 'at_sv_av_dn'))
|
||||
satz = sum(self._l10n_at_sv_satz(
|
||||
'dn', k, staffel_basis=self._l10n_at_sv_basis_roh(result_rules))
|
||||
for k in ('kv', 'pv', 'av'))
|
||||
return basis * satz / 100.0
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
# Part of the odoo-at-payroll project. License: LGPL-3.
|
||||
"""Sozialversicherungs-Kern (GP4/AP4): DG-Beiträge (SVDG), Geringfügigkeit
|
||||
(§ 5 Abs 2 ASVG iVm § 810 Abs 3 — 2026-Aufwertung ausgestellt), §-53a-
|
||||
UV der Geringfügigen, beitragsfreie Bezüge nach § 49 Abs 3 ASVG mit
|
||||
Jahres-Kumulativen, altersabhängige Satzausschaltungen (§ 1 Abs 2 lit e
|
||||
AlVG, § 51 Abs 6/7 ASVG, § 12 Abs 2 IESG), WF-Satzvektor Bundesland ×
|
||||
Jahr (Wien 1,5 % ab 1.1.2026), ALV-DN-Staffel (§ 2a AMPFG) und
|
||||
Beitragsmonats-Allokation (Anspruchsprinzip, historisch versionierte
|
||||
Sätze/HBG je Beitragsmonat).
|
||||
|
||||
Verifizierte Grundlagen (2026-09-11, s. RECHTSQUELLEN-Privat Abschn. 4
|
||||
und docs/rechenfaelle/sozialversicherung.md):
|
||||
- ÖGK-Beitragstarifsystem „Normalbetriebe Allgemeiner Teil", gültig ab
|
||||
01.07.2026 (DN 18,07 % · DG 20,98 % · Wien DN 18,32/DG 21,23 %);
|
||||
- TASY-LSWH-Export 2026-03-24 (GFG 551,10 · DAG-Grenze 826,65 ·
|
||||
§-19a-Pauschalbeitrag 83,49 €/Monat — Primärquellen-Entscheidung);
|
||||
- „Beitragsrechtliche Werte 2026" (sozialversicherung.at): GFG-Aufwertung
|
||||
2026 ausgesetzt (§ 810 Abs 3 ASVG); AV-Staffel bis 2.225/2.427/2.630 €
|
||||
0/1/2 % DN; WF Wien 0,75/0,75 ab 1.1.2026;
|
||||
- ASVG §§ 51 Abs 6 (UV-Entfall 60. LJ/Lehrlinge), 51 Abs 7 (PV in der
|
||||
Bonusphase hälftig, DG und DN), 53a Abs 1/3/5 (UV 1,1 % der allgemeinen
|
||||
Beitragsgrundlage; Pauschalbeitrag 14,12 %, auch von SZ);
|
||||
IESG § 12 Abs 1 Z 4 iVm Abs 2 (Entfall ab Folgemonat nach 63);
|
||||
AlVG § 1 Abs 2 lit e (AV-Entfall, ab 2027 inkl. Korridorpension).
|
||||
|
||||
Laufzeit-Datenfluss wie GP3: Regeln reichen Zwischensummen über
|
||||
``result_rules`` an die Compute-Methoden; abgeschlossene Läufe werden
|
||||
über line_ids gelesen. Der Beitragsmonat wird je Regel geführt
|
||||
(``l10n_at_beitragsmonat``) und auf die Lohnkontolinie durchgereicht.
|
||||
"""
|
||||
from datetime import date, timedelta
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.safe_eval import safe_eval
|
||||
|
||||
|
||||
class HrSalaryRule(models.Model):
|
||||
_inherit = 'hr.salary.rule'
|
||||
|
||||
l10n_at_sv49_frei = fields.Selection(
|
||||
[('keine', 'Keine §-49-Abs-3-Befreiung'),
|
||||
('mahlzeit', 'Mahlzeiten-Gutschein (§ 49 Abs 3 Z 12; 8 €/AT)'),
|
||||
('rabatt', 'Mitarbeiterrabatt (§ 49 Abs 3 Z 29; 1.000 €/J)'),
|
||||
('betriebsveranstaltung', 'Betriebsveranstaltung (Z 17; 365 €/J)'),
|
||||
('jubilaeum', 'Jubiläums-Sachzuwendung (Z 17; 186 €/J)'),
|
||||
('zukunftssicherung', 'Zukunftssicherung (Z 18 lit a; 300 €/J)'),
|
||||
('kinderbetreuung', 'Kinderbetreuungszuschuss (Z 11 lit d; 2.000 €/Kind/J)'),
|
||||
('homeoffice', 'Homeoffice-Pauschale (Z 31; 3 €/Tag, max 100 Tage)')],
|
||||
string='AT § 49 Abs 3 (beitragsfrei)',
|
||||
default='keine',
|
||||
help='Beitragsfreie Bezugsbestandteile: der beitragsfreie Anteil '
|
||||
'wird je Bezugsmonat von der SV-Beitragsgrundlage abgezogen; '
|
||||
'Grenzen als Jahres-Kumulative je Dienstnehmer '
|
||||
'(at_sv49_grenzen). Überschreiten = beitragspflichtiger '
|
||||
'Sachbezug (Umwidmung). Menge = Arbeitstage (Z 12/Z 31).')
|
||||
l10n_at_s67_abs = fields.Selection(
|
||||
[('keine', 'Keine §-67-Abs-3/6-Begünstigung'),
|
||||
('abs3', 'Abfertigung (§ 67 Abs 3 EStG)'),
|
||||
('abs6', 'Abfindung (§ 67 Abs 6 EStG)')],
|
||||
string='AT § 67 Abs 3/6',
|
||||
default='keine',
|
||||
help='Markiert Bezüge, die beim FLAF-Dienstgeberbeitrag (§ 41 '
|
||||
'Abs 4 FLAG), Zuschlag zum DG-Beitrag (WKG) und der '
|
||||
'Kommunalsteuer (§ 5 Abs 2 KommStG) aus der Bemessungsgrund'
|
||||
'lage ausgenommen sind.')
|
||||
l10n_at_beitragsmonat = fields.Date(
|
||||
string='AT Beitragsmonat (Anspruchsprinzip)',
|
||||
help='Monat, in dem der Anspruch auf diesen Bezug fällig wurde '
|
||||
'(§ 17 ASVG). Leer = Abrechnungsmonat. Für Nachzahlungs-/'
|
||||
'Korrekturlinien setzen: SV-Sätze, HBG und GFG werden '
|
||||
'historisch versioniert je Beitragsmonat aufgelöst '
|
||||
'(Lohnsteuer rollt kumulativ in den Zuflussmonat, GP3).')
|
||||
|
||||
|
||||
class HrPayslipLine(models.Model):
|
||||
_inherit = 'hr.payslip.line'
|
||||
|
||||
l10n_at_beitragsmonat = fields.Date(
|
||||
string='AT Beitragsmonat',
|
||||
compute='_compute_l10n_at_beitragsmonat',
|
||||
store=True,
|
||||
readonly=False,
|
||||
index=True,
|
||||
help='Beitragsmonat der Linie (Anspruchsprinzip); default '
|
||||
'Abrechnungsmonat, über die Regel übersteuerbar.')
|
||||
|
||||
@api.depends('salary_rule_id.l10n_at_beitragsmonat', 'date_from')
|
||||
def _compute_l10n_at_beitragsmonat(self):
|
||||
for line in self:
|
||||
line.l10n_at_beitragsmonat = (
|
||||
line.salary_rule_id.l10n_at_beitragsmonat or line.date_from)
|
||||
|
||||
|
||||
class HrVersion(models.Model):
|
||||
_inherit = 'hr.version'
|
||||
|
||||
l10n_at_lehrling = fields.Boolean(
|
||||
string='AT Lehrling',
|
||||
help='Keine AK-Umlage (§ 61 AKG) und kein UV-Beitrag (§ 51 Abs 6 '
|
||||
'ASVG — aus Mitteln der Unfallversicherung); GFG gilt nicht '
|
||||
'(§ 5 Abs 3 ASVG).')
|
||||
l10n_at_alv_entfall_ab = fields.Date(
|
||||
string='AT ALV-Entfall ab (§ 1 Abs 2 lit e AlVG)',
|
||||
help='AV-Beitrag DN+DG und IESG-Zuschlag entfallen ab diesem '
|
||||
'Beitragsmonat (63. Lebensjahr oder erfüllte Alterspensions-'
|
||||
'Anwartschaft; ab 1.1.2027 inkl. Korridorpension, '
|
||||
'NOR40280219; § 12 Abs 2 IESG). Stichtagsregel am Vertrag.')
|
||||
l10n_at_uv_entfall_ab = fields.Date(
|
||||
string='AT UV-Entfall ab (§ 51 Abs 6 ASVG)',
|
||||
help='Unfallversicherungsbeitrag entfällt ab diesem '
|
||||
'Beitragsmonat (Vollendung des 60. Lebensjahres); die '
|
||||
'Person bleibt unfallversichert.')
|
||||
l10n_at_pv_bonusphase_ab = fields.Date(
|
||||
string='AT PV-Bonusphase ab (§ 51 Abs 7 ASVG)',
|
||||
help='Pensionsversicherungsbeitrag je zur Hälfte reduziert für '
|
||||
'DG und DN (Bonusphase/Pensionsanspruch; ÖGK-Abschlag '
|
||||
'A 15; Pensionskonto-Gutschrift bleibt ungekürzt — Auswertung '
|
||||
'GP8).')
|
||||
l10n_at_lnkp_frei_ab = fields.Date(
|
||||
string='AT LNK-frei ab (§ 41 Abs 4 lit f FLAG)',
|
||||
help='Arbeitslöhne ab diesem Kalendermonat sind vom FLAF-'
|
||||
'Dienstgeberbeitrag und vom Zuschlag zum Dienstgeberbeitrag '
|
||||
'(WKG) ausgenommen (Folgemonat nach Vollendung des 60. '
|
||||
'Lebensjahres). Kommunalsteuer: keine Befreiung.')
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
l10n_at_bundesland = fields.Selection(
|
||||
[('burgenland', 'Burgenland'), ('kaernten', 'Kärnten'),
|
||||
('niederoesterreich', 'Niederösterreich'),
|
||||
('oberoesterreich', 'Oberösterreich'), ('salzburg', 'Salzburg'),
|
||||
('steiermark', 'Steiermark'), ('tirol', 'Tirol'),
|
||||
('vorarlberg', 'Vorarlberg'), ('wien', 'Wien')],
|
||||
string='AT Bundesland (Betriebsstätte)',
|
||||
help='Betriebsstätten-Bundesland für Bundesland-Satzvektoren '
|
||||
'(z. B. DZ-Landeskammeranteil; WF-Wien zusätzlich über das '
|
||||
'Company-Flag l10n_at_wf_wien steuerbar).')
|
||||
l10n_at_wk_mitglied = fields.Boolean(
|
||||
string='AT WKO-Mitgliedschaft (DZ-pflichtig)',
|
||||
help='Zuschlag zum Dienstgeberbeitrag (§§ 122/126 WKG) nur für '
|
||||
'Mitglieder der Wirtschaftskammerorganisation (§ 2 WKG).')
|
||||
|
||||
def _l10n_at_dag(self, monat_start):
|
||||
"""Dienstgeberabgabe geringfügig Beschäftigter (§ 1 DAG) für den
|
||||
Kalendermonat: 19,4 % der Lohnsumme (Beitragsgrundlagen ohne SZ)
|
||||
aller geringfügig Beschäftigten, wenn die Lohnsumme das 1,5-fache
|
||||
der monatlichen GFG überschreitet und mindestens zwei
|
||||
Geringfügige beschäftigt sind (lb-bes-06; TASY MINGRDAGP1 2026:
|
||||
826,65 €; Ausweis/Veranlagung GP8)."""
|
||||
monat_ende = (monat_start + timedelta(days=32)).replace(day=1) \
|
||||
- timedelta(days=1)
|
||||
slips = self.env['hr.payslip'].search([
|
||||
('company_id', '=', self.id),
|
||||
('date_from', '<=', monat_ende),
|
||||
('date_to', '>=', monat_start),
|
||||
('state', 'not in', ('draft', 'cancel')),
|
||||
('l10n_at_geringfuegig', '=', True),
|
||||
])
|
||||
lohnsumme = sum(
|
||||
slip._l10n_at_sv_basis_roh() for slip in slips)
|
||||
anzahl = len({s.employee_id.id for s in slips})
|
||||
params = self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_dag', monat_start, raise_if_not_found=False) or {}
|
||||
gfg = float(self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_sv_gfg_monatlich', monat_start,
|
||||
raise_if_not_found=False) or 0.0)
|
||||
schwelle = float(params.get('schwelle_faktor', 0.0)) * gfg
|
||||
abgabe = 0.0
|
||||
if anzahl >= 2 and lohnsumme > schwelle:
|
||||
abgabe = lohnsumme * float(params.get('satz', 0.0)) / 100.0
|
||||
return {'anzahl': anzahl, 'lohnsumme': lohnsumme,
|
||||
'schwelle': schwelle, 'abgabe': abgabe}
|
||||
|
||||
|
||||
class HrPayslip(models.Model):
|
||||
_inherit = 'hr.payslip'
|
||||
|
||||
l10n_at_geringfuegig = fields.Boolean(
|
||||
string='AT Geringfügig beschäftigt',
|
||||
compute='_compute_l10n_at_geringfuegig',
|
||||
store=True,
|
||||
help='Laufendes Entgelt (§-49-bereinigt, hochgerechnet bei '
|
||||
'untermonatiger Beschäftigung) überschreitet die GFG nicht '
|
||||
'(§ 5 Abs 2 ASVG). DAG-Monitoring-Grundlage (§ 1 DAG).')
|
||||
|
||||
@api.depends('line_ids', 'date_from', 'date_to', 'version_id')
|
||||
def _compute_l10n_at_geringfuegig(self):
|
||||
for slip in self:
|
||||
try:
|
||||
slip.l10n_at_geringfuegig = slip._l10n_at_geringfuegig()
|
||||
except Exception:
|
||||
# Alter Lauf ohne GFG-Parameterzeile: keine Bewertung.
|
||||
slip.l10n_at_geringfuegig = False
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Geringfügigkeit (§ 5 Abs 2 ASVG; SZ zählen nicht — lb-bes-06)
|
||||
# ------------------------------------------------------------------
|
||||
def _l10n_at_geringfuegig(self, result_rules=None):
|
||||
"""Hochgerechnetes laufendes Entgelt ≤ GFG (2026: 551,10 € —
|
||||
Aufwertung gem. § 810 Abs 3 ASVG ausgesetzt). Lehrlinge sind
|
||||
nie geringfügig (§ 5 Abs 3 ASVG). Verhältnisse kürzer als ein
|
||||
Naturalmonat: Gesamtentgelt direkt gegen die Monatsgrenze."""
|
||||
self.ensure_one()
|
||||
version = self.version_id
|
||||
if version.l10n_at_lehrling:
|
||||
return False
|
||||
roh = self._l10n_at_sv_basis_roh(result_rules)
|
||||
if roh <= 0.0:
|
||||
# Ohne laufenden Bezug keine Statusbewertung (z. B.
|
||||
# reiner SZ-Lauf): Normalbehandlung der SZ-Beiträge.
|
||||
return False
|
||||
if (version.contract_date_start and version.contract_date_end
|
||||
and (version.contract_date_end - version.contract_date_start)
|
||||
.days < 29):
|
||||
vergleich = roh
|
||||
else:
|
||||
tage = self._l10n_at_lohnsteuertage()
|
||||
vergleich = roh * 30.0 / max(tage, 1) if tage < 30 else roh
|
||||
gfg = float(self.env['hr.rule.parameter']
|
||||
._get_parameter_from_code(
|
||||
'at_sv_gfg_monatlich', self.date_to,
|
||||
raise_if_not_found=False) or 0.0)
|
||||
return vergleich <= gfg
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Beitragsfreie Bezüge § 49 Abs 3 ASVG (Jahres-Kumulative je DN)
|
||||
# ------------------------------------------------------------------
|
||||
def _l10n_at_sv49_ytd(self, kategorie, menge=False):
|
||||
"""Jahresverbrauch einer §-49-Kategorie aus früheren validierten
|
||||
Läufen (refundbewusst über _l10n_at_ytd_slaeufe)."""
|
||||
self.ensure_one()
|
||||
total = 0.0
|
||||
for slip in self._l10n_at_ytd_slaeufe():
|
||||
linien = slip.line_ids.filtered(
|
||||
lambda l: l.salary_rule_id.l10n_at_sv49_frei == kategorie)
|
||||
if menge:
|
||||
total += sum(linien.mapped('quantity'))
|
||||
else:
|
||||
total += sum(linien.mapped('total'))
|
||||
return total
|
||||
|
||||
def _l10n_at_sv49_freie_laufen(self, result_rules=None):
|
||||
"""Beitragsfreie Anteile laufender Bezüge dieses LZP: je Kategorie
|
||||
Tages-/Jahresgrenzen (at_sv49_grenzen) minus Jahresverbrauch;
|
||||
Überschreiten = beitragspflichtig (Umwidmung, § 49 Abs 3)."""
|
||||
self.ensure_one()
|
||||
grenzen = self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_sv49_grenzen', self.date_to, raise_if_not_found=False)
|
||||
if not grenzen:
|
||||
return 0.0
|
||||
frei_gesamt = 0.0
|
||||
for rule in self.struct_id.rule_ids:
|
||||
kategorie = rule.l10n_at_sv49_frei
|
||||
if (not kategorie or kategorie == 'keine'
|
||||
or rule.l10n_at_bemessung != 'laufend'):
|
||||
continue
|
||||
werte = None
|
||||
if result_rules is not None:
|
||||
if rule.code in result_rules:
|
||||
werte = result_rules[rule.code]
|
||||
else:
|
||||
linie = self.line_ids.filtered(lambda l: l.code == rule.code)
|
||||
if linie:
|
||||
werte = {'total': sum(linie.mapped('total')),
|
||||
'quantity': sum(linie.mapped('quantity'))}
|
||||
if not werte:
|
||||
continue
|
||||
total = werte['total']
|
||||
menge = werte.get('quantity', 0.0)
|
||||
if kategorie == 'mahlzeit':
|
||||
frei = min(
|
||||
total, float(grenzen.get('mahlzeit_tag')) * menge)
|
||||
elif kategorie == 'homeoffice':
|
||||
rest_tage = max(
|
||||
float(grenzen.get('homeoffice_tage'))
|
||||
- self._l10n_at_sv49_ytd('homeoffice', menge=True), 0.0)
|
||||
frei = min(
|
||||
total,
|
||||
float(grenzen.get('homeoffice_tag'))
|
||||
* min(menge, rest_tage))
|
||||
else:
|
||||
pool = {'rabatt': 'rabatt_jahr',
|
||||
'betriebsveranstaltung': 'betriebsveranstaltung_jahr',
|
||||
'jubilaeum': 'jubilaeum_jahr',
|
||||
'zukunftssicherung': 'zukunftssicherung_jahr',
|
||||
'kinderbetreuung': 'kinderbetreuung_jahr'}.get(
|
||||
kategorie)
|
||||
rest = max(
|
||||
float(grenzen.get(pool))
|
||||
- self._l10n_at_sv49_ytd(kategorie), 0.0)
|
||||
frei = min(total, rest)
|
||||
frei_gesamt += max(frei, 0.0)
|
||||
return frei_gesamt
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Laufende Beitragsgrundlage — je Beitragsmonat (Anspruchsprinzip)
|
||||
# ------------------------------------------------------------------
|
||||
def _l10n_at_sv_basis_roh(self, result_rules=None):
|
||||
"""Laufender Arbeitslohn minus beitragsfreie §-49-Anteile
|
||||
(vor HBG-Cap; Geringfügigkeits-/Staffel-Basis)."""
|
||||
self.ensure_one()
|
||||
roh = self._l10n_at_brutto('laufend', result_rules) \
|
||||
- self._l10n_at_sv49_freie_laufen(result_rules)
|
||||
return max(roh, 0.0)
|
||||
|
||||
def _l10n_at_sv_basis_laufen_monate(self, result_rules=None):
|
||||
"""[(Beitragsmonat, HBG-gecappte Basis), …]: laufender Arbeitslohn
|
||||
(§-49-bereinigt), gruppiert nach Regel-Beitragsmonat; HBG je
|
||||
Beitragsmonat historisch aufgelöst (at_sv_hbg_monatlich)."""
|
||||
self.ensure_one()
|
||||
gruppen = {}
|
||||
for rule in self.struct_id.rule_ids:
|
||||
if rule.l10n_at_bemessung != 'laufend':
|
||||
continue
|
||||
werte = None
|
||||
if result_rules is not None:
|
||||
if rule.code in result_rules:
|
||||
werte = result_rules[rule.code]
|
||||
else:
|
||||
linie = self.line_ids.filtered(lambda l: l.code == rule.code)
|
||||
if linie:
|
||||
werte = {'total': sum(linie.mapped('total'))}
|
||||
if not werte:
|
||||
continue
|
||||
monat = (rule.l10n_at_beitragsmonat or self.date_from) \
|
||||
.replace(day=1)
|
||||
gruppen[monat] = gruppen.get(monat, 0.0) + werte['total']
|
||||
standard = self.date_from.replace(day=1)
|
||||
if standard in gruppen:
|
||||
gruppen[standard] -= self._l10n_at_sv49_freie_laufen(
|
||||
result_rules)
|
||||
ergebnis = []
|
||||
for monat, basis in sorted(gruppen.items()):
|
||||
hbg = float(self._l10n_at_param('at_sv_hbg_monatlich', monat))
|
||||
ergebnis.append((monat, min(max(basis, 0.0), hbg)))
|
||||
return ergebnis
|
||||
|
||||
def _l10n_at_svdn_basis_laufen(self, result_rules=None):
|
||||
"""SV-Beitragsgrundlage laufend: Summe der je Beitragsmonat
|
||||
HBG-gecappten, §-49-bereinigten Basen (at_sv_*)."""
|
||||
self.ensure_one()
|
||||
return sum(basis for _monat, basis
|
||||
in self._l10n_at_sv_basis_laufen_monate(result_rules))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Effektive Beitragssätze (Alter/Stichtäge, Wien-WF, ALV-DN-Staffel)
|
||||
# ------------------------------------------------------------------
|
||||
def _l10n_at_sv_satz(self, seite, komponente, monat=None,
|
||||
staffel_basis=None):
|
||||
"""Effektiver Satz (vH) je Seite ('dn'/'dg') und Komponente
|
||||
(kv/pv/av/uv/ak/wf/iesg) zum Beitragsmonat, unter Berücksich-
|
||||
tigung der Stichtags-Regeln am Vertrag und der ALV-DN-Staffel
|
||||
(§ 2a AMPFG: reduziert nur den DN-Anteil; Grenzen nicht zu
|
||||
aliquotieren; gilt auch für SZ-Beiträge)."""
|
||||
self.ensure_one()
|
||||
version = self.version_id
|
||||
monat = monat or self.date_from
|
||||
if komponente == 'wf':
|
||||
vektor = self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_sv_wf_vektor', monat, raise_if_not_found=False)
|
||||
satz = None
|
||||
if vektor:
|
||||
wien = (self.company_id.l10n_at_wf_wien
|
||||
or self.company_id.l10n_at_bundesland == 'wien')
|
||||
eintrag = vektor.get('wien' if wien else 'default') \
|
||||
or vektor.get('default')
|
||||
if eintrag:
|
||||
satz = float(eintrag.get(seite, 0.0))
|
||||
if satz is None:
|
||||
satz = float(self.env['hr.rule.parameter']
|
||||
._get_parameter_from_code(
|
||||
'at_sv_wf_%s' % seite, monat,
|
||||
raise_if_not_found=False) or 0.0)
|
||||
return satz
|
||||
satz = float(self._l10n_at_param(
|
||||
'at_sv_%s_%s' % (komponente, seite), monat))
|
||||
entfall_alv = (version.l10n_at_alv_entfall_ab
|
||||
and monat >= version.l10n_at_alv_entfall_ab)
|
||||
if komponente in ('av', 'iesg') and entfall_alv:
|
||||
# AV DN+DG entfallen (AlVG § 1 Abs 2 lit e) — der IESG-
|
||||
# Zuschlag folgt dem AV-Beitrag (§ 12 Abs 1 Z 4 iVm
|
||||
# § 12 Abs 2 IESG).
|
||||
return 0.0
|
||||
if komponente == 'uv':
|
||||
if version.l10n_at_lehrling \
|
||||
or (version.l10n_at_uv_entfall_ab
|
||||
and monat >= version.l10n_at_uv_entfall_ab):
|
||||
return 0.0
|
||||
if komponente == 'ak' and version.l10n_at_lehrling:
|
||||
return 0.0
|
||||
if komponente == 'iesg' and version.l10n_at_lehrling:
|
||||
# § 12 Abs 2 IESG: für Lehrlinge gesamte Lehrzeit kein Zuschlag
|
||||
return 0.0
|
||||
if komponente == 'pv' and (
|
||||
version.l10n_at_pv_bonusphase_ab
|
||||
and monat >= version.l10n_at_pv_bonusphase_ab):
|
||||
faktor = float(self.env['hr.rule.parameter']
|
||||
._get_parameter_from_code(
|
||||
'at_pv_bonus_faktor', monat,
|
||||
raise_if_not_found=False) or 0.5)
|
||||
satz *= faktor
|
||||
if komponente == 'av' and seite == 'dn':
|
||||
staffel = self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_sv_av_staffel_ampfg', monat, raise_if_not_found=False)
|
||||
if staffel and staffel.get('tiers'):
|
||||
basis = staffel_basis if staffel_basis is not None \
|
||||
else self._l10n_at_sv_basis_roh()
|
||||
if basis > 0:
|
||||
for _von, bis, dn_satz in staffel['tiers']:
|
||||
if basis <= float(bis):
|
||||
return float(dn_satz)
|
||||
# über der obersten Stufe: voller DN-Satz
|
||||
return float(staffel.get('dn_voll', satz))
|
||||
return satz
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Beiträge laufend (DN- wie DG-seitig; geringfügig = 0)
|
||||
# ------------------------------------------------------------------
|
||||
def _l10n_at_sv_beitrag(self, seite, komponente, result_rules=None):
|
||||
"""Beitragssumme je Beitragsmonat: Basis × historischen Satz;
|
||||
geringfügige Beschäftigung → 0 (stattdessen §-53a-UV, s. u.)."""
|
||||
self.ensure_one()
|
||||
if self._l10n_at_geringfuegig(result_rules):
|
||||
return 0.0
|
||||
total = 0.0
|
||||
for monat, basis in self._l10n_at_sv_basis_laufen_monate(
|
||||
result_rules):
|
||||
satz = self._l10n_at_sv_satz(seite, komponente, monat, basis)
|
||||
total += basis * satz / 100.0
|
||||
return total
|
||||
|
||||
def _l10n_at_svdn(self, komponente, result_rules=None):
|
||||
"""DN-SV-Komponente laufend: kv/pv/av/ak/wf — AK (§ 61 AKG) und
|
||||
WF nur laufend, HBGL-Cap; Wien über WF-Satzvektor."""
|
||||
self.ensure_one()
|
||||
return self._l10n_at_sv_beitrag('dn', komponente, result_rules)
|
||||
|
||||
def _l10n_at_svdg(self, komponente, result_rules=None):
|
||||
"""DG-SV-Komponente laufend: kv/pv/av/uv/wf/iesg (AK = 0);
|
||||
ÖGK-Tarif „Normalbetriebe" 2026: DG-Gesamt 20,98 % (Wien 21,23)."""
|
||||
self.ensure_one()
|
||||
return self._l10n_at_sv_beitrag('dg', komponente, result_rules)
|
||||
|
||||
def _l10n_at_svdg_gesamt(self, result_rules=None):
|
||||
self.ensure_one()
|
||||
return sum(self._l10n_at_svdg(k, result_rules)
|
||||
for k in ('kv', 'pv', 'av', 'uv', 'wf', 'iesg'))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Beiträge auf sonstigen Bezügen (§ 54 ASVG; 60faches HBG je Jahr)
|
||||
# ------------------------------------------------------------------
|
||||
def _l10n_at_svdg_sz(self, komponente, result_rules=None):
|
||||
"""DG-Beitrag auf sonstigen Bezügen: KV/PV/AV/UV und IESG-Zuschlag
|
||||
(folgt dem AV-Beitrag) — ohne AK/WF (§ 62 Z 3/Z 5; lb-son-03:
|
||||
DN 17,07 %; DG 20,48 % inkl. UV 1,10 + IESG 0,10)."""
|
||||
self.ensure_one()
|
||||
if self._l10n_at_geringfuegig(result_rules):
|
||||
return 0.0
|
||||
basis = self._l10n_at_svdn_basis_sz(result_rules)
|
||||
satz = self._l10n_at_sv_satz(
|
||||
'dg', komponente, staffel_basis=self._l10n_at_sv_basis_roh(
|
||||
result_rules))
|
||||
return basis * satz / 100.0
|
||||
|
||||
def _l10n_at_svdg_sz_gesamt(self, result_rules=None):
|
||||
self.ensure_one()
|
||||
return sum(self._l10n_at_svdg_sz(k, result_rules)
|
||||
for k in ('kv', 'pv', 'av', 'uv', 'iesg'))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# § 53a ASVG — Geringfügig Beschäftigte
|
||||
# ------------------------------------------------------------------
|
||||
def _l10n_at_svdg_uv_geringfuegig(self, result_rules=None):
|
||||
"""DG-UV geringfügig Beschäftigter: 1,1 % der allgemeinen
|
||||
Beitragsgrundlage (§ 53a Abs 1 ASVG) als Monatspauschale
|
||||
(at_sv_geringfuegig['beitrag_uv']; aBG 2026 = 83,49 ÷ 14,12 % =
|
||||
591,29 → 6,50 € — abgeleitet, s. Rechenfälle). Entfällt bei
|
||||
UV-Stichtag (60. LJ) bzw. Lehrlingen (§ 51 Abs 6 ASVG)."""
|
||||
self.ensure_one()
|
||||
if not self._l10n_at_geringfuegig(result_rules):
|
||||
return 0.0
|
||||
if self._l10n_at_sv_satz('dg', 'uv') <= 0.0:
|
||||
return 0.0
|
||||
params = self.env['hr.rule.parameter']._get_parameter_from_code(
|
||||
'at_sv_geringfuegig', self.date_to, raise_if_not_found=False) \
|
||||
or {}
|
||||
return float(params.get('beitrag_uv', 0.0))
|
||||
@@ -1,3 +1,4 @@
|
||||
# Part of the odoo-at-payroll project. License: LGPL-3.
|
||||
from . import test_tasy_import
|
||||
from . import test_lohnsteuer
|
||||
from . import test_lohnsteuer
|
||||
from . import test_sozialversicherung
|
||||
@@ -156,13 +156,14 @@ class LohnsteuerTest(TransactionCase):
|
||||
# DN-SV / Bemessung (user-Formel)
|
||||
# ------------------------------------------------------------------
|
||||
def test_05_svdn_und_bemessung(self):
|
||||
"""SV-DN 18,07 % (KV/PV/AV/AK/WF) auf laufender Basis; Bemessung
|
||||
= Arbeitslohn − SV-DN (user-Formel)."""
|
||||
"""SV-DN auf 2.059,41 €: § 2a AMPFG mindert den DN-AV auf 0 %
|
||||
(BG ≤ 2.225 €) → DN-Gesamt 15,12 % statt 18,07 % (GP4-Staffel;
|
||||
DG-AV bleibt 2,95 %); Bemessung = Arbeitslohn − SV-DN."""
|
||||
employee = self._employee()
|
||||
self._regel('LFD', 2059.41)
|
||||
slip = self._slip(employee, 1)
|
||||
svdn = slip._l10n_at_svdn_gesamt()
|
||||
self.assertAlmostEqual(svdn, 2059.41 * 0.1807, places=2)
|
||||
self.assertAlmostEqual(svdn, 2059.41 * 0.1512, places=2)
|
||||
bem = slip._l10n_at_bemessung_laufen()
|
||||
self.assertAlmostEqual(bem, 2059.41 - svdn, places=2)
|
||||
|
||||
@@ -221,7 +222,7 @@ class LohnsteuerTest(TransactionCase):
|
||||
self._regel('SZ', 2059.41, bemessung='sonstig')
|
||||
slip_nov = self._slip(employee, 11)
|
||||
sz_bem = slip_nov._l10n_at_sz_bemessung()
|
||||
sv_sz = 2059.41 * 0.1707 # KV+PV+AV auf SZ-Basis
|
||||
sv_sz = 2059.41 * 0.1412 # KV+PV auf SZ-Basis; AV-DN 0 (§ 2a)
|
||||
self.assertAlmostEqual(sz_bem, 2059.41 - sv_sz, places=2)
|
||||
# Sechstel = 2 × 2059,41 × 60 ÷ 60 = 4.118,82 > Freigrenze
|
||||
self.assertAlmostEqual(
|
||||
@@ -257,13 +258,13 @@ class LohnsteuerTest(TransactionCase):
|
||||
python='result = payslip._l10n_at_lst_sonstige(result_rules)')
|
||||
slip_nov = self._slip(employee, 11, confirm=True)
|
||||
sz_nov = self._total(slip_nov, 'LST_SZ')
|
||||
# SV-SZ = 2.059,41 × 17,07 % = 351,54 (KV+PV+AV auf SZ-Basis)
|
||||
# SV-SZ = 2.059,41 × 14,12 % (KV+PV; AV-DN 0 nach § 2a AMPFG)
|
||||
self.assertAlmostEqual(
|
||||
sz_nov, (2059.41 * (1 - 0.1707) - 620.0) * 0.06, places=1)
|
||||
sz_nov, (2059.41 * (1 - 0.1412) - 620.0) * 0.06, places=1)
|
||||
slip_dez = self._slip(employee, 12)
|
||||
sz_dez = self._total(slip_dez, 'LST_SZ')
|
||||
# Jahres-SZ-Bemessung = 2 × (2.059,41 − SV-SZ)
|
||||
jahres_bem = 2 * 2059.41 * (1 - 0.1707)
|
||||
jahres_bem = 2 * 2059.41 * (1 - 0.1412)
|
||||
soll_jahr = (jahres_bem - 620.0) * 0.06
|
||||
self.assertAlmostEqual(sz_dez, soll_jahr - sz_nov, places=1)
|
||||
|
||||
@@ -276,8 +277,8 @@ class LohnsteuerTest(TransactionCase):
|
||||
slip = self._slip(employee, 1)
|
||||
# Sechstel = 2.000 × 60/30 = 4.000 > 2.615 → Pauschalierung
|
||||
self.assertAlmostEqual(slip._l10n_at_sechstel(), 4000.0, places=2)
|
||||
sz_bem = slip._l10n_at_sz_bemessung() # 6.000 − SV-SZ (1.024,20)
|
||||
self.assertAlmostEqual(sz_bem, 6000.0 - 6000.0 * 0.1707, places=2)
|
||||
sz_bem = slip._l10n_at_sz_bemessung() # 6.000 − SV-SZ (14,12 %)
|
||||
self.assertAlmostEqual(sz_bem, 6000.0 - 6000.0 * 0.1412, places=2)
|
||||
self.assertAlmostEqual(
|
||||
slip._l10n_at_sz_tarifisch_aktuell(), sz_bem - 4000.0, places=2)
|
||||
self.assertAlmostEqual(
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
# 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)
|
||||
@@ -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)
|
||||
@@ -1,5 +1,45 @@
|
||||
# CHANGELOG — odoo-at-payroll
|
||||
|
||||
## 2026-09-11 — General-AT GP4: SV/DB komplett im Kern umgesetzt (M5)
|
||||
|
||||
- `addons/l10n_at_hr_payroll` (19.0.3.0.0): `models/sozialversicherung.py`
|
||||
— DG-Beiträge (ÖGK 2026: DG 20,98 %, Wien 21,23 %), §-54-SZ-Beiträge
|
||||
DG 20,48 % (KV/PV/AV/UV/IESG), Geringfügigkeit § 5 Abs 2 iVm
|
||||
**§ 810 Abs 3 ASVG** (GFG 2026 = 551,10 €, Aufwertung ausgesetzt —
|
||||
A7-Rest gelöst) mit Hochrechnung bei untermonatiger Beschäftigung,
|
||||
§-53a-Abs-1-UV 6,50 €/Monat, beitragsfreie Bezüge § 49 Abs 3 mit
|
||||
Jahres-Kumulativen 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
|
||||
+IESG; § 51 Abs 6 — UV ab 60/Lehrlinge; § 51 Abs 7 — PV hälftig
|
||||
DG+DN; § 41 Abs 4 lit f FLAG), **ALV-DN-Staffel § 2a AMPFG
|
||||
(DN-seitig; 0/1/2 % bis 2.225/2.427/2.630 €; auch für SZ; ab 2027
|
||||
aufgehoben)**, WF-Satzvektor Bundesland × Jahr (Wien 0,75/0,75 ab
|
||||
1. 1. 2026), Beitragsmonats-Allokation (Anspruchsprinzip, historische
|
||||
Sätze/HBG je Beitragsmonatsgruppe, 2025-HBG 6.450 €), DAG-Bewertung
|
||||
§ 1 DAG (19,4 %, Schwelle 1,5 × GFG = 826,65 €, ≥ 2 Geringfügige,
|
||||
Lohnsumme ohne SZ). Parameter: `rule_parameters_sv_2026.xml` +
|
||||
AV-Staffel-Umbau (2025/2026/2027-Zeilen) in `rule_parameters_2026.xml`.
|
||||
- `addons/l10n_at_hr_payroll_private` (19.0.4.0.0):
|
||||
`salary_rules_sv_private.xml` — **SVDN_SZ-Nachtrag** (§ 67 Abs 12
|
||||
als eigene Abzugszeile; GP3-Lücke: Netto in §-67-Monaten um den
|
||||
SV-DN(SZ) zu hoch), DG-Block SVDG_*/SVDG_SZ_*/SVDG_UV_GFG (ATP_DG,
|
||||
ohne Nettoeffekt), FLAFDB (§ 41 FLAG 3,7 %), KOMMST (§ 9 KommStG
|
||||
3 %), DZ (§§ 122/126 WKG, WKO-flag-gated, Satzvektor je BL ⚠ WKO
|
||||
8.11) mit gemeinsamer LNK-Basis (Zufluss, ohne §-67-Abs-3/6, lit f
|
||||
nur FLAF/DZ, Freibetragsstaffel 1.095/1.460 €).
|
||||
- **Rechtskorrektur § 2a AMPFG:** DN-SV auf laufenden Bezügen und SZ
|
||||
bei BG ≤ 2.225 € sinkt von pauschal 18,07 % auf 15,12 % (ALV-DN
|
||||
0 %) — GP3-Rechenfälle RF-L1/L3/L5 und die betroffenen Tests
|
||||
nachgezogen (Engine war zuvor ohne Staffel); §-19a-Selbstversicherung
|
||||
2026 = **83,49 €/Monat** (statt ≈ 77,80 € — TASY KVPVBTG19A), Zahlung
|
||||
direkt an den Träger (kein Lohnabzug).
|
||||
- Tests: Kern `test_sozialversicherung` (14) + privat `test_sv_private`
|
||||
(8) neu; GP3-Suiten §-2a-korrigiert — **74/74 grün** auf `odoo_dev`
|
||||
(Aufruf s. README). Rechenfälle `docs/rechenfaelle/sozialversicherung.md`;
|
||||
RQ-Privat Abschnitt 4 und KB-KONFLIKTE A7 aufgelöst (§ 810 Abs 3 /
|
||||
§ 1 DAG / 83,49/826,65); Plan § 10 GP4-Update.
|
||||
|
||||
## 2026-09-10 — General-AT: Beschaffungsliste abgearbeitet (Primärquellen lokal)
|
||||
|
||||
- **19 RIS-Gesetzestexte** (konsolidiert, Fassung vom 10. 09. 2026;
|
||||
|
||||
@@ -783,6 +783,44 @@ Budget: die Kandidaten 8.13, der DZ (8.11) und die Regel-Optionen
|
||||
(NSchAB, DAG) laufen über die GP0-/Pilotmandant-Entscheidung bzw.
|
||||
Change-Requests.
|
||||
|
||||
**Update 2026-09-11 (GP4 umgesetzt):** SV/DB komplett im Kern gebaut
|
||||
(AP4, D3-Vorfinanzierung) und grün: `models/sozialversicherung.py`
|
||||
(DG-Beiträge ÖGK 2026 20,98 %/Wien 21,23; § 54-SZ-Beiträge DG
|
||||
20,48 % inkl. IESG; Geringfügigkeit § 5 Abs 2 iVm **§ 810 Abs 3
|
||||
ASVG — 2026-Aufwertung ausgestellt, GFG 551,10 € bestätigt → A7-Rest
|
||||
gelöst**; §-53a-Abs-1-UV 6,50 €/Monat; beitragsfreie Bezüge § 49
|
||||
Abs 3 mit Jahres-Kumulativen je DN; altersabhängige
|
||||
Satzausschaltungen als Stichtags-Datumfelder am Vertrag — AlVG
|
||||
§ 1 Abs 2 lit e (AV DN+DG+IESG), § 51 Abs 6 (UV ab 60), § 51 Abs 7
|
||||
(PV hälftig DG+DN, Bonusphase), § 41 Abs 4 lit f (FLAF/DZ);
|
||||
ALV-DN-Staffel § 2a AMPFG **DN-seitig** (bis 2.225/2.427/2.630 € →
|
||||
0/1/2 %, Grenzen nicht zu aliquotieren, gilt auch für SZ — korrigiert
|
||||
die GP3-Rechenfälle RF-L1 ff.: DN-SV 15,12 statt pauschal 18,07 %
|
||||
bei 2.059,41 €); WF-Satzvektor BL × Jahr (Wien 0,75/0,75 ab 1.1.2026,
|
||||
löst die KB-Protokollnotiz); Beitragsmonats-Allokation
|
||||
(Regel-/Lohnkontolinien-Feld, historische Sätze+HBG je Gruppe,
|
||||
2025-HBG-Zeile 6.450); DAG-Bewertung § 1 DAG (19,4 %, Schwelle
|
||||
1,5 × GFG = 826,65 €, ≥ 2 Geringfügige, Lohnsumme ohne SZ).
|
||||
Parameter: `rule_parameters_sv_2026.xml` (WF-Vektor, §-49-Grenzen,
|
||||
§-53a-Pauschalen 77,81/83,49 — **§-19a-Selbstversicherung 2026 =
|
||||
83,49 €** statt ≈ 77,80 (TASY KVPVBTG19A); FLAF 3,7/2,7; KommSt 3;
|
||||
LNK-Freibetrag 1.095/1.460; DZ-Vektor je BL ⚠ WKO 8.11; DAG-Satz+Faktor)
|
||||
+ AV-Staffel-Umbau (2025-Zeile 2.074/2.262/2.451, 2026-Zeile auf
|
||||
01.01. vorverlegt, 2027-Zeile tiers=[] da § 2a Ende 2026 aufgehoben).
|
||||
Privat: `salary_rules_sv_private.xml` — **SVDN_SZ-Nachtrag** (§ 67
|
||||
Abs 12 als eigene Abzugszeile — GP3-Lücke: Netto in §-67-Monaten
|
||||
war um den SV-DN(SZ) zu hoch), DG-Block SVDG_*/SVDG_SZ_*/SVDG_UV_GFG
|
||||
(ATP_DG), FLAFDB/KOMMST/DZ (WKO-flag) mit LNK-Basis-Compute
|
||||
(`_at_lnk_basis`: Zufluss, ohne §-67-Abs-3/6, lit f nur FLAF/DZ,
|
||||
KommSt ohne Befreiung). Neue Tests: Kern `test_sozialversicherung`
|
||||
(14) + privat `test_sv_private` (8); GP3-Erwartungen §-2a-korrigiert
|
||||
— **74/74 grün** auf `odoo_dev`. Rechenfälle
|
||||
`docs/rechenfaelle/sozialversicherung.md` + lohnsteuer.md-GP4-
|
||||
Korrekturvermerk. Offen: UI der Vertragsfelder (GP8), DAG-Ausweis/
|
||||
Veranlagung (GP8), DZ-WKO-Verifikation (8.11), IESG-auf-SZ-§-5-
|
||||
AMPFG-Volltext, §-2a-Volltext (Abs 1 Z 1–3) bei GP8-Parameterpflege,
|
||||
mBGM-Nachtragslogik (GP7), GP5 Abfertigung Neu als nächster Bauabschnitt.
|
||||
|
||||
**Update 2026-09-11 (GP3 umgesetzt):** Lohnsteuer komplett im Kern
|
||||
gebaut (AP3, D3-Vorfinanzierung) und grün: `models/lohnsteuer.py`
|
||||
(§ 33-Tarif, § 66 kumulativ mit Rollung über Lohnsteuertage 30/Monat,
|
||||
|
||||
@@ -106,7 +106,36 @@
|
||||
- **AK-Umlage = 0,5 % DN-Beitrag** (ÖGK-Tarifsystem Normalbetriebe: AK 0,500 in der **DN**-Zeile, Arbeiter **und** Angestellte; TASY: AK-Tarif im Tarifset der Beschäftigtengruppen „Arbeiter" B001 und „Angestellte" B002) — die frühere RQ-Formel „0,5 % (**nur DG**)" war **falsch**; **lb-sva-06 („0,50 % (DN)") war richtig.** Das Kern-Modul trägt bereits den korrekten Stand (`at_sv_ak_dn` 0,5 / `at_sv_ak_dg` 0,0) — nur die Doku war falsch (→ RQ Abschnitt 4 korrigiert).
|
||||
- **Korrektur (2026-09-11, 2. Verifikationsrunde):** **„14,12" ist ein Prozentsatz** — § 53a Abs 3 ASVG idgF (`.additional_docs/gsvg53a.pdf`; Datei enthält § 53a **ASVG**, nicht GSVG): Pauschalbeitrag geringfügig Vollversicherter = **14,12 % der allgemeinen Beitragsgrundlage** (KV 3,87 % + PV 9,25 % + PV-Zusatzbeitrag 1,00 %); § 53a Abs 1: DG-UV-Beitrag 1,1 % der allgemeinen Beitragsgrundlage. Die **%-Spalten-Einordnung in lb-sva-06 war richtig**; die 1.-Runde-Lesung „14,12 = €/Monat" (und die RQ-Zeile „Geringfügigen-Beitrag 14,12 €/Monat") war **falsch** und ist in RQ Abschnitt 4 korrigiert.
|
||||
- **Fundstellen ✅ (3. RIS-Runde 11.09.2026):** **GFG = ASVG § 5 Abs 2** („… kein höheres Entgelt als 425,70 €“; ab Beginn jedes Beitragsjahres × Aufwertungszahl § 108a; `asvg_index.txt`): **BMSG geringfügig Beschäftigter = GFG** bestätigt (BVAEB deckungsgleich). **AK-Umlage = AKG § 61** (`akg_par61.txt`, NOR40114698): Abs 1 Umlage von kammerzugehörigen AN; Abs 2 **höchstens 0,5 %** der KV-allgemeinen Beitragsgrundlage, **HBG-Cap § 45 Abs 1 lit a ASVG**; Abs 3 Einbehalt vom Lohn; Abs 4 Einhebung durch SV-Träger (Abfuhr bis 20. des Folgemonats); Pflichtmitgliedschaft § 10 AKG. § 53a ASVG (NOR40245133): Abs 3 Pauschalbeitrag **14,12 %** (KV 3,87 + PV 9,25 + PV-Zusatz 1,00) der allgemeinen BMSG.
|
||||
- **Rest offen (⚠ wertkritisch):** **2026-GFG** — die §-5-Abs-2-Anm.-Reihe enthält per RIS 11.09.2026 **keinen 2026-Eintrag**; **551,10 € = Wert 2025** (BGBl II 417/2024; BGBl II 263/2025 weist den 2026-GFG nicht aus). Die €-Pauschale 2026 (14,12 % × GFG ≈ 77,80 €) und die DAG-Schwelle (1,5 × GFG = 826,65 €) dürfen erst nach Fixierung des **2026**-GFG parametrisiert werden (SV-VO/ÖGK bei GP4/GP8-Parameterpflege prüfen).
|
||||
- **Rest offen (⚠ wertkritisch) — ✅ GELÖST (GP4, 2026-09-11):** Der
|
||||
fehlende 2026-Eintrag in der §-5-Abs-2-Anmerkungsreihe ist
|
||||
aufgeklärt: **§ 810 Abs 3 ASVG setzt die Aufwertung der
|
||||
Geringfügigkeitsgrenze für 2026 aus** („Beitragsrechtliche Werte
|
||||
2026", sozialversicherung.at, Fn. 1: GFG 2026 unverändert
|
||||
**551,10 €**); deckungsgleich lb-bes-06 (Stand 2026-07: „bleibt
|
||||
gegenüber 2025 unverändert", Historie 2024: 518,44 · 2023: 500,91 ·
|
||||
2022: 485,85) und TASY GFGBTG (offene Gültigkeit ab 2025-01-01).
|
||||
**DAG-Grenzbetrag 2026 = 826,65 €** (TASY MINGRDAGP1 „§ 1 Abs.1 DAG
|
||||
Grenzbetrag", offen ab 2025-01-01; offizielle SV-Werte Fn. 8;
|
||||
Historie 2024: 777,66 · 2023: 751,37 · 2022: 728,78 = je 1,5 × GFG)
|
||||
— Nutzer-Beobachtung „862,25“ war Zifferndreher (1,5 × 551,10 =
|
||||
826,65). **§-19a/§-53a-Abs-3-Selbstversicherung 2026 = 83,49 €/**
|
||||
Monat (§ 77 Abs 2a ASVG; TASY KVPVBTG19A: 2024: 73,20 · 2025: 77,81
|
||||
· 2026: 83,49) — korrigiert die RQ-Abschnitt-4-Zeile „≈ 77,80 €"
|
||||
(2025-Wert); Pauschalbeitrag auch von SZ (§ 53a Abs 5 ✅ Normtext);
|
||||
aBG 2026 = 83,49 ÷ 14,12 % = 591,29 € → DG-UV § 53a Abs 1 = 1,1 %
|
||||
× aBG ≈ 6,50 €/Monat (abgeleitet ⚠ direkter Beleg bei GP8-
|
||||
Parameterpflege). **Normzitat DAG ✅:** § 1 DAG (ÖGK-Beitragstarif-
|
||||
system „Dienstgeberabgabe gem. § 1 DAG" + lb-bes-02) — lb-sva-12-
|
||||
„ohne Normzitat" damit erledigt. Engine-Umsetzung: GP4
|
||||
(`at_sv_geringfuegig`, `at_dag`, DAG-Bewertung § 1 DAG).
|
||||
- **AV-Staffel § 2a AMPFG — Klarstellung GP4 (2026-09-11):** Die
|
||||
Staffel mindert **nur den DN-Anteil** (ÖGK-Abschläge „Mind. AV auf
|
||||
0/1/2 %“ = −2,95/−1,95/−0,95 vH; Beitragsrechtliche Werte 2026,
|
||||
Fn. 3: bis 2.225 €: 0 % · bis 2.427: 1 % · bis 2.630: 2 %) — die
|
||||
frühere Parameter-Annahme „av_total“ (GemBG-Seed) war in der
|
||||
Wirkung falsch und ist umgebaut (tiers + dn_voll; Grenzen nicht zu
|
||||
aliquotieren, gelten auch für SZ-Beiträge, lb-son-03; § 2a Ende
|
||||
2026 aufgehoben → ab 2027 voller DN-Satz).
|
||||
|
||||
### A8. Höchstbeitragsgrundlagen (HBGL) im SV-System
|
||||
|
||||
@@ -360,11 +389,11 @@ Nicht im Korpus enthalten; Querverweise in den Einträgen bestehen bereits:
|
||||
|
||||
## Nächste Schritte (konsolidiert — nach der A-/B-Lösungsrunde und 2. Verifikationsrunde 2026-09-11)
|
||||
|
||||
1. **RIS-Klärrunde (Plan 8.12) — Restagenda nach der 3. RIS-Runde (11.09.2026):** offen bleiben **A3 („Formel 7“/Verwaltungspraxis — blockiert AP4)**, **A4-All-In** (AMS-Abklärung) und **A7-2026-GFG** (551,10 € = 2025-Wert; vor GP4/GP8 über SV-VO/ÖGK fixieren — Pauschale ≈ 77,80 € und DAG-Schwelle 826,65 € hängen daran); **erledigt in der 3. Runde**: A6-ALV-Entfall-Wortlaut (AlVG § 1 Abs 2 lit e 2027-Fassung, NOR40280219 ✅), A9-AZR-Werte (1.273,99/1.308,39, ASVG § 293 Anm. 2 ✅), A10-Altrecht (APG § 1 Abs 3 ✅), A4-Zitierstruktur (Art. 2 § 27 + Art. 7 § 82 Abs 7/8 ✅), A1-Zitierkorrektur (Z 440 lit c ✅), B16-Bezugszeitraum (Z 492/494 ✅); **bereits vorher erledigt**: 6 %-Fixsatz § 67 Abs 3 idgF (A5 ✅), GSVG § 48 + §-45/§-108-Zitierkette (A8 ✅), § 82 Abs 7/8 AlVG-Normbasis (A4 ✅), Bonus-Maxima § 5 Abs 4 APG idgF (A10 ✅), A6-BgBG-Identität (BGBl I 62/2026, verkündet) + §-25-Doppelfehlzitat (✅); **B-Familien mit der B-Lösungsrunde 2026-09-11 erledigt** (s. Abschnitt B) — Restpunkte s. Punkt 2.
|
||||
1. **RIS-Klärrunde (Plan 8.12) — Restagenda nach der 3. RIS-Runde (11.09.2026):** offen bleiben **A3 („Formel 7“/Verwaltungspraxis — blockiert nur die Prämienoptimierung, nicht den GP4-Kern; konservative GP3-Verteilung als Default umgesetzt)**, **A4-All-In** (AMS-Abklärung) und **DZ-WKO-Satzverifikation** (8.11; Umsetzung läuft flag-gated); **A7-2026-GFG ✅ in GP4 gelöst** (§ 810 Abs 3 ASVG Aufwertungsaussetzung — GFG 551,10, DAG-Grenze 826,65, §-19a-Pauschale 83,49 €, UV 6,50 € abgeleitet); **erledigt in der 3. Runde**: A6-ALV-Entfall-Wortlaut (AlVG § 1 Abs 2 lit e 2027-Fassung, NOR40280219 ✅), A9-AZR-Werte (1.273,99/1.308,39, ASVG § 293 Anm. 2 ✅), A10-Altrecht (APG § 1 Abs 3 ✅), A4-Zitierstruktur (Art. 2 § 27 + Art. 7 § 82 Abs 7/8 ✅), A1-Zitierkorrektur (Z 440 lit c ✅), B16-Bezugszeitraum (Z 492/494 ✅); **bereits vorher erledigt**: 6 %-Fixsatz § 67 Abs 3 idgF (A5 ✅), GSVG § 48 + §-45/§-108-Zitierkette (A8 ✅), § 82 Abs 7/8 AlVG-Normbasis (A4 ✅), Bonus-Maxima § 5 Abs 4 APG idgF (A10 ✅), A6-BgBG-Identität (BGBl I 62/2026, verkündet) + §-25-Doppelfehlzitat (✅); **B-Familien mit der B-Lösungsrunde 2026-09-11 erledigt** (s. Abschnitt B) — Restpunkte s. Punkt 2.
|
||||
2. **B-Runde-Rest (2026-09-11):** **B3** VwGH-Ausgang der Amtsrevision (BFG RV/3100422/2024, fortsetzend RV/7105649/2017) abwarten — bis dahin Praxis konservativ nach LStR Rz 104; **B14** Umsetzungsentscheidung zurückgestellt (Verantwortlichen-Entscheidung); **B18** GKK-Verfahrensweise als Praxis-Default dokumentiert, Dissent beibehalten; **B17** inhaltlich ⚠ (VwGH 2021/13/0004 vs. LStR-Praxis; Zitat korrigiert). Kleinverifikationen: **B2** LZP-Anwendung (§ 8 Abs 12 EuroStUV-Volltext), **B5** Schlichtungsstellen-§-Verweise (GlBG/BehG) bei Umsetzung — **B16-Bezugszeitraum ✅ RIS 11.09.2026** (Z 492/494, s. B16).
|
||||
3. **AMS-Abklärung (A4-Rest):** All-In-Oberwert-Basis (AMS-Stellungnahme/Praxis-RL einholen) — Ersatzquote (27,5 % Blockzeit 2026) und ÜStd-Behandlung sind geklärt.
|
||||
4. **GP3/GP4-Blockade:** A3 bleibt der einzige Punkt, der AP4 direkt blockiert.
|
||||
4. **A3-Reststatus (nach GP4):** blockiert nur noch die **Prämienoptimierung („Formel 7“)**, nicht den umgesetzten GP4-Kern (SV-Verteilung konservativ nach GP3-Default: §-68-Zuschläge verbleiben in der laufenden SV-Beitragsgrundlage).
|
||||
5. **Folgebatches:** D-Liste mit Pilotmandant abstimmen (Plan 8.13, inkl. Mutterschutz-/Karenz-Block).
|
||||
6. **2027er-Werte:** C7 erst nach Verordnungsverlautbarung/BGBl-Endfassung in die Engine.
|
||||
7. **Engine-Protokollnotizen aus der A-Runde:** WF-Wien-Zuschlag (+0,25/0,25 ab 1.1.2026) als rule parameter ergänzen, bevor Wien-Mandanten abgerechnet werden (GP2–GP4-Designinput); Geringfügigen-Pauschalbeitrag (14,12 % der allgemeinen Beitragsgrundlage = GFG, § 53a Abs 3 ASVG iVm § 5 Abs 2 ASVG ✅ RIS) bei GP4/GP8 parametrisieren — ⚠ erst nach Fixierung des **2026-GFG** (A7-Rest; 551,10 € = Wert 2025 — Pauschale ≈ 77,80 €/Monat und DAG-Schwelle 826,65 € hängen daran).
|
||||
7. **Engine-Protokollnotizen aus der A-Runde:** WF-Wien-Zuschlag (+0,25/0,25 ab 1.1.2026) ✅ als rule parameter umgesetzt (GP4, `at_sv_wf_vektor`); Geringfügigen-Beiträge ✅ in GP4 parametrisiert (`at_sv_geringfuegig`: UV 6,50 € abgeleitet/Selbstversicherung 83,49 €; §-19a-Zahlung direkt an den Träger — KEIN Lohnabzug, SV-Werte-2026 Fn. 9).
|
||||
8. **Engine-Designnotizen aus der B-Runde:** IESG-Grenzbeträge als HBG-Relationen je LZP parametrisieren (Grenzbetrag 2× HBG; Abfertigung 1× voll / darüber bis 2× halb → wirksam 1,5× je Monatsbetrag; B11); EFZG-Entgeltfortzahlungsstufen 6/8/10/12 Wochen + je 4 Wochen halbes Entgelt, AU/BK separat (B13); § 67 Abs 6-Zwölftel-Deckel Dreifaches der monatlichen HBG (2026: 20.790 €; B17); § 68 Abs 1-Feiertagsarbeitsentgelt im 400-€-Freibetrag ab LZP 2026 (B16); GF-Schwelle > 25 % für ASVG/GSVG-Zuständigkeitslogik (B7); SBV § 2 Abs 7a-Kleinwohnungswerte (B2); BSVG-Versicherungswert je Beitragsjahr aus Aufwertungszahl (B15).
|
||||
|
||||
@@ -206,19 +206,23 @@ deckungsgleich (A-Lösungsrunde, s. `KB-KONFLIKTE.md` A2/A7).
|
||||
|
||||
| Wert | 2026 |
|
||||
|---|---|
|
||||
| Höchstbeitragsgrundlage (monatlich) | 6.930,00 € (SZ-Jahreshöchstbetrag 13.860,00 €; Systematik s. u.) |
|
||||
| Geringfügigkeitsgrenze (§ 5 Abs 2 ASVG) | 551,10 €/Monat ⚠ **= Wert 2025** (BGBl II 417/2024; 425,70 € × Aufwertungszahl § 108a) — 2026-Wert per RIS 11.09.2026 noch nicht verlautbart; vor GP4/GP8 fixieren |
|
||||
| Höchstbeitragsgrundlage (monatlich) | 6.930,00 € (SZ-Jahreshöchstbetrag 13.860,00 € = 60faches HBG, § 54 ASVG; Systematik s. u.) |
|
||||
| Geringfügigkeitsgrenze (§ 5 Abs 2 ASVG) | 551,10 €/Monat ✅ **= Wert 2026** — die Aufwertung ist gem. **§ 810 Abs 3 ASVG für 2026 ausgesetzt** („Beitragsrechtliche Werte 2026", Fn. 1; deshalb kein 2026-Eintrag in der RIS-Anmerkungsreihe; A7-Rest gelöst, GP4). SZ zählen nicht zur Ermittlung; untermonatig: Hochrechnung auf den Monat (lb-bes-06) |
|
||||
| Krankenversicherung (KV) | 7,65 % (DN 3,87 / DG 3,78) |
|
||||
| Pensionsversicherung (PV) | 22,80 % (DN 10,25 / DG 12,55) |
|
||||
| Unfallversicherung (UV) | 1,10 % (nur DG) |
|
||||
| Arbeitslosenversicherung (AV) | 5,90 % (2,95/2,95); Staffel § 2a AMPFG (durch BGBl I 62/2026 aufgehoben, außer Kraft 31. 12. 2026); **ALV-Entfall ab 1. 1. 2027** = AlVG § 1 Abs 2 lit e idF BGBl I 62/2026 (NOR40280219; bei Zuerkennung oder erfüllter Anwartschaft, Folgemonat, inkl. Korridorpension; DN + DG + IESG-Zuschlag entfallen) |
|
||||
| Arbeitslosenversicherung (AV) | 5,90 % (2,95/2,95); **DN-Staffel § 2a AMPFG** (mindert nur den DN-Anteil): BG bis 2.225 €: 0 % · bis 2.427 €: 1 % · bis 2.630 €: 2 % — Grenzen nicht zu aliquotieren, gelten auch für SZ; § 2a mit 31. 12. 2026 aufgehoben (BGBl I 62/2026); **ALV-Entfall ab 1. 1. 2027** = AlVG § 1 Abs 2 lit e idF BGBl I 62/2026 (NOR40280219; bei Zuerkennung oder erfüllter Anwartschaft, Folgemonat, inkl. Korridorpension; DN + DG + IESG-Zuschlag entfallen) |
|
||||
| AK-Umlage | 0,5 % (**DN-Lohnabzug**; DG 0) — **AKG § 61** ✅ RIS 11.09.2026 (Abs 2: höchstens 0,5 % der KV-allgemeinen Beitragsgrundlage, HBG-Cap § 45 Abs 1 lit a ASVG; Abs 3 Lohnabzug; Abs 4 Einhebung SV-Träger) |
|
||||
| Wohnbauförderungsbeitrag (WF) | 1,0 % (0,5/0,5) bundesweit; **Wien ab 1.1.2026: 1,5 % gesamt (0,75 DN + 0,75 DG)** — Wiener WF-Zuschlag gem. Wiener WF-Beitragstarif 2018 § 1 |
|
||||
| IESG-Zuschlag (Insolvenz) | 0,10 % (nur DG) |
|
||||
| Geringfügigen-Pauschalbeitrag (§ 53a Abs 3 ASVG) | **14,12 % der allgemeinen Beitragsgrundlage = GFG** (ASVG § 5 Abs 2; KV 3,87 · PV 9,25 + 1,00 Zusatz) — GFG-Basis 551,10 € = **Wert 2025** (≈ € 77,80/Monat); ⚠ €-Pauschale erst nach Fixierung des **2026**-GFG parametrisieren; DG-UV 1,1 % (§ 53a Abs 1 ASVG; ÖGK-Tarifsystem zitiert § 51 Abs 1 Z 2 ASVG) |
|
||||
| Geringfügigen-Beiträge (§ 53a ASVG) | **DG-UV 1,1 % der allgemeinen Beitragsgrundlage** (§ 53a Abs 1; ≈ **6,50 €/Monat** 2026 — aBG abgeleitet: 83,49 ÷ 14,12 % = 591,29 € ⚠ direkter Beleg GP8); **Selbstversicherung KV+PV 83,49 €/Monat 2026** (§ 53a Abs 3: 14,12 % der aBG = KV 3,87 · PV 9,25 + 1,00 Zusatz; § 77 Abs 2a ASVG; TASY KVPVBTG19A: 2024: 73,20 · 2025: 77,81 · 2026: 83,49) — **kein Lohnabzug**: Zahlung der Person direkt an den Träger (SV-Werte-2026 Fn. 9); Pauschalbeitrag auch von SZ (§ 53a Abs 5) |
|
||||
| BV-Beitrag (BMSVG) | 1,53 % (DG; auf Entgelt **und** SZ) |
|
||||
| DN-Gesamtbeitragssatz (Normalbetriebe) | **18,07 %** = SV 17,07 (KV 3,87 · PV 10,25 · ALV 2,95 · UV 0) + AK 0,50 + WF 0,50 — **Wien 18,32 %** (WF-DN 0,75) |
|
||||
| DN-Gesamtbeitragssatz (Normalbetriebe) | **18,07 %** = SV 17,07 (KV 3,87 · PV 10,25 · ALV 2,95 · UV 0) + AK 0,50 + WF 0,50 — **Wien 18,32 %** (WF-DN 0,75); **über 2.630 € BG** — darunter §-2a-Staffel: 2.059,41 € → DN 15,12 % (GP4) |
|
||||
| DG-Gesamtbeitragssatz (Normalbetriebe) | **20,98 %** = SV 20,38 (KV 3,78 · PV 12,55 · ALV 2,95 · UV 1,10) + WF 0,50 + IESG 0,10 — **Wien 21,23 %** |
|
||||
| SZ-Beiträge (§ 54 ASVG) | DN **14,12 %** (KV 3,87 · PV 10,25; ALV nach §-2a-Staffel) — ohne AK/WF (§ 62 Z 3/Z 5); DG **20,48 %** = KV 3,78 · PV 12,55 · ALV 2,95 · UV 1,10 · IESG 0,10 (IESG folgt dem ALV-Beitrag; ⚠ §-5-AMPFG-Volltext GP8) |
|
||||
| Altersabhängige Satzausschaltungen | ALV DN+DG **und IESG** entfallen (AlVG § 1 Abs 2 lit e; § 12 Abs 1 Z 4 iVm Abs 2 IESG); UV entfällt (§ 51 Abs 6 ASVG); PV je hälftig DG+DN in der Bonusphase (§ 51 Abs 7 ASVG — „A 15“; Kontogutschrift ungekürzt); FLAF+DZ ab Folgemonat nach 60 ohne den AN (§ 41 Abs 4 lit f FLAG — KommSt ohne Befreiung) |
|
||||
| Dienstgeberabgabe geringfügig Beschäftigter (§ 1 DAG) | **19,4 %** der Lohnsumme (Beitragsgrundlagen **ohne SZ**) aller Geringfügigen je Kalendermonat, wenn Lohnsumme > **826,65 €** (= 1,5 × GFG; TASY MINGRDAGP1, offene Gültigkeit) und ≥ 2 Geringfügige; „mit UV 20,5 %“ = Summensicht (UV separat § 53a Abs 1); ab 60. LJ entfällt der UV-Anteil; jährliche Zahlung (lb-bes-06; Rhythmus aus §-1-DAG-Volltext GP8) |
|
||||
| Beitragsfreie Bezüge (§ 49 Abs 3 ASVG) | Stand 2026-07 (lb-sva-03/04): Mahlzeiten-Gutscheine 8 €/AT · Lebensmittel 2 €/AT · Mitarbeiterrabatte ≤ 20 % je Fall ODER 1.000 €/J · Betriebsveranstaltungen 365 €/J · Jubiläums-Sachzuwendungen 186 €/J · Zukunftssicherung 300 €/J · Kinderbetreuungszuschuss 2.000 €/Kind/J · Homeoffice-Pauschale 3 €/Tag max 100 Tage (iVm § 26 Z 9 EStG) — Jahres-Kumulative je DN, Überschuss = beitragspflichtiger Sachbezug |
|
||||
|
||||
- **HBGL-Systematik (A-Lösung 2026-09-11):** ASVG = **Kalendertagwert**
|
||||
nach § 108 Abs 3 (2026: 231 €/Kalendertag, BGBl II 263/2025;
|
||||
@@ -589,7 +593,7 @@ nunmehr die **§-Inhalte** anhand der Volltexte zu verifizieren:
|
||||
Beschäftigung), § 49 Abs 2/3 (Beitragsgrundlagen-Systematik,
|
||||
beitragsfreie Bezugsbestandteile), § 44 Abs 7 (Umverteilung
|
||||
bei Gleitzeit/Durchrechnung), § 51 Abs 6 (UV-Entfall ab 60),
|
||||
§ 53b (AUVA-Zuschuss geringfähig Beschäftigter), § 60 (DN-
|
||||
§ 53b (AUVA-Zuschuss geringfügig Beschäftigter), § 60 (DN-
|
||||
Abzugsrecht bei Nachzahlung), § 143 (Krankengeldanspruch bei
|
||||
DG-Zuschuss) — kuratiert unterlegt über sva-/mel-/bes-Cluster
|
||||
(Plan 4.3/4.6); Primärverifikation vor GP4/GP7.
|
||||
|
||||
Reference in New Issue
Block a user