# Part of the odoo-at-payroll project. License: LGPL-3. """Kind-Datenmodell (GP7): Kinder je Mitarbeiter für die Wartung des Familienbonus Plus und die Befüllung des L16-Kinderblocks (Lohnzettel-Finanz-Mitteilungssatz, DM-ORG 42.7.0 E.14, Felder Nr. 196–209: je Kind 123 Stellen — KFAM/KVON/KSTAAT/KSTWE/KVSNR/ KGEBD/KAFBZ/KAPFB/KAUHZ/KBGFP/KEGFP/KBHFP/KEHFP). Nutzer-Entscheidung 2026-09-12: die FB+-Steuerwirkung selbst ist KEIN Bestandteil der Personalverrechnung (bei Unterschreiten der Steuer auf 0 erfolgt die Geltendmachung über die Arbeitnehmerveranlagung) — das Modell dient der Stammdaten-Wartung (Anspruch, Monate, halber Bonus) und der L16-Meldung. Monatsfelder im Format MM (Kinderblock 2n); die Betragsermittlung (FABO) rechnet der L16-Generator aus den gepflegten Monaten und der Altersstaffel (§ 33 Abs 5 EStG: bis 18. Geburtstag 166,68 €/Monat, darüber 58,34 €/Monat solange Familienbeihilfe).""" from odoo import fields, models class HrEmployee(models.Model): _inherit = 'hr.employee' l10n_at_payroll_kind_ids = fields.One2many( 'l10n.at.payroll.kind', 'employee_id', string='Kinder (Familienbonus Plus)', groups="hr_payroll.group_hr_payroll_user") class L10nAtPayrollKind(models.Model): _name = 'l10n.at.payroll.kind' _description = 'Kind (Familienbonus Plus / Lohnzettel L16)' _order = 'geburtstag, id' employee_id = fields.Many2one( 'hr.employee', string='Mitarbeiter:in', required=True, index=True, ondelete='cascade') familienname = fields.Char( string='Familienname (KFAM)', required=True) vorname = fields.Char(string='Vorname (KVON)') geburtstag = fields.Date( string='Geburtsdatum (KGEBD)', required=True, help='Maßgeblich für die FB+-Staffel (bis zum 18. Geburtstag ' '166,68 €/Monat, danach 58,34 €/Monat solange ' 'Familienbeihilfe) und die Altersfilter (z. B. ' 'Schwerarbeitsmeldung 40 M/35 F).') versicherungsnummer = fields.Char( string='Versicherungsnummer (KVSNR)', help='10-stellig, LLLPTTMMJJ; nur wenn zugeteilt.') staatsangehoerigkeit = fields.Char( string='Staatsangehörigkeit (KSTAAT, 3-stelliger Code)') staatsangehoerigkeit_2 = fields.Char( string='2. Staatsangehörigkeit (KSTWE, 1-stelliger Code)') # ------------------------------------------------------------------ # Familienbonus Plus — Wartung (L16-Kinderblock) # ------------------------------------------------------------------ fab_plus = fields.Boolean( string='Familienbonus Plus geltend gemacht', help='L16 KFABO (Anzahl) und FABO (Betrag) ergeben sich aus den ' 'Kindern mit gesetztem FB+-Kennzeichen.') fab_monat_von = fields.Integer( string='FB+ ab Monat (KBGFP)', help='Monat (1–12), ab dem der volle Familienbonus Plus für ' 'dieses Kind geltend gemacht wurde (L16 KBGFP).') fab_monat_bis = fields.Integer( string='FB+ bis Monat (KEGFP)', help='Letzter Monat (1–12) des vollen Familienbonus Plus (L16 ' 'KEGFP).') fab_halb_monat_von = fields.Integer( string='Halber FB+ ab Monat (KBHFP)', help='Monat (1–12), ab dem nur mehr der halbe Familienbonus Plus ' 'geltend gemacht wurde (Aufteilung zwischen den ' 'Elternteilen; L16 KBHFP).') fab_halb_monat_bis = fields.Integer( string='Halber FB+ bis Monat (KEHFP)', help='Letzter Monat (1–12) des halben Familienbonus Plus (L16 ' 'KEHFP).') def _l10n_at_fab_monate(self, jahr): """[(Monat, Anteil 1.0/0.5), …] des FB+ im Lohnzetteljahr aus den gepflegten Monatsfeldern (voll + halb, Überschneidung: der spätere Eintrag gewinnt).""" self.ensure_one() monate = {} von, bis = self.fab_monat_von or 0, self.fab_monat_bis or 0 if von and bis and 1 <= von <= bis <= 12: for monat in range(von, bis + 1): monate[monat] = 1.0 hvon, hbis = (self.fab_halb_monat_von or 0, self.fab_halb_monat_bis or 0) if hvon and hbis and 1 <= hvon <= hbis <= 12: for monat in range(hvon, hbis + 1): monate[monat] = 0.5 return sorted(monate.items()) def _l10n_at_fab_betrag(self, jahr, voll=166.68, vermindert=58.34): """FB+-Jahresbetrag je Kind aus Monaten × Monatsrate; die Rate wechselt mit dem 18. Geburtstag (monatliche Staffel: Monate vor dem Geburtsmonat + 18 Jahre voller Satz, danach verminderter Satz — § 33 Abs 5 EStG, solange Familienbeihilfe).""" self.ensure_one() if not self.geburtstag or not self.fab_plus: return 0.0 umschalt = self.geburtstag.month return sum(anteil * (vermindert if monat >= umschalt else voll) for monat, anteil in self._l10n_at_fab_monate(jahr))