Files
odoo-at-payroll/addons/l10n_at_gemeinde_payroll/models/hr_version_bgld.py
T
fegger 30270f9877 [IMP] l10n_at_gemeinde_payroll: implement AP1 pay scale model (GemBG Bgld.)
Katalogmodell nach Implementierungsplan AP1 (freigegeben 2026-09-09):

- ``gemeinde.payroll.entlohnungsgruppe`` (Code, Schema, §, Bundesland,
  Vorrückungszeitraum je Gruppe; § 66 Abs 2 GemBG: 4 Jahre, abweichend
  2 Jahre für Betreuungspersonen-/Sondergruppen) und
  ``gemeinde.payroll.entlohnungsstufe`` (Stufe, Monatsentgelt, Stichtag,
  unique je Gruppe/Stufe/Stichtag) mit Stichtags-Lookup-Helfern.
- Seed 2026: 35 Entlohnungsgruppen, 433 Werte (Schemata I/gv, II/gh,
  Ia/bv, IIa/bh, kb, av sowie §-Gruppen 150c/151/151c), Werte aus der
  konsolidierten GemBG-Fassung 09.09.2026 (Wert 1.7.2026 gemäß Artikel 4
  RV 0715/XXIII. GP; 2025er-Stichtagsannahme für nicht 2026 angepasste
  Tabellen als AP0-Verifikationspunkt dokumentiert). Generator mit
  Herkunftsnachweis: personalverrechnung/tools/extract_gembg_katalog.py.
- GemBG-Felder auf der Payroll-Version (hr.version) plus Employee-Spiegel
  nach dem Engine-Muster (related/inherited): Entlohnungsgruppe, Stufe,
  Besoldungsdienstalter, Vorrückungstermin — berechnet nach § 66 Abs 2
  (erster Tag des Monats nach Vollendung weiterer n Jahre BDA), manuell
  überschreibbar für Überleitungsfälle (§§ 157a ff).
- Vorrückungs-Wizard (§ 66 Abs 2): fällige Versionen zum Stichtag,
  Stufenerhöhung mit Höchststufen-Schutz und Ergebnis-Notification —
  bewusst kein stilles Mutieren im Lohnlauf (Dokumentationspflicht).
- Views/Menüs (Personalverrechnung Bgld. unter Payroll), Security auf
  hr_payroll-Gruppen, Employee-Form-Anbindung in payroll_group.
- Tests (Rechenfälle AP1): Seed-Werte inkl. Quellenanomalie kb1a/6,
  Stichtags-Lookup, Jahresversionierung, Vorrückungstermin (BDA 15.03.2020
  -> 1.4.2028), Wizard-Anwendung mit Höchststufen-Skip.

Statische Validierung grün (py_compile, XML, Manifest, CSV-Integrität);
Runtime-Testlauf auf dem Dev-Host (gem360_dev) ausständig, wie im
Implementierungsplan M2 vorgesehen.
2026-09-09 11:55:15 +02:00

72 lines
3.2 KiB
Python

# Part of the gem360 onboarding. See LICENSE / project docs for details.
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
class HrVersion(models.Model):
"""GemBG-Besoldungsfelder auf der Payroll-Version des Mitarbeiters.
§ 66 Abs 2 Bgld. GemBG 2014: Die Vorrückung erfolgt mit dem ersten Tag
jenes Monats, der auf die Vollendung weiterer vier Jahre des
Besoldungsdienstalters folgt (Vorrückungstermin); für bestimmte Gruppen
zwei Jahre (§ 150c Abs 2, § 150d ff). Überleitungsfälle (§§ 157a ff)
können einen einmalig vorgezogenen Termin haben — daher ist der
berechnete Termin manuell überschreibbar.
"""
_inherit = 'hr.version'
entlohnungsgruppe_id = fields.Many2one(
'gemeinde.payroll.entlohnungsgruppe', index=True,
groups="hr_payroll.group_hr_payroll_user", tracking=True)
entlohnungsstufe = fields.Integer(
groups="hr_payroll.group_hr_payroll_user", tracking=True)
besoldungsdienstalter = fields.Date(
string='Besoldungsdienstalter (ab)',
groups="hr_payroll.group_hr_payroll_user", tracking=True)
vorrueckungstermin = fields.Date(
compute='_compute_vorrueckungstermin', store=True, readonly=False,
groups="hr_payroll.group_hr_payroll_user", tracking=True,
help="Vorschlag nach § 66 Abs 2 GemBG (BDA + Vorrückungszeitraum); "
"bei Überleitungsfällen manuell korrigierbar.")
@api.depends('entlohnungsgruppe_id', 'besoldungsdienstalter')
def _compute_vorrueckungstermin(self):
for version in self:
bda = version.besoldungsdienstalter
gruppe = version.entlohnungsgruppe_id
if not bda or not gruppe:
version.vorrueckungstermin = False
continue
period = gruppe.vorrueckungszeitraum_jahre or 4
today = fields.Date.context_today(version)
elapsed_years = relativedelta(today, bda).years
next_maturity = bda + relativedelta(
years=(elapsed_years // period + 1) * period)
version.vorrueckungstermin = (
fields.Date.end_of(next_maturity, 'month')
+ relativedelta(days=1)
)
def _get_katalog_entgelt(self, datum=None):
"""Katalog-Position (Monatsentgelt) der Version zum Stichtag."""
self.ensure_one()
return self.entlohnungsgruppe_id._get_entgelt(
self.entlohnungsstufe, datum)
class HrEmployee(models.Model):
_inherit = 'hr.employee'
entlohnungsgruppe_id = fields.Many2one(
related="version_id.entlohnungsgruppe_id", inherited=True,
readonly=False, groups="hr_payroll.group_hr_payroll_user")
entlohnungsstufe = fields.Integer(
related="version_id.entlohnungsstufe", inherited=True,
readonly=False, groups="hr_payroll.group_hr_payroll_user")
besoldungsdienstalter = fields.Date(
related="version_id.besoldungsdienstalter", inherited=True,
readonly=False, groups="hr_payroll.group_hr_payroll_user")
vorrueckungstermin = fields.Date(
related="version_id.vorrueckungstermin", inherited=True,
readonly=False, groups="hr_payroll.group_hr_payroll_user")