4b86bcb790
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)
495 lines
25 KiB
Python
495 lines
25 KiB
Python
# Part of the odoo-at-payroll project. License: LGPL-3.
|
|
"""AP14-A: Endabrechnungs-Wizard — sammelt die offenen Posten der
|
|
Beendigungs-Abrechnung (Urlaubsersatzleistung, Abgangsentschädigung,
|
|
Zeitguthaben/-schulden, offene Vorschüsse) und legt den
|
|
Endabrechnungs-Lauf mit vorbefüllten Eingaben an. Reiner
|
|
Sammel-/Anlageprozess; die BV-Anwartschaft läuft über den eigenen
|
|
BV-Wizard (GP5), die Pfändung über die AP11-Maschine."""
|
|
from datetime import timedelta
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class L10nAtEndabrechnungWizard(models.TransientModel):
|
|
_name = 'l10n.at.payroll.endabrechnung.wizard'
|
|
_description = 'Endabrechnung (Beendigung des Dienstverhältnisses)'
|
|
|
|
employee_id = fields.Many2one(
|
|
'hr.employee', string='Dienstnehmer:in', required=True)
|
|
austrittsdatum = fields.Date(
|
|
string='Austritt (Ende des Arbeitsverhältnisses)', required=True)
|
|
departure_reason_id = fields.Many2one(
|
|
'hr.departure.reason', string='Abgangsgrund', required=True,
|
|
domain="['|', ('country_id', '=', False), ('country_id.code', '=', 'AT')]",
|
|
help='Odoo-Abgangsgrund des Beschäftigtendatensatzes; die '
|
|
'Abfertigungsberechtigung wird zusätzlich ausdrücklich bestätigt.')
|
|
uel_tage = fields.Float(
|
|
string='Offene Urlaubstage (Arbeitstage)',
|
|
help='Resturlaub früherer Urlaubsjahre zur Gänze plus aliquoter '
|
|
'Anspruch des laufenden Urlaubsjahres abzüglich verbrauchter '
|
|
'Tage, ohne Rundung (§ 10 UrlG, lb-url-16). Für '
|
|
'unberechtigten vorzeitigen Austritt sind die Tage der 5. '
|
|
'und 6. Urlaubswoche des laufenden Jahres herauszurechnen.')
|
|
abgang_betrag = fields.Monetary(
|
|
string='Abgangsentschädigung (Brutto, § 67 Abs 8 lit b EStG)',
|
|
currency_field='currency_id',
|
|
help='Entschädigung für den Verzicht auf die Arbeitsleistung '
|
|
'während der (fiktiven) Kündigungsfrist — LSt: Fünftelregelung; '
|
|
'SV: Umlegung auf den Kündigungsfrist-Zeitraum (§ 11 Abs 2 '
|
|
'ASVG); voll lohnnebenkostenpflichtig.')
|
|
abgang_ffrist_tage = fields.Float(
|
|
string='Kündigungsfrist (Kalendertage)',
|
|
help='Kalendertage der (fiktiven) Kündigungsfrist, auf die die '
|
|
'pauschalierte Abgangsentschädigung sv-rechtlich umzulegen '
|
|
'ist (§ 11 Abs 2 ASVG).')
|
|
zeit_guthaben_stunden = fields.Float(
|
|
string='Zeitguthaben an Normalarbeitszeit (Stunden)',
|
|
help='Offenes Guthaben an Normalarbeitszeit aus durchrechenbarem '
|
|
'Arbeitszeitmodell — Abgeltung mit 50 % Zuschlag (§ 19e '
|
|
'Abs 2 AZG); bei unberechtigtem vorzeitigem Austritt kein '
|
|
'Zuschlag.')
|
|
zeit_schulden_stunden = fields.Float(
|
|
string='Zeitschulden (Stunden)',
|
|
help='Offene Zeitschulden (negative Zeitguthaben), abgerechnet '
|
|
'mit der aktuellen Normalstunde (lb-end-08).')
|
|
vorschuss_saldo = fields.Monetary(
|
|
string='Offener Vorschuss-/Darlehenssaldo',
|
|
currency_field='currency_id',
|
|
help='Bei Beendigung zur Gänze fälliger, noch offener '
|
|
'Vorschusssaldo (lb-end-06) — Rückverrechnung vom Netto '
|
|
'nach SV und Lohnsteuer, ohne Abgabenberührung '
|
|
'(§ 293 Abs 3 EO).')
|
|
abf_alt_aktiv = fields.Boolean(string='Gesetzliche Abfertigung Alt')
|
|
abf_alt_anspruch_bestaetigt = fields.Boolean(
|
|
string='Anspruch und Nachweise geprüft',
|
|
help='Bestätigung, dass Alt-Anwartschaft, Beendigungsgrund, '
|
|
'Dienstzeiten und Bemessungsgrundlage geprüft wurden.')
|
|
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='Anspruchsart', default='normal')
|
|
abf_alt_dienstzeit_monate = fields.Integer(
|
|
string='Nachgewiesene Abfertigungsdienstzeit (Monate)')
|
|
abf_alt_monatsentgelt = fields.Monetary(
|
|
string='Maßgebliches Monatsentgelt', currency_field='currency_id',
|
|
help='Bestätigte arbeitsrechtliche Bemessungsgrundlage: letzter '
|
|
'Monat einschließlich regelmäßiger Bezugsteile, Sachbezüge '
|
|
'und aliquoter Sonderzahlungen.')
|
|
abf_alt_laufender_arbeitslohn = fields.Monetary(
|
|
string='Laufender Monatsarbeitslohn (§ 67 Abs 3)',
|
|
currency_field='currency_id',
|
|
help='Laufender Arbeitslohn für den steuerlichen Vervielfacher; '
|
|
'aliquote Sonderzahlungen gehören hier nicht dazu.')
|
|
abf_alt_monatslohnsteuer = fields.Monetary(
|
|
string='Tarif-LSt des laufenden Monats', currency_field='currency_id',
|
|
help='Die auf den maßgeblichen laufenden Monatsarbeitslohn '
|
|
'entfallende tarifmäßige Lohnsteuer nach den persönlichen '
|
|
'Verhältnissen. Bei steuerfreiem Monatslohn ausdrücklich 0 '
|
|
'bestätigen.')
|
|
abf_alt_mehrfach = fields.Float(
|
|
string='Bestätigter Anspruchsfaktor',
|
|
help='§-23-Staffel, gegebenenfalls halbiert/gedeckelt oder als '
|
|
'eingefrorener beziehungsweise nachgewiesener Faktor.')
|
|
abf_alt_nachweis = fields.Text(
|
|
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)
|
|
|
|
uel_lfd_vorschau = fields.Monetary(
|
|
string='UEL laufender Anteil (Vorschau)',
|
|
currency_field='currency_id', compute='_compute_vorschau')
|
|
uel_sz_vorschau = fields.Monetary(
|
|
string='UEL Sonderzahlungsanteil (Vorschau)',
|
|
currency_field='currency_id', compute='_compute_vorschau')
|
|
sv_tage_vorschau = fields.Integer(
|
|
string='SV-Verlängerungstage (§ 11 Abs 2)',
|
|
compute='_compute_vorschau')
|
|
abf_alt_betrag_vorschau = fields.Monetary(
|
|
string='Abfertigung Alt brutto', currency_field='currency_id',
|
|
compute='_compute_vorschau')
|
|
abf_alt_steuer_vervielfachung_vorschau = fields.Monetary(
|
|
string='LSt Vervielfachungsmethode', currency_field='currency_id',
|
|
compute='_compute_vorschau')
|
|
abf_alt_steuer_6_vorschau = fields.Monetary(
|
|
string='LSt 6 %', currency_field='currency_id',
|
|
compute='_compute_vorschau')
|
|
abf_alt_lohnsteuer_vorschau = fields.Monetary(
|
|
string='Angewendete günstigere LSt', currency_field='currency_id',
|
|
compute='_compute_vorschau')
|
|
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):
|
|
for wizard in self:
|
|
if not wizard.employee_id:
|
|
continue
|
|
version = wizard.employee_id.version_id
|
|
wizard.austrittsdatum = (
|
|
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_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()
|
|
if not self.employee_id or not self.austrittsdatum:
|
|
return
|
|
version = self.employee_id.version_id
|
|
start = version.contract_date_start
|
|
if start and not self.abf_alt_dienstzeit_monate:
|
|
dauer = relativedelta(
|
|
self.austrittsdatum + timedelta(days=1), start)
|
|
self.abf_alt_dienstzeit_monate = dauer.years * 12 + dauer.months
|
|
slip = self._vorschau_payslip()
|
|
if not self.abf_alt_laufender_arbeitslohn:
|
|
self.abf_alt_laufender_arbeitslohn = slip._at_kv_gehalt_basis()
|
|
if not self.abf_alt_monatsentgelt:
|
|
self.abf_alt_monatsentgelt = (
|
|
self.abf_alt_laufender_arbeitslohn
|
|
+ 2.0 * slip._at_sz_basis(self.austrittsdatum) / 12.0)
|
|
vorgeschlagen = slip._at_abf_alt_mehrfach_vorschlag(
|
|
self.abf_alt_dienstzeit_monate, self.abf_alt_anspruchsart)
|
|
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_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
|
|
wizard.uel_sz_vorschau = 0.0
|
|
wizard.sv_tage_vorschau = 0
|
|
wizard.abf_alt_betrag_vorschau = 0.0
|
|
wizard.abf_alt_steuer_vervielfachung_vorschau = 0.0
|
|
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()
|
|
wizard.uel_lfd_vorschau = slip._at_uel_lfd()
|
|
wizard.uel_sz_vorschau = slip._at_uel_sz()
|
|
wizard.sv_tage_vorschau = slip._at_end_sv_tage(
|
|
wizard.uel_tage)
|
|
if wizard.abf_alt_aktiv:
|
|
betrag = slip._at_abf_alt_betrag()
|
|
steuer_vervielfachung = \
|
|
slip._at_abf_alt_steuer_vervielfachung()
|
|
steuer_6 = slip._at_abf_alt_steuer_6()
|
|
steuer = min(steuer_vervielfachung, steuer_6)
|
|
wizard.abf_alt_betrag_vorschau = betrag
|
|
wizard.abf_alt_steuer_vervielfachung_vorschau = \
|
|
steuer_vervielfachung
|
|
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
|
|
Speichern): trägt Austrittsmonat, Struktur und die Eingaben."""
|
|
self.ensure_one()
|
|
erster = self.austrittsdatum.replace(day=1)
|
|
letzter = (erster + timedelta(days=32)).replace(day=1) \
|
|
- timedelta(days=1)
|
|
struct = self.employee_id.version_id.structure_id
|
|
if not struct:
|
|
struct = self.env.ref(
|
|
'l10n_at_hr_payroll_private.structure_at_privat')
|
|
slip = self.env['hr.payslip'].new({
|
|
'employee_id': self.employee_id.id,
|
|
'struct_id': struct.id,
|
|
'date_from': erster,
|
|
'date_to': letzter,
|
|
'l10n_at_abf_alt_anspruchsart': self.abf_alt_anspruchsart,
|
|
'l10n_at_abf_alt_dienstzeit_monate':
|
|
self.abf_alt_dienstzeit_monate,
|
|
'l10n_at_abf_alt_monatsentgelt': self.abf_alt_monatsentgelt,
|
|
'l10n_at_abf_alt_laufender_arbeitslohn':
|
|
self.abf_alt_laufender_arbeitslohn,
|
|
'l10n_at_abf_alt_monatslohnsteuer':
|
|
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, {
|
|
'input_type_id': self.env['hr.payslip.input.type']
|
|
.search([('code', '=', code)], limit=1).id,
|
|
'amount': betrag,
|
|
})
|
|
for code, betrag in eingaben if betrag
|
|
]
|
|
return slip
|
|
|
|
def _eingaben(self):
|
|
self.ensure_one()
|
|
return [
|
|
('ATP_UEL_TAGE', self.uel_tage),
|
|
('ATP_ABGANG', self.abgang_betrag),
|
|
('ATP_ABGANG_FFRIST_TAGE', self.abgang_ffrist_tage),
|
|
('ATP_ZEIT_GUTHABEN', self.zeit_guthaben_stunden),
|
|
('ATP_ZEIT_SCHULDEN', self.zeit_schulden_stunden),
|
|
('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):
|
|
self.ensure_one()
|
|
if not self.abf_alt_aktiv:
|
|
return
|
|
if not self.abf_alt_anspruch_bestaetigt:
|
|
raise UserError(_('Bitte Anspruch und Nachweise der '
|
|
'Abfertigung Alt bestätigen.'))
|
|
if self.employee_id.version_id.l10n_at_abfertigung_neu \
|
|
and self.abf_alt_anspruchsart != 'eingefroren':
|
|
raise UserError(_(
|
|
'Das Dienstverhältnis ist als Abfertigung Neu markiert. '
|
|
'Eine Alt-Abfertigung ist nur als nachgewiesener '
|
|
'eingefrorener Anspruch zulässig.'))
|
|
if self.abf_alt_anspruchsart == 'eltern' \
|
|
and self.abf_alt_dienstzeit_monate < 60:
|
|
raise UserError(_(
|
|
'Ein Elternaustritt nach § 23a Abs. 3/4 AngG setzt ein '
|
|
'ununterbrochenes Dienstverhältnis von fünf Jahren voraus.'))
|
|
if (self.abf_alt_dienstzeit_monate <= 0
|
|
or self.abf_alt_monatsentgelt <= 0
|
|
or self.abf_alt_laufender_arbeitslohn <= 0
|
|
or self.abf_alt_monatslohnsteuer < 0
|
|
or self.abf_alt_mehrfach <= 0):
|
|
raise UserError(_('Dienstzeit, Monatsentgelt, laufender '
|
|
'Arbeitslohn und Anspruchsfaktor müssen '
|
|
'größer als null sein; die Tarif-LSt darf '
|
|
'nicht negativ sein.'))
|
|
agrd = self.departure_reason_id.l10n_at_agrd
|
|
if agrd == '02' and self.abf_alt_anspruchsart not in (
|
|
'eltern', 'pension', 'manuell'):
|
|
raise UserError(_(
|
|
'Eine gewöhnliche Arbeitnehmerkündigung begründet keinen '
|
|
'Anspruch nach § 23 AngG. Bitte einen §-23a-Sonderfall '
|
|
'wählen oder den Anspruch manuell nachweisen.'))
|
|
if agrd == '06' and self.abf_alt_anspruchsart != 'manuell':
|
|
raise UserError(_(
|
|
'Der Abgangsgrund „Fristlose Entlassung“ unterscheidet '
|
|
'nicht zwischen verschuldeter und unverschuldeter '
|
|
'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)
|
|
version = self.employee_id.version_id
|
|
version.write({
|
|
'contract_date_end': self.austrittsdatum,
|
|
'departure_reason_id': self.departure_reason_id.id,
|
|
})
|
|
struct = version.structure_id \
|
|
or self.env.ref('l10n_at_hr_payroll_private.structure_at_privat')
|
|
slip = self.env['hr.payslip'].create({
|
|
'name': _('Endabrechnung %s') % self.employee_id.name,
|
|
'employee_id': self.employee_id.id,
|
|
'struct_id': struct.id,
|
|
'date_from': erster,
|
|
'date_to': letzter,
|
|
'l10n_at_abf_alt_anspruchsart': self.abf_alt_anspruchsart
|
|
if self.abf_alt_aktiv else False,
|
|
'l10n_at_abf_alt_dienstzeit_monate':
|
|
self.abf_alt_dienstzeit_monate if self.abf_alt_aktiv else 0,
|
|
'l10n_at_abf_alt_monatsentgelt':
|
|
self.abf_alt_monatsentgelt if self.abf_alt_aktiv else 0.0,
|
|
'l10n_at_abf_alt_laufender_arbeitslohn':
|
|
self.abf_alt_laufender_arbeitslohn
|
|
if self.abf_alt_aktiv else 0.0,
|
|
'l10n_at_abf_alt_monatslohnsteuer':
|
|
self.abf_alt_monatslohnsteuer if self.abf_alt_aktiv else 0.0,
|
|
'l10n_at_abf_alt_mehrfach':
|
|
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)
|
|
for code, _betrag in self._eingaben()}
|
|
self.env['hr.payslip.input'].create([{
|
|
'payslip_id': slip.id,
|
|
'input_type_id': typen[code].id,
|
|
'amount': betrag,
|
|
} for code, betrag in self._eingaben() if betrag])
|
|
slip.compute_sheet()
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Endabrechnung'),
|
|
'res_model': 'hr.payslip',
|
|
'view_mode': 'form',
|
|
'res_id': slip.id,
|
|
} |