mirror of
http://100.103.83.12:3003/fegger/odoo-at-payroll.git
synced 2026-09-17 08:52:45 +00:00
[IMP] l10n_at_hr_payroll_private: add statutory old-system severance (AP15-A)
Pay the pre-2003 AngG severance from the end-of-employment run as its own neutral benefit line: free of SV (§ 49 Abs 3 Z 7 ASVG) and payroll levies, outside the annual sixth, and collected into the § 291d EO termination pot net of its own wage tax. Taxation follows the binding better-of rule of § 67 Abs 3 EStG: multiple-of-method (tariff wage tax on the running monthly wage × the statutory multiple of the payout) versus the flat 6 % rate, applied mandatorily in favour of the employee. The tariff wage tax is captured as a separately confirmed value instead of deriving it from gross pay through the § 62 engine. The wizard enforces § 23a Abs 3 AngG (parental exit needs five uninterrupted years), blocks BMSVG-new contracts except frozen claims and validates AGRD 02/06 against the claim type. The LNK basis subtracts § 67 Abs 3/6 rules only when they actually run in the tax base, the L16 generator reports LST_ABF in key 260 outside 210/220, and result_rules access in the garnishment paths avoids DefaultDictPayroll materialisation. Verified against the original statute texts in .ris/ (AngG §§ 23/23a, EStG § 67 Abs 3). Version 19.0.13.0.0 (private), 19.0.9.0.0 (core)
This commit is contained in:
@@ -68,6 +68,11 @@ L10N_AT_BUCHUNGSMATRIX = {
|
||||
'rule_svdn_sz': {'credit': ('3600',)},
|
||||
'rule_lst_lfd': {'credit': ('3540',)},
|
||||
'rule_lst_sz': {'credit': ('3540',)},
|
||||
'rule_lst_abf': {'credit': ('3540',)},
|
||||
# Gesetzliche Abfertigung Alt: bis zur Referenzbuchhaltungs-
|
||||
# Fixierung allgemeiner Gehalts-/Lohnaufwand, company-dependent
|
||||
# Regelkonto bleibt übersteuerbar.
|
||||
'rule_abf_alt': {'debit': ('6200',), 'debit_arbeiter': ('6000',)},
|
||||
# Nettoauszahlung (reconcilable, s. o.)
|
||||
'rule_netto': {'credit': ('3850',)},
|
||||
# DG-Beiträge (650–655 SV Arbeiter · 656–659 SV Angestellte)
|
||||
|
||||
@@ -56,6 +56,34 @@ class HrSalaryRule(models.Model):
|
||||
class HrPayslip(models.Model):
|
||||
_inherit = 'hr.payslip'
|
||||
|
||||
l10n_at_abf_alt_anspruchsart = fields.Selection(
|
||||
[('normal', 'Normalanspruch (§ 23 AngG)'),
|
||||
('eltern', 'Elternaustritt (§ 23a Abs 3/4 AngG)'),
|
||||
('tod', 'Tod (§ 23 Abs 6 AngG)'),
|
||||
('pension', 'Pension/Invalidität (§ 23a Abs 1 AngG)'),
|
||||
('eingefroren', 'Eingefrorener Altanspruch (§ 47 BMSVG)'),
|
||||
('manuell', 'Sonstiger nachgewiesener Anspruch')],
|
||||
string='AT Abfertigung Alt — Anspruchsart', copy=False)
|
||||
l10n_at_abf_alt_dienstzeit_monate = fields.Integer(
|
||||
string='AT Abfertigung Alt — Dienstzeitmonate', copy=False)
|
||||
l10n_at_abf_alt_monatsentgelt = fields.Float(
|
||||
string='AT Abfertigung Alt — Monatsentgelt', copy=False,
|
||||
help='Bestätigte arbeitsrechtliche Bemessungsgrundlage inklusive '
|
||||
'regelmäßiger Bezugsbestandteile und aliquoter Sonderzahlungen.')
|
||||
l10n_at_abf_alt_laufender_arbeitslohn = fields.Float(
|
||||
string='AT Abfertigung Alt — laufender Arbeitslohn', copy=False,
|
||||
help='Laufender Monatsarbeitslohn für den steuerlichen '
|
||||
'Vervielfacher nach § 67 Abs 3 EStG.')
|
||||
l10n_at_abf_alt_monatslohnsteuer = fields.Float(
|
||||
string='AT Abfertigung Alt — tarifmäßige Monatslohnsteuer',
|
||||
copy=False,
|
||||
help='Auf den maßgeblichen laufenden Monatsarbeitslohn entfallende '
|
||||
'tarifmäßige Lohnsteuer nach den persönlichen Verhältnissen.')
|
||||
l10n_at_abf_alt_mehrfach = fields.Float(
|
||||
string='AT Abfertigung Alt — Anspruchsfaktor', copy=False)
|
||||
l10n_at_abf_alt_nachweis = fields.Text(
|
||||
string='AT Abfertigung Alt — Nachweis/Begründung', copy=False)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# SV-Tage-Umrechnung und Verlängerungsmonate (§ 11 Abs 2 ASVG)
|
||||
# ------------------------------------------------------------------
|
||||
@@ -135,6 +163,75 @@ class HrPayslip(models.Model):
|
||||
lambda i: i.input_type_id.code == code)
|
||||
return linie[:1].amount or 0.0
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Abfertigung Alt — §§ 23/23a AngG, § 67 Abs 3 EStG
|
||||
# ------------------------------------------------------------------
|
||||
def _at_abf_alt_staffel(self, dienstzeit_monate=None):
|
||||
"""Arbeitsrechtlicher Grundfaktor nach § 23 Abs 1 AngG."""
|
||||
self.ensure_one()
|
||||
monate = dienstzeit_monate
|
||||
if monate is None:
|
||||
monate = self.l10n_at_abf_alt_dienstzeit_monate
|
||||
staffel = self._l10n_at_param('at_endabrechnung').get(
|
||||
'abfertigung_alt_staffel', [])
|
||||
mehrfach = 0.0
|
||||
for grenze, faktor in staffel:
|
||||
if monate >= int(grenze):
|
||||
mehrfach = float(faktor)
|
||||
return mehrfach
|
||||
|
||||
def _at_abf_alt_mehrfach_vorschlag(self, dienstzeit_monate=None,
|
||||
anspruchsart=None):
|
||||
"""§-23-Faktor mit Halb-/Deckelregeln für Elternaustritt/Tod."""
|
||||
self.ensure_one()
|
||||
art = anspruchsart or self.l10n_at_abf_alt_anspruchsart
|
||||
monate = dienstzeit_monate
|
||||
if monate is None:
|
||||
monate = self.l10n_at_abf_alt_dienstzeit_monate
|
||||
mehrfach = self._at_abf_alt_staffel(monate)
|
||||
if art == 'eltern':
|
||||
if monate < 60:
|
||||
return 0.0
|
||||
return min(mehrfach / 2.0, 3.0) if mehrfach else 0.0
|
||||
if art == 'tod':
|
||||
return mehrfach / 2.0
|
||||
return mehrfach
|
||||
|
||||
def _at_abf_alt_betrag(self, result_rules=None):
|
||||
"""Gesetzliche Alt-Abfertigung als eigene Bezugszeile."""
|
||||
self.ensure_one()
|
||||
return self._at_input_amount('ATP_ABF_ALT')
|
||||
|
||||
def _at_abf_alt_steuer_6(self, result_rules=None):
|
||||
self.ensure_one()
|
||||
satz = float(self._l10n_at_param(
|
||||
'at_endabrechnung')['abfertigung_steuersatz'])
|
||||
return max(self._at_abf_alt_betrag(result_rules), 0.0) * satz / 100.0
|
||||
|
||||
def _at_abf_alt_steuer_vervielfachung(self, result_rules=None):
|
||||
"""§ 67 Abs 3: Monats-Tarif-LSt × steuerlicher Vervielfacher.
|
||||
|
||||
Der steuerliche Vervielfacher ist Abfertigungsbetrag dividiert
|
||||
durch den laufenden Arbeitslohn. Er kann vom arbeitsrechtlichen
|
||||
Staffel-Faktor abweichen, weil die Abfertigungsbasis etwa aliquote
|
||||
Sonderzahlungen enthält (lb-end-01, RF 21 Dienstjahre: 10,5 statt 9).
|
||||
"""
|
||||
self.ensure_one()
|
||||
betrag = self._at_abf_alt_betrag(result_rules)
|
||||
laufend = self.l10n_at_abf_alt_laufender_arbeitslohn
|
||||
if betrag <= 0 or laufend <= 0:
|
||||
return self._at_abf_alt_steuer_6(result_rules)
|
||||
vervielfacher = betrag / laufend
|
||||
return self.l10n_at_abf_alt_monatslohnsteuer * vervielfacher
|
||||
|
||||
def _at_abf_alt_lohnsteuer(self, result_rules=None):
|
||||
"""Zwingend günstigere Steuer aus Vervielfachung und 6 %."""
|
||||
self.ensure_one()
|
||||
if self._at_abf_alt_betrag(result_rules) <= 0:
|
||||
return 0.0
|
||||
return min(self._at_abf_alt_steuer_vervielfachung(result_rules),
|
||||
self._at_abf_alt_steuer_6(result_rules))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Urlaubsersatzleistung — § 67 Abs 8 lit d, lb-url-15/16
|
||||
# ------------------------------------------------------------------
|
||||
@@ -238,7 +335,8 @@ class HrPayslip(models.Model):
|
||||
+ self._l10n_at_brutto('sonstig', result_rules)
|
||||
- self._l10n_at_st_frei_freie_laufen(result_rules))
|
||||
for rule in self.struct_id.rule_ids:
|
||||
if rule.l10n_at_s67_abs in ('abs3', 'abs6'):
|
||||
if (rule.l10n_at_bemessung in ('laufend', 'sonstig')
|
||||
and 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:
|
||||
|
||||
@@ -351,7 +351,8 @@ class HrPayslip(models.Model):
|
||||
+ self._l10n_at_brutto('sonstig', result_rules)
|
||||
- self._l10n_at_st_frei_freie_laufen(result_rules))
|
||||
for rule in self.struct_id.rule_ids:
|
||||
if rule.l10n_at_s67_abs in ('abs3', 'abs6'):
|
||||
if (rule.l10n_at_bemessung in ('laufend', 'sonstig')
|
||||
and 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:
|
||||
|
||||
@@ -322,7 +322,7 @@ class HrPayslip(models.Model):
|
||||
# ------------------------------------------------------------------
|
||||
def _at_pfa_rule_amount(self, result_rules, code):
|
||||
if result_rules is not None:
|
||||
werte = result_rules.get(code)
|
||||
werte = result_rules[code] if code in result_rules else None
|
||||
# result_rules enthält ungerundete Rule-Summen; die
|
||||
# Bezugsart ist der gerundete Zeilenbetrag (Cents) —
|
||||
# mit diesem wird auch die Pfändungsberechnungsgrundlage
|
||||
@@ -378,14 +378,16 @@ class HrPayslip(models.Model):
|
||||
if not rule.l10n_at_pfandung_beendigung:
|
||||
continue
|
||||
if result_rules is not None:
|
||||
werte = result_rules.get(rule.code)
|
||||
werte = result_rules[rule.code] \
|
||||
if rule.code in result_rules else None
|
||||
if werte:
|
||||
total += float(werte['total'])
|
||||
else:
|
||||
linie = self.line_ids.filtered(
|
||||
lambda l, c=rule.code: l.code == c)
|
||||
total += sum(linie.mapped('total'))
|
||||
return round(max(0.0, total), 2)
|
||||
steuer = self._at_pfa_rule_amount(result_rules, 'LST_ABF')
|
||||
return round(max(0.0, total - steuer), 2)
|
||||
raise UserError('Unbekannter Pfändungstopf: %s' % topf)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
@@ -420,6 +422,7 @@ class HrPayslip(models.Model):
|
||||
total = self._at_pfaendung_masse(result_rules, 'laufend')
|
||||
total += self._at_pfaendung_masse(result_rules, 'sz13')
|
||||
total += self._at_pfaendung_masse(result_rules, 'sz14')
|
||||
total += self._at_pfaendung_masse(result_rules, 'beendigung')
|
||||
return round(total, 2)
|
||||
|
||||
def _at_pfaendung_kostenersatz(self, result_rules):
|
||||
|
||||
Reference in New Issue
Block a user