[IMP] l10n_at_hr_payroll_private: GP6 FI-Buchung UGB (KFS/BW-6-Matrix, EKR-Debit-Split, NET-Konvention)

Buchungsmatrix nach dem Oesterreichischen Einheitskontenrahmen (KFS/BW 6; Nutzer-Referenz-Exemplar .additional_docs/KFSBW6_13072017_RF.pdf): Hook _configure_payroll_account_at (models/account_chart_private.py) ordnet Regelkonten, Journal SLR (Default = Gehaelterkonto 6200, BE-Muster) und das NET-Konto 3850 "Verbindlichkeiten aus Lohn und Gehalt" (Nutzer-Entscheidung 5.1; Anlage + reconcile, l10n_at-Standardchart hat es nicht) je Company zu — getriggert beim Chart-Load (_post_load_data) UND ueber die <function>-Datendatei data/hr_payroll_account_private.xml fuer Bestands-Companies (erster <value> einer function ist die Record-ID-Liste, convert.py-Semantik), idempotent. Konto-Suche exakt zuerst, Praefix-Fallback nur bis eine Stelle laenger — verhindert Matches auf Odoo-Scaffold-Konten chartloser Firmen (6000 darf nicht 600000 "Expenses" matchen).

EKR-Debit-Split Arbeiter/Angestellte (Nutzer-Klaerung: 600-619 Loehne, 620-639 Gehaelter — "6000 Gehaelter/6200 Loehne" war gegen die eigene KFS/BW-6-Referenz vertauscht): l10n_at_personalgruppe am Vertrag (models/hr_version_private.py) + Override-Feld l10n_at_account_debit_arbeiter je Regel; Option A minimal (Nutzer-Entscheidung 5.2: Grundentgelt 6000, Sozialaufwand 6500, Abgaben 6600/6601/6602; Zuschlaege/UeStd/Praemien/SZ und BV (EKR 644 ohne Split) buchen fuer Arbeiter bis zur Referenzbuchhaltungs-Fixierung auf die Angestellten-Konten — fehlende Konten warnen, keine Erfindung). models/account_posting_private.py: Gesamtueberschreibung von _prepare_slip_lines nach Upstream-Muster (Odoo-Pin 19.0+e.20260910) mit einzeiliger Kontosubstitution — Odoo bietet dafuer keinen Override-Punkt; Verhalten testgepinnt. Matrix: KVGEO/URL_UE 6200/6000, Zuschlaege 6225, UeStd 6310, Praemien 6230, B13/B14 6240, DN-SV/LSt auf 3600/3540, NET 3850, SVDG-Block 6560/6500 auf 3600, BVG 6440 (Fallback 6400) auf Credit 3600 (Abfuhr via KV-Traeger, Nutzer 5.3), FLAFDB 6661/6601 auf 3541, KOMMST 6660/6600 auf 3550, DZ 6662/6602 auf 3542.

NET-Umbenennung NETTO -> NET (Odoo-Konvention: action_register_payment, net_wage und Negativ-Netto-Erkennung filtern code == NET) inkl. 4 Bestands-Suiten. Odoo-19-Fund: das Anlegen einer Structure kopiert die Regeln des hr_payroll.default_structure (BASIC/GROSS/NET/...) via Feld-Default in rule_ids — die kopierte Default-NET-Regel kollidierte im result_rules-Dict (Netto fiel auf 0); Fix: <function> in salary_rules_private.xml archiviert die Kopie (active=False; KEIN Unlink — struct_id ist NOT NULL und historische Lohnkontolinien behalten ihre Regel-Referenz; One2many blendet Archivierte aus). Journal-Default-Konten duerfen nicht Receivable/Payable sein (Odoo-Constraint); Rundungscents bucht Odoo als Adjustment Entry aufs Journal-Default.

depends: + l10n_at, hr_payroll_account_iso20022 (SEPA-Auszahlung, Plan 4.5; kein VRV/MVAG — gem360-Bruecke). Tests: test_account_private (4: RF-BUCH-1..4 — Kontenplan-Mock ohne Chart-Install, Move-Balance, Kontenzeilen je Matrix, Arbeiter-Split, Geringfuegiger, Fallback/Warnung) — gesamt 88/88 gruen auf Wegwerf-DB (frischer -i-Lauf). Rechenfaelle docs/rechenfaelle/buchhaltung.md. 19.0.6.0.0.
This commit is contained in:
2026-09-12 12:58:53 +02:00
parent 1e88fd1636
commit 27654211fb
16 changed files with 842 additions and 25 deletions
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- GP6 FI-Buchung UGB: Buchungsmatrix für Bestands-Companies -->
<!-- auf dem AT-Kontenrahmen (res.company.chart_template ist das -->
<!-- Selection-Feld mit dem Template-Code, Muster -->
<!-- l10n_be_hr_payroll_account). Der ERSTE <value> ist die -->
<!-- Record-ID-Liste des Aufrufs (convert.py: browse(ids)) — -->
<!-- AbstractModel → []. Frische Chart-Loads laufen automatisch -->
<!-- über account.chart.template._post_load_data → -->
<!-- _load_payroll_accounts (Kontext chart_template_load). Beide -->
<!-- Pfade idempotent (Konto-/Journalsuche, Matrix-Write). -->
<data noupdate="1">
<function model="account.chart.template" name="_load_payroll_accounts">
<value eval="[]"/>
<value>at</value>
<value model="res.company"
eval="obj().search([('chart_template', '=', 'at')])"/>
</function>
</data>
</odoo>
@@ -367,10 +367,14 @@ result = bezahlt * (payslip._at_sz_dienstzeit_faktor() - 1.0)
]]></field>
</record>
<!-- NETTO (Kategoriensummen; DN-Abzüge folgen GP3/GP4). -->
<!-- NET (Kategoriensummen; DN-Abzüge folgen GP3/GP4). Odoo- -->
<!-- Regelkonvention: hr_payroll_account erwartet für die -->
<!-- Zahlungsregistrierung den Netto-Regelcode 'NET' (action_ -->
<!-- register_payment filtert code == 'NET' und prüft account_ -->
<!-- credit.reconcile) — GP6-Umbenennung von NETTO. -->
<record id="rule_netto" model="hr.salary.rule">
<field name="name">Netto</field>
<field name="code">NETTO</field>
<field name="code">NET</field>
<field name="sequence" eval="100"/>
<field name="category_id" ref="l10n_at_hr_payroll_private.category_atp_netto"/>
<field name="struct_id" ref="l10n_at_hr_payroll_private.structure_at_privat"/>
@@ -380,4 +384,15 @@ result = bezahlt * (payslip._at_sz_dienstzeit_faktor() - 1.0)
result = categories['ATP_BRUTTO'] - categories['ATP_ABZUG']
]]></field>
</record>
<!-- GP6: die beim Structure-Anlegen automatisch kopierte -->
<!-- Default-NET-Regel (hr_payroll.default_structure, Feld- -->
<!-- Default _get_default_rule_ids) von der Structure abhängen -->
<!-- und archivieren — Code-Kollision mit rule_netto (Code NET -->
<!-- nach Odoo-Konvention): sonst überschreiben sich zwei NET- -->
<!-- Regeln im result_rules-Dict und die Netto-Zeile fällt auf 0. -->
<!-- Methode: models/payslip_private.py; idempotent. -->
<function model="hr.payroll.structure" name="_l10n_at_entferne_default_net_kopie">
<value eval="[ref('l10n_at_hr_payroll_private.structure_at_privat')]"/>
</function>
</odoo>