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 voluntary severance under § 67 Abs 6 (AP15-B)
Split the voluntary severance into its privileged part and a tariff remainder on the exit run: the privileged part combines the quarter rule (1/4 of the last twelve months' running pay, capped at nine times the monthly HBG) with the twelfth rule (2/12 to 12/12 by proven service, capped at n × 3 × HBG), reduced per Z 3 by severance already received and the statutory claim due at this termination, all taxed at the flat 6 % rate. The excess runs as its own rule flagged l10n_at_s67_abs6_ueberhang: taxed with the running tariff of the payment month but excluded from the annual sixth, since Z 5 exempts only the Z 1/Z 2 amounts and the excess is a special payment, not running pay. The twelve-month basis aggregates validated prior runs plus own lines, excluding the flagged excess and § 26 Z 4 travel overhang via a dedicated rule flag. Free of SV (§ 49 Abs 3 Z 7 ASVG), payroll levies regardless of the 6 %/tarif split (§ 41 Abs 4 lit b FLAG, § 122 Abs 8 WKG, § 5 Abs 2 lit b KommStG) and BV contributions; the former BV-Anwartschaft exclusion Z 7 is repealed (BGBl I 118/2015). The wizard proposes the rolling basis and the statutory claim, previews Z 1/Z 2/reduction/privileged/excess/tax and requires explicit confirmation against claim-conversion risk. The § 291d EO termination pot nets both severance wage-tax rules; key 260 now includes LST_ABF_FREI. Verified against the original statute text in .ris/ (EStG § 67 Abs 6) and the knowledge-base sources lb-end-12/13/15; KZ positioning of Abs-6 amounts and the excess's § 291d pot allocation remain documented verification points against LStR Rz 1087 ff. Version 19.0.14.0.0 (private), 19.0.10.0.0 (core)
This commit is contained in:
@@ -101,6 +101,43 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
string='Nachweis/Begründung',
|
||||
help='Quelle der Dienstzeiten, Anspruchsprüfung, Alt-/Neu-Status '
|
||||
'und allfällige manuelle Abweichung dokumentieren.')
|
||||
abf_frei_aktiv = fields.Boolean(
|
||||
string='Freiwillige Abfertigung (§ 67 Abs 6)')
|
||||
abf_frei_anspruch_bestaetigt = fields.Boolean(
|
||||
string='Prüfung und Nachweise bestätigt',
|
||||
help='Bestätigung, dass es sich um eine Beendigungsleistung ohne '
|
||||
'schädliche Anspruchsumwandlung handelt (KE/UE/SZ/Zeitguthaben '
|
||||
'müssen getrennt abrechnet werden — GPLB-Risiko, lb-end-15), '
|
||||
'dass die (Vor-)Dienstzeiten lückenlos zum Lohnkonto '
|
||||
'(§ 76 EStG) nachgewiesen sind und erhaltene Abfertigungen '
|
||||
'angegeben wurden.')
|
||||
abf_frei_betrag = fields.Monetary(
|
||||
string='Bruttobetrag', currency_field='currency_id')
|
||||
abf_frei_basis_12 = fields.Monetary(
|
||||
string='Laufende Bezüge letzte 12 Monate',
|
||||
currency_field='currency_id',
|
||||
help='Basis der Viertel-/Zwölftelregelung: alle steuerbaren '
|
||||
'Bezugsteile (auch steuerfreie Zuschläge, Sachbezüge), '
|
||||
'ohne Sonderzahlungen und ohne §-26-Z-4-Reisevergütungen; '
|
||||
'wird aus den letzten zwölf validierten Läufen vorgeschlagen '
|
||||
'und ist bestätigbar (lb-end-13).')
|
||||
abf_frei_dienstzeit_monate = fields.Integer(
|
||||
string='Nachgewiesene Dienstzeit (Monate)')
|
||||
abf_frei_erhaltene_abfertigungen = fields.Monetary(
|
||||
string='Bereits erhaltene Abfertigungen', currency_field='currency_id',
|
||||
help='In den nachgewiesenen Dienstzeiten erhaltene Abfertigungen '
|
||||
'(§ 67 Abs 3 oder Abs 6 EStG) — Kürzung nach Z 3.')
|
||||
abf_frei_gesetzlicher_anspruch = fields.Monetary(
|
||||
string='Bestehender gesetzlicher Anspruch',
|
||||
currency_field='currency_id',
|
||||
help='Anspruch auf eine gesetzliche Abfertigung am aktuellen '
|
||||
'Dienstverhältnis-Ende (Z 3); bei aktiver Alt-Abfertigung '
|
||||
'automatisch aus dem Alt-Anspruch vorgeschlagen.')
|
||||
abf_frei_nachweis = fields.Text(
|
||||
string='Nachweis/Begründung',
|
||||
help='Vordienstzeiten-Nachweis (Lohnkonto § 76 EStG), erhaltene '
|
||||
'Abfertigungen, Basis-Abweichungen und Anspruchsgrundlage '
|
||||
'dokumentieren.')
|
||||
currency_id = fields.Many2one(
|
||||
'res.currency', default=lambda self: self.env.company.currency_id)
|
||||
|
||||
@@ -128,6 +165,27 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
abf_alt_netto_vorschau = fields.Monetary(
|
||||
string='Abfertigung Alt netto', currency_field='currency_id',
|
||||
compute='_compute_vorschau')
|
||||
abf_frei_z1_vorschau = fields.Monetary(
|
||||
string='Z 1 Viertelregelung (Vorschau)', currency_field='currency_id',
|
||||
compute='_compute_vorschau')
|
||||
abf_frei_z2_vorschau = fields.Monetary(
|
||||
string='Z 2 Zwölftelregelung (Vorschau)', currency_field='currency_id',
|
||||
compute='_compute_vorschau')
|
||||
abf_frei_kuerzung_vorschau = fields.Monetary(
|
||||
string='Z 3 Kürzung (Vorschau)', currency_field='currency_id',
|
||||
compute='_compute_vorschau')
|
||||
abf_frei_beguenstigt_vorschau = fields.Monetary(
|
||||
string='Begünstigter Teil 6 % (Vorschau)', currency_field='currency_id',
|
||||
compute='_compute_vorschau')
|
||||
abf_frei_ueberhang_vorschau = fields.Monetary(
|
||||
string='Überhang zum Tarif (Vorschau)', currency_field='currency_id',
|
||||
compute='_compute_vorschau')
|
||||
abf_frei_lst_vorschau = fields.Monetary(
|
||||
string='LSt 6 % (Vorschau)', currency_field='currency_id',
|
||||
compute='_compute_vorschau')
|
||||
abf_frei_netto_vorschau = fields.Monetary(
|
||||
string='Begünstigter Teil netto (Vorschau)',
|
||||
currency_field='currency_id', compute='_compute_vorschau')
|
||||
|
||||
@api.onchange('employee_id')
|
||||
def _onchange_employee(self):
|
||||
@@ -139,12 +197,16 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
version.contract_date_end or fields.Date.today())
|
||||
wizard.departure_reason_id = version.departure_reason_id
|
||||
wizard._at_abf_alt_vorschlag_setzen()
|
||||
wizard._at_abf_frei_vorschlag_setzen()
|
||||
|
||||
@api.onchange('austrittsdatum', 'abf_alt_anspruchsart',
|
||||
'abf_alt_dienstzeit_monate')
|
||||
'abf_alt_dienstzeit_monate', 'abf_alt_aktiv',
|
||||
'abf_alt_monatsentgelt', 'abf_alt_mehrfach',
|
||||
'abf_frei_aktiv', 'abf_frei_dienstzeit_monate')
|
||||
def _onchange_abf_alt(self):
|
||||
for wizard in self:
|
||||
wizard._at_abf_alt_vorschlag_setzen()
|
||||
wizard._at_abf_frei_vorschlag_setzen()
|
||||
|
||||
def _at_abf_alt_vorschlag_setzen(self):
|
||||
self.ensure_one()
|
||||
@@ -168,11 +230,27 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
if vorgeschlagen or not self.abf_alt_mehrfach:
|
||||
self.abf_alt_mehrfach = vorgeschlagen
|
||||
|
||||
def _at_abf_frei_vorschlag_setzen(self):
|
||||
self.ensure_one()
|
||||
if not self.employee_id or not self.austrittsdatum:
|
||||
return
|
||||
slip = self._vorschau_payslip()
|
||||
if self.abf_frei_aktiv and not self.abf_frei_basis_12:
|
||||
self.abf_frei_basis_12 = slip._at_bezuege_12_monate()
|
||||
if (self.abf_frei_aktiv and self.abf_alt_aktiv
|
||||
and not self.abf_frei_gesetzlicher_anspruch):
|
||||
self.abf_frei_gesetzlicher_anspruch = (
|
||||
self.abf_alt_monatsentgelt * self.abf_alt_mehrfach)
|
||||
|
||||
@api.depends('employee_id', 'austrittsdatum', 'uel_tage',
|
||||
'abf_alt_aktiv', 'abf_alt_monatsentgelt',
|
||||
'abf_alt_laufender_arbeitslohn', 'abf_alt_monatslohnsteuer',
|
||||
'abf_alt_mehrfach',
|
||||
'abf_alt_dienstzeit_monate', 'abf_alt_anspruchsart')
|
||||
'abf_alt_dienstzeit_monate', 'abf_alt_anspruchsart',
|
||||
'abf_frei_aktiv', 'abf_frei_betrag', 'abf_frei_basis_12',
|
||||
'abf_frei_dienstzeit_monate',
|
||||
'abf_frei_erhaltene_abfertigungen',
|
||||
'abf_frei_gesetzlicher_anspruch')
|
||||
def _compute_vorschau(self):
|
||||
for wizard in self:
|
||||
wizard.uel_lfd_vorschau = 0.0
|
||||
@@ -183,6 +261,13 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
wizard.abf_alt_steuer_6_vorschau = 0.0
|
||||
wizard.abf_alt_lohnsteuer_vorschau = 0.0
|
||||
wizard.abf_alt_netto_vorschau = 0.0
|
||||
wizard.abf_frei_z1_vorschau = 0.0
|
||||
wizard.abf_frei_z2_vorschau = 0.0
|
||||
wizard.abf_frei_kuerzung_vorschau = 0.0
|
||||
wizard.abf_frei_beguenstigt_vorschau = 0.0
|
||||
wizard.abf_frei_ueberhang_vorschau = 0.0
|
||||
wizard.abf_frei_lst_vorschau = 0.0
|
||||
wizard.abf_frei_netto_vorschau = 0.0
|
||||
if not wizard.employee_id or not wizard.austrittsdatum:
|
||||
continue
|
||||
slip = wizard._vorschau_payslip()
|
||||
@@ -202,6 +287,19 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
wizard.abf_alt_steuer_6_vorschau = steuer_6
|
||||
wizard.abf_alt_lohnsteuer_vorschau = steuer
|
||||
wizard.abf_alt_netto_vorschau = betrag - steuer
|
||||
if wizard.abf_frei_aktiv:
|
||||
split = slip._at_abf_frei_split()
|
||||
satz = float(slip._l10n_at_param(
|
||||
'at_endabrechnung')['abfertigung_steuersatz'])
|
||||
wizard.abf_frei_z1_vorschau = split['z1']
|
||||
wizard.abf_frei_z2_vorschau = split['z2']
|
||||
wizard.abf_frei_kuerzung_vorschau = split['kuerzung']
|
||||
wizard.abf_frei_beguenstigt_vorschau = split['beguenstigt']
|
||||
wizard.abf_frei_ueberhang_vorschau = split['ueberhang']
|
||||
wizard.abf_frei_lst_vorschau = \
|
||||
split['beguenstigt'] * satz / 100.0
|
||||
wizard.abf_frei_netto_vorschau = \
|
||||
split['beguenstigt'] - wizard.abf_frei_lst_vorschau
|
||||
|
||||
def _vorschau_payslip(self):
|
||||
"""Flüchtiger Payslip-Kontext für die Vorschau-Berechnung (kein
|
||||
@@ -229,11 +327,21 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
self.abf_alt_monatslohnsteuer,
|
||||
'l10n_at_abf_alt_mehrfach': self.abf_alt_mehrfach,
|
||||
'l10n_at_abf_alt_nachweis': self.abf_alt_nachweis,
|
||||
'l10n_at_abf_frei_basis_12': self.abf_frei_basis_12,
|
||||
'l10n_at_abf_frei_dienstzeit_monate':
|
||||
self.abf_frei_dienstzeit_monate,
|
||||
'l10n_at_abf_frei_erhaltene_abfertigungen':
|
||||
self.abf_frei_erhaltene_abfertigungen,
|
||||
'l10n_at_abf_frei_gesetzlicher_anspruch':
|
||||
self.abf_frei_gesetzlicher_anspruch,
|
||||
'l10n_at_abf_frei_nachweis': self.abf_frei_nachweis,
|
||||
})
|
||||
eingaben = [
|
||||
('ATP_UEL_TAGE', self.uel_tage),
|
||||
('ATP_ABF_ALT', self.abf_alt_monatsentgelt
|
||||
* self.abf_alt_mehrfach if self.abf_alt_aktiv else 0.0),
|
||||
('ATP_ABF_FREI', self.abf_frei_betrag
|
||||
if self.abf_frei_aktiv else 0.0),
|
||||
]
|
||||
slip.input_line_ids = [
|
||||
(0, 0, {
|
||||
@@ -256,6 +364,8 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
('ATP_ABRECHNUNG_VORSCHUSS', self.vorschuss_saldo),
|
||||
('ATP_ABF_ALT', self.abf_alt_monatsentgelt
|
||||
* self.abf_alt_mehrfach if self.abf_alt_aktiv else 0.0),
|
||||
('ATP_ABF_FREI', self.abf_frei_betrag
|
||||
if self.abf_frei_aktiv else 0.0),
|
||||
]
|
||||
|
||||
def _abf_alt_validieren(self):
|
||||
@@ -299,11 +409,30 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
'Entlassung. Bitte den Anspruch manuell bestätigen und '
|
||||
'begründen.'))
|
||||
|
||||
def _abf_frei_validieren(self):
|
||||
self.ensure_one()
|
||||
if not self.abf_frei_aktiv:
|
||||
return
|
||||
if not self.abf_frei_anspruch_bestaetigt:
|
||||
raise UserError(_('Bitte Prüfung und Nachweise der freiwilligen '
|
||||
'Abfertigung bestätigen.'))
|
||||
if self.abf_frei_betrag <= 0:
|
||||
raise UserError(_('Der Bruttobetrag der freiwilligen '
|
||||
'Abfertigung muss größer als null sein.'))
|
||||
if (self.abf_frei_basis_12 < 0
|
||||
or self.abf_frei_erhaltene_abfertigungen < 0
|
||||
or self.abf_frei_gesetzlicher_anspruch < 0
|
||||
or self.abf_frei_dienstzeit_monate < 0):
|
||||
raise UserError(_('12-Monats-Basis, erhaltene Abfertigungen, '
|
||||
'gesetzlicher Anspruch und Dienstzeit dürfen '
|
||||
'nicht negativ sein.'))
|
||||
|
||||
def action_payslip(self):
|
||||
"""Endabrechnungs-Lauf im Austrittsmonat anlegen und die
|
||||
gesammelten offenen Posten als Eingaben vorbefüllen."""
|
||||
self.ensure_one()
|
||||
self._abf_alt_validieren()
|
||||
self._abf_frei_validieren()
|
||||
erster = self.austrittsdatum.replace(day=1)
|
||||
letzter = (erster + timedelta(days=32)).replace(day=1) \
|
||||
- timedelta(days=1)
|
||||
@@ -335,6 +464,18 @@ class L10nAtEndabrechnungWizard(models.TransientModel):
|
||||
self.abf_alt_mehrfach if self.abf_alt_aktiv else 0.0,
|
||||
'l10n_at_abf_alt_nachweis':
|
||||
self.abf_alt_nachweis if self.abf_alt_aktiv else False,
|
||||
'l10n_at_abf_frei_basis_12':
|
||||
self.abf_frei_basis_12 if self.abf_frei_aktiv else 0.0,
|
||||
'l10n_at_abf_frei_dienstzeit_monate':
|
||||
self.abf_frei_dienstzeit_monate if self.abf_frei_aktiv else 0,
|
||||
'l10n_at_abf_frei_erhaltene_abfertigungen':
|
||||
self.abf_frei_erhaltene_abfertigungen
|
||||
if self.abf_frei_aktiv else 0.0,
|
||||
'l10n_at_abf_frei_gesetzlicher_anspruch':
|
||||
self.abf_frei_gesetzlicher_anspruch
|
||||
if self.abf_frei_aktiv else 0.0,
|
||||
'l10n_at_abf_frei_nachweis':
|
||||
self.abf_frei_nachweis if self.abf_frei_aktiv else False,
|
||||
})
|
||||
typen = {code: self.env['hr.payslip.input.type'].search(
|
||||
[('code', '=', code)], limit=1)
|
||||
|
||||
Reference in New Issue
Block a user