[IMP] l10n_at_hr_payroll_private: add unpaid care/parental leave family (AP16)
Close the parental/care-leave block after the pilot-client scope release (8.13): six unpaid full-release kinds join the generic parental-leave work entry — Bildungskarenz (AVRAG § 11, two to twelve months by agreement with the AMS-financed Weiterbildungsbeihilfe), Familienhospizkarenz for terminal accompaniment (AVRAG § 14a, three to six months), accompaniment of seriously ill children (§ 14b, five to nine months), children's rehabilitation leave (§ 14e, four weeks per year), Pflegekarenz (§ 14c, one to three months, undivided) and the Papa-Monat (VKG § 1a, one month, creditable toward seniority under § 1a Abs 7 VKG iVm § 15f MSchG while Bildungs-/Pflegekarenz is not). All are unpaid at the employer — the external bodies pay the replacement income (AK, AMS, Bundesamt, KV-Träger) — so the new negative KARENZ_ENTGELT rule stops the employer wage per working day through the shared Tagesatz helper whose exclusion list now covers EFZG, Mutterschutz and Karenz corrections. The Versichertenmeldung run emits M4 deregistrations at the end of the pay entitlement (the day before the release begins) and M3 re-registrations at the return date — omitted when the employment itself ends — with the eSV Karenzart strings logged as protocol information pending the special DM-ORG formats (GP7 track). The fictive BMSVG basis gains the § 7 Abs 4 Z 1–3 bridge: when a new maternity prohibition follows a parental-leave stretch directly or after employment of less than three months, the reference months fall before the preceding prohibition, and a re-founded employment within three months of the ended karenziert employment uses the single last full calendar month; contributions during the KBG period are FLAF-financed (§ 7 Abs 5) and during hospice/care leave Bund-financed (§ 7 Abs 6) — no employer rule, verified by test. Pflegeteilzeit and comparable reduced-hour arrangements pay the BV contribution on the pre-reduction wage via a new version field consumed by the BMSVG basis (§ 6 Abs 4). The endabrechnung wizard gains the § 23 Abs 8 AngG full-time re-rating preview (monthly salary ÷ work_time_rate, confirmable) with § 23a Abs 4a and UEL § 10 Abs 4 UrlG guidance. The Mutterschutz status now detects the § 163 ASVG Sonderwochengeld case (prohibition inside a Karenz — the KV-Träger pays the increased sickness benefit) and warns on § 166 ASVG suspension (full for >50 % continued pay, half at 50 %, activity and Pflegekarenzgeld hints). Verified against the original statute text in .ris/ (AVRAG §§ 11/11a/14a–14e, VKG § 1a, MSchG § 15f, BMSVG § 7 Abs 4–6, ASVG §§ 163/166) and the knowledge-base sources lb-kar/elt/kzs/pap/kbg; the vacation proration of leave stretches (§ 15f Abs 2 MSchG on the hr_holidays allocation side), the eSV special formats for the Karenz art block, the full Sonderwochengeld computation and the leave-overlap policy decision remain documented open points. Version 19.0.17.0.0 (private)
This commit is contained in:
@@ -23,12 +23,15 @@ BVAB/BVJN aus dem GP5-BMSVG-Flag, VWAZ vereinbarte Wochenarbeitszeit
|
||||
(Stunden ×100, neu für Meldedaten ab 01.01.2026).
|
||||
|
||||
Dateibasiert (Prämisse P7); Bestätigungen/Übertragung beim Mandanten."""
|
||||
from datetime import date
|
||||
from datetime import date, timedelta
|
||||
import base64
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
from odoo.addons.l10n_at_hr_payroll_private.models.karenz import \
|
||||
KARENZ_ARTEN
|
||||
|
||||
from odoo.addons.l10n_at_hr_payroll.models.elda import (
|
||||
L10N_AT_ELDA_IDTEIL,
|
||||
L10nAtEldaBestand,
|
||||
@@ -199,6 +202,58 @@ class L10nAtPayrollVr(models.Model):
|
||||
abmeldungen.append(version)
|
||||
return sorted(abmeldungen, key=lambda v: v.contract_date_end)
|
||||
|
||||
def _l10n_at_offene_karenz_events(self):
|
||||
"""AP16 (8.13): An-/Abmeldungen aus validierten Karenz-
|
||||
Freistellungen: M4 zum Ende des Entgeltanspruchs (Tag vor dem
|
||||
Karenzbeginn; Familienzeit am Tag vor Beginn, § 11 Abs 3 lit a
|
||||
ASVG, lb-pap-01), M3 zum ersten Arbeitstag nach dem Karenzende
|
||||
— entfällt, wenn das DV mit der Karenz endet (normale M4-
|
||||
Vertragsabmeldung deckt das Ende). Karenzart-Strings für die
|
||||
eSV-Sonderformate „Familienhospizkarenz/Pflegekarenz An-/
|
||||
Abmeldung" (lb-kzs-05) laufen als Protokoll-Info; erweiterte
|
||||
eSV-Sonderformate = GP7-Rest. Dedup über die Registry
|
||||
(employee, art, adatum); keine Events nach dem Stichtag."""
|
||||
self.ensure_one()
|
||||
typen = self.env['hr.leave.type'].search([
|
||||
('work_entry_type_id.code', 'in', list(KARENZ_ARTEN))])
|
||||
if not typen:
|
||||
return []
|
||||
leaves = self.env['hr.leave'].search([
|
||||
('company_id', 'in', self.company_id.ids),
|
||||
('holiday_status_id', 'in', typen.ids),
|
||||
('state', 'in', ('validate', 'validate1')),
|
||||
]).sorted('request_date_from')
|
||||
registry = self.env['l10n.at.payroll.vr.event'].search([
|
||||
('company_id', '=', self.company_id.id),
|
||||
])
|
||||
gesehen = {(e.employee_id.id, e.art, e.adatum) for e in registry}
|
||||
ereignisse = []
|
||||
for leave in leaves:
|
||||
von = leave.request_date_from
|
||||
bis = leave.request_date_to
|
||||
if not von or not bis:
|
||||
continue
|
||||
version = leave.employee_id.version_id
|
||||
if not version:
|
||||
continue
|
||||
wett_code = leave.holiday_status_id \
|
||||
.work_entry_type_id.code
|
||||
karenzart = KARENZ_ARTEN.get(wett_code, 'Karenz')
|
||||
abmeldetag = von - timedelta(days=1)
|
||||
if abmeldetag > self.stichtag:
|
||||
continue
|
||||
if (leave.employee_id.id, 'M4', abmeldetag) not in gesehen:
|
||||
ereignisse.append((version, 'M4', abmeldetag, karenzart))
|
||||
rueckkehr = bis + timedelta(days=1)
|
||||
if (version.contract_date_end
|
||||
and rueckkehr >= version.contract_date_end):
|
||||
continue
|
||||
if rueckkehr > self.stichtag:
|
||||
continue
|
||||
if (leave.employee_id.id, 'M3', rueckkehr) not in gesehen:
|
||||
ereignisse.append((version, 'M3', rueckkehr, karenzart))
|
||||
return ereignisse
|
||||
|
||||
def _l10n_at_bber(self, version):
|
||||
if version.l10n_at_lehrling:
|
||||
return '03' if getattr(
|
||||
@@ -234,6 +289,7 @@ class L10nAtPayrollVr(models.Model):
|
||||
raise UserError('Beitragskontonummer (BKNR) fehlt.')
|
||||
datensaetze = []
|
||||
ereignisse = []
|
||||
karenz_info = []
|
||||
vstr = bknr[:2]
|
||||
if lauf.nur_fallweise:
|
||||
versionen = self.env['hr.version'].search([
|
||||
@@ -366,6 +422,51 @@ class L10nAtPayrollVr(models.Model):
|
||||
ereignisse.append((version, 'M4',
|
||||
version.contract_date_end,
|
||||
refw))
|
||||
for version, art, adatum, karenzart in \
|
||||
lauf._l10n_at_offene_karenz_events():
|
||||
if not version.ssnid:
|
||||
fehler.append(
|
||||
'Karenz-Meldung %s ohne Versicherungsnummer.'
|
||||
% version.employee_id.name)
|
||||
continue
|
||||
satz = L10nAtEldaSatz(
|
||||
L10N_AT_ELDA_IDTEIL + VR_SATZ, 772,
|
||||
bezeichnung='%s Karenz %s' % (
|
||||
art, version.employee_id.name))
|
||||
refw = '%s-K%d-%s-%d' % (
|
||||
art, company.id,
|
||||
adatum.strftime('%Y%m%d'),
|
||||
version.employee_id.id)
|
||||
satz.setze('SART', art)
|
||||
satz.setze('VSTR', vstr)
|
||||
satz.setze('REFW', refw)
|
||||
satz.setze('BKNR', bknr)
|
||||
satz.setze('DGNA', company.name[:70])
|
||||
satz.setze('VSNR', version.ssnid)
|
||||
satz.setze_datum(
|
||||
'GEBD', version.employee_id.birthday)
|
||||
familienname, vorname = l10n_at_namen(
|
||||
version.employee_id)
|
||||
satz.setze('FANA', familienname[:70])
|
||||
satz.setze('VONA', (vorname or '')[:70])
|
||||
satz.setze_datum('ADAT', adatum)
|
||||
if art == 'M3':
|
||||
satz.setze('BBER', lauf._l10n_at_bber(version))
|
||||
satz.setze('GERF', 'N')
|
||||
satz.setze('FRDV', 'N')
|
||||
else:
|
||||
satz.setze_datum('EBSV', adatum)
|
||||
satz.setze('AGRD', '00')
|
||||
kalender = version.resource_calendar_id
|
||||
if kalender:
|
||||
satz.setze('VWAZ', kalender.hours_per_week,
|
||||
skala=2)
|
||||
datensaetze.append(satz)
|
||||
ereignisse.append((version, art, adatum, refw))
|
||||
karenz_info.append(
|
||||
'%s (ADAT %s) — %s' % (
|
||||
version.employee_id.name,
|
||||
adatum.strftime('%d.%m.%Y'), karenzart))
|
||||
if fehler:
|
||||
lauf.protokoll = 'FEHLER:\n' + '\n'.join(fehler)
|
||||
raise UserError('Versichertenmeldung mit Fehlern '
|
||||
@@ -395,12 +496,17 @@ class L10nAtPayrollVr(models.Model):
|
||||
ereignisse = self.env['l10n.at.payroll.vr.event'].create(
|
||||
ereignis_werte) if ereignis_werte else \
|
||||
self.env['l10n.at.payroll.vr.event']
|
||||
protokoll = 'Meldungen: %d' % len(datensaetze)
|
||||
if karenz_info:
|
||||
protokoll += ("\nKarenz (eSV-Sonderformate GP7-Rest; "
|
||||
"Karenzart zur Übergabe):\n"
|
||||
+ "\n".join(karenz_info))
|
||||
lauf.write({
|
||||
'datei': base64.b64encode(datei.render()),
|
||||
'datei_name': 'versichertenmeldung_%s.txt' % (
|
||||
fields.Date.today().strftime('%Y%m%d'),),
|
||||
'event_ids': [(6, 0, ereignisse.ids)],
|
||||
'state': 'done',
|
||||
'protokoll': 'Meldungen: %d' % len(datensaetze),
|
||||
'protokoll': protokoll,
|
||||
})
|
||||
return True
|
||||
Reference in New Issue
Block a user