Files
odoo-at-payroll/addons/l10n_at_hr_payroll_private/models/sachbezuege_private.py
T

225 lines
12 KiB
Python

# Part of the odoo-at-payroll project. License: LGPL-3.
"""AP12b: wertgebundene Sachbezüge auf dem Dienstverhältnis.
Ein Fahrzeug bzw. eine Wohnung je Version ist bewusst MVP-Grenze. Wechsel,
Pool-/Mehrfachfahrzeuge, Mini-Sachbezug und Kleinwohnungs-Retroaktivität
bleiben dokumentierte Folgefälle (lb-sac-03/04/09/18/15/08).
"""
from dateutil.relativedelta import relativedelta
from odoo import fields, models
BUNDESLAENDER = [
('burgenland', 'Burgenland'), ('kaernten', 'Kärnten'),
('niederoesterreich', 'Niederösterreich'),
('oberoesterreich', 'Oberösterreich'), ('salzburg', 'Salzburg'),
('steiermark', 'Steiermark'), ('tirol', 'Tirol'),
('vorarlberg', 'Vorarlberg'), ('wien', 'Wien'),
]
class HrVersion(models.Model):
_inherit = 'hr.version'
l10n_at_sb_wagen_aktiv = fields.Boolean(
string='AT Dienstwagen privat nutzbar', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wagen_ak = fields.Monetary(
string='AT Dienstwagen Anschaffungskosten', currency_field='currency_id',
tracking=True, groups='hr_payroll.group_hr_payroll_user',
help='Maßgebliche AK inkl. USt/NoVA nach § 4 SBWVO; bei '
'Gebrauchtwagen historischer Neupreis (lb-sac-03).')
l10n_at_sb_wagen_erstzulassung = fields.Date(
string='AT Dienstwagen Erstzulassung', tracking=True,
groups='hr_payroll.group_hr_payroll_user',
help='Bestimmt den CO₂-Grenzwert; bei Gebrauchtwagen ist das '
'Erstzulassungsjahr maßgeblich (lb-sac-03).')
l10n_at_sb_wagen_co2 = fields.Float(
string='AT Dienstwagen CO₂ (g/km)', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wagen_halb = fields.Boolean(
string='AT Dienstwagen halber Sachbezug', tracking=True,
groups='hr_payroll.group_hr_payroll_user',
help='Nachweislich höchstens 500 Privat-km/Monat bzw. 6.000/Jahr; '
'Nachweis/Fahrtenbuch durch Arbeitgeber prüfen (lb-sac-03).')
l10n_at_sb_wagen_kostenbeitrag = fields.Monetary(
string='AT Dienstwagen Kostenbeitrag monatlich', currency_field='currency_id',
tracking=True, groups='hr_payroll.group_hr_payroll_user',
help='Laufender DN-Kostenbeitrag; mindert nach § 4 Abs 7 SBWVO '
'den Sachbezugswert (nicht einzelne Betriebskosten).')
l10n_at_sb_wohnung_aktiv = fields.Boolean(
string='AT Dienstwohnung überlassen', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_flaeche = fields.Float(
string='AT Dienstwohnung Fläche (m²)', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_bundesland = fields.Selection(
BUNDESLAENDER, string='AT Dienstwohnung Bundesland', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_norm = fields.Boolean(
string='AT Dienstwohnung Normwohnung', default=True, tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_besorger = fields.Boolean(
string='AT Dienstwohnung Hausbesorger/Betreuer', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_arbeitsplatznah = fields.Boolean(
string='AT Dienstwohnung arbeitsplatznah (≤ 15 Min.)', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_kein_mittelpunkt = fields.Boolean(
string='AT Dienstwohnung nicht Mittelpunkt Lebensinteressen', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_ueberlassung_ab = fields.Date(
string='AT Dienstwohnung überlassen ab', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_kostenbeitrag = fields.Monetary(
string='AT Dienstwohnung Kostenbeitrag monatlich', currency_field='currency_id',
tracking=True, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_parkplatz_aktiv = fields.Boolean(
string='AT Parkplatz in Kurzparkzone berechtigt', tracking=True,
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_parkplatz_ausnahme = fields.Boolean(
string='AT Parkplatz sachbezugsbefreit', tracking=True,
groups='hr_payroll.group_hr_payroll_user',
help='Nachtdienst ohne Gebührenpflicht, Behinderung mit Pauschbetrag '
'oder kontrollierter Verzicht/Nichtparken (lb-sac-18).')
l10n_at_sb_parkplatz_kostenbeitrag = fields.Monetary(
string='AT Parkplatz Kostenbeitrag monatlich', currency_field='currency_id',
tracking=True, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_handy_profil = fields.Selection(
[('beruflich', 'Beruflich/fallweise privat (kein Sachbezug)'),
('ueberwiegend_privat', 'Überwiegend privat (tatsächliche Kosten)'),
('private_ueberlassung', 'Private Überlassung (Rabatt-Regime)')],
string='AT Handy-/Arbeitsmittel-Nutzungsprofil', default='beruflich',
tracking=True, groups='hr_payroll.group_hr_payroll_user')
def _l10n_at_sb_wagen_wert(self, datum):
self.ensure_one()
if not (self.l10n_at_sb_wagen_aktiv and self.l10n_at_sb_wagen_ak):
return 0.0
co2 = self.l10n_at_sb_wagen_co2
if co2 == 0.0:
return 0.0
werte = self.env['hr.rule.parameter']._get_parameter_from_code(
'at_sb_wagen', datum, raise_if_not_found=False) or {}
grenzen = self.env['hr.rule.parameter']._get_parameter_from_code(
'at_sb_wagen_co2', datum, raise_if_not_found=False) or {}
ez_jahr = (self.l10n_at_sb_wagen_erstzulassung or datum).year
grenze = float(grenzen.get('ab_2025' if ez_jahr >= 2025
else str(ez_jahr),
grenzen.get('vor_2016', 0.0)))
niedrig = bool(grenze and co2 <= grenze)
art = 'niedrig' if niedrig else 'hoch'
prefix = 'halb' if self.l10n_at_sb_wagen_halb else 'voll'
wert = self.l10n_at_sb_wagen_ak * float(
werte.get('%s_%s_satz' % (prefix, art), 0.0)) / 100.0
wert = min(wert, float(werte.get('%s_%s_cap' % (prefix, art), 0.0)))
return max(wert - self.l10n_at_sb_wagen_kostenbeitrag, 0.0)
def _l10n_at_sb_wohnung_wert(self, datum):
self.ensure_one()
if not (self.l10n_at_sb_wohnung_aktiv
and self.l10n_at_sb_wohnung_flaeche
and self.l10n_at_sb_wohnung_bundesland):
return 0.0
werte = self.env['hr.rule.parameter']._get_parameter_from_code(
'at_sb_wohnung', datum, raise_if_not_found=False) or {}
flaeche = self.l10n_at_sb_wohnung_flaeche
klein = (self.l10n_at_sb_wohnung_arbeitsplatznah
and self.l10n_at_sb_wohnung_kein_mittelpunkt)
if klein and flaeche <= float(werte.get('klein_frei_m2', 0.0)):
return 0.0
wert = flaeche * float(werte.get(
self.l10n_at_sb_wohnung_bundesland, 0.0))
if (not self.l10n_at_sb_wohnung_norm
and self.l10n_at_sb_wohnung_besorger):
wert *= 1.0 - float(werte.get('kombiniert_abschlag', 0.0))
elif not self.l10n_at_sb_wohnung_norm:
wert *= 1.0 - float(werte.get('nicht_norm_abschlag', 0.0))
elif self.l10n_at_sb_wohnung_besorger:
wert *= 1.0 - float(werte.get('besorger_abschlag', 0.0))
if (klein and flaeche <= float(werte.get('klein_abschlag_bis_m2', 0.0))
and self.l10n_at_sb_wohnung_ueberlassung_ab
and datum < self.l10n_at_sb_wohnung_ueberlassung_ab
+ relativedelta(months=12)):
wert *= 1.0 - float(werte.get('klein_abschlag', 0.0))
return max(wert - self.l10n_at_sb_wohnung_kostenbeitrag, 0.0)
def _l10n_at_sb_parkplatz_wert(self, datum):
self.ensure_one()
if not (self.l10n_at_sb_parkplatz_aktiv
and not self.l10n_at_sb_parkplatz_ausnahme):
return 0.0
wert = float(self.env['hr.rule.parameter']._get_parameter_from_code(
'at_sb_parkplatz', datum, raise_if_not_found=False) or 0.0)
return max(wert - self.l10n_at_sb_parkplatz_kostenbeitrag, 0.0)
class HrEmployee(models.Model):
_inherit = 'hr.employee'
l10n_at_sb_wagen_aktiv = fields.Boolean(
related='version_id.l10n_at_sb_wagen_aktiv', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wagen_ak = fields.Monetary(
related='version_id.l10n_at_sb_wagen_ak', inherited=True,
readonly=False, currency_field='currency_id',
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wagen_erstzulassung = fields.Date(
related='version_id.l10n_at_sb_wagen_erstzulassung', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wagen_co2 = fields.Float(
related='version_id.l10n_at_sb_wagen_co2', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wagen_halb = fields.Boolean(
related='version_id.l10n_at_sb_wagen_halb', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wagen_kostenbeitrag = fields.Monetary(
related='version_id.l10n_at_sb_wagen_kostenbeitrag', inherited=True,
readonly=False, currency_field='currency_id',
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_aktiv = fields.Boolean(
related='version_id.l10n_at_sb_wohnung_aktiv', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_flaeche = fields.Float(
related='version_id.l10n_at_sb_wohnung_flaeche', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_bundesland = fields.Selection(
related='version_id.l10n_at_sb_wohnung_bundesland', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_norm = fields.Boolean(
related='version_id.l10n_at_sb_wohnung_norm', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_besorger = fields.Boolean(
related='version_id.l10n_at_sb_wohnung_besorger', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_arbeitsplatznah = fields.Boolean(
related='version_id.l10n_at_sb_wohnung_arbeitsplatznah', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_kein_mittelpunkt = fields.Boolean(
related='version_id.l10n_at_sb_wohnung_kein_mittelpunkt', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_ueberlassung_ab = fields.Date(
related='version_id.l10n_at_sb_wohnung_ueberlassung_ab', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_wohnung_kostenbeitrag = fields.Monetary(
related='version_id.l10n_at_sb_wohnung_kostenbeitrag', inherited=True,
readonly=False, currency_field='currency_id',
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_parkplatz_aktiv = fields.Boolean(
related='version_id.l10n_at_sb_parkplatz_aktiv', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_parkplatz_ausnahme = fields.Boolean(
related='version_id.l10n_at_sb_parkplatz_ausnahme', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_parkplatz_kostenbeitrag = fields.Monetary(
related='version_id.l10n_at_sb_parkplatz_kostenbeitrag', inherited=True,
readonly=False, currency_field='currency_id',
groups='hr_payroll.group_hr_payroll_user')
l10n_at_sb_handy_profil = fields.Selection(
related='version_id.l10n_at_sb_handy_profil', inherited=True,
readonly=False, groups='hr_payroll.group_hr_payroll_user')