From 90e4bcaa5d6369e1d09aeb935704b24935a4ac1b Mon Sep 17 00:00:00 2001 From: fegger Date: Fri, 11 Sep 2026 22:24:03 +0200 Subject: [PATCH] [IMP] l10n_at_hr_payroll_private: GP3 payroll tax integration (DN/SV and LSt rules, 67/68 rule flags, tests) --- .../__manifest__.py | 3 +- .../data/salary_rules_lst_private.xml | 107 ++++++++++ .../data/salary_rules_private.xml | 90 ++++++--- .../docs/rechenfaelle/lohnsteuer.md | 101 ++++++++++ .../tests/__init__.py | 3 +- .../tests/test_entgelt_private.py | 12 +- .../tests/test_lst_private.py | 188 ++++++++++++++++++ 7 files changed, 472 insertions(+), 32 deletions(-) create mode 100644 addons/l10n_at_hr_payroll_private/data/salary_rules_lst_private.xml create mode 100644 addons/l10n_at_hr_payroll_private/docs/rechenfaelle/lohnsteuer.md create mode 100644 addons/l10n_at_hr_payroll_private/tests/test_lst_private.py diff --git a/addons/l10n_at_hr_payroll_private/__manifest__.py b/addons/l10n_at_hr_payroll_private/__manifest__.py index e08c155..a16300b 100644 --- a/addons/l10n_at_hr_payroll_private/__manifest__.py +++ b/addons/l10n_at_hr_payroll_private/__manifest__.py @@ -1,7 +1,7 @@ # Part of the odoo-at-payroll project. License: LGPL-3. { 'name': 'Österreich - Privatwirtschaft Personalverrechnung (General-AT)', - 'version': '19.0.2.0.0', + 'version': '19.0.3.0.0', 'author': 'ixsol / gem360', 'website': 'https://gem360.at', 'category': 'Human Resources/Payroll', @@ -52,6 +52,7 @@ gem360-Brücke). 'data/work_entry_types_private.xml', 'data/input_types_private.xml', 'data/salary_rules_private.xml', + 'data/salary_rules_lst_private.xml', 'views/kv_views.xml', ], 'countries': ['at'], diff --git a/addons/l10n_at_hr_payroll_private/data/salary_rules_lst_private.xml b/addons/l10n_at_hr_payroll_private/data/salary_rules_lst_private.xml new file mode 100644 index 0000000..ff7bd62 --- /dev/null +++ b/addons/l10n_at_hr_payroll_private/data/salary_rules_lst_private.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + SV-DN Krankenversicherung (§ 62 Z 1 iVm § 16 Abs 3) + SVDN_KV + + + + python + result = payslip._l10n_at_svdn('kv', result_rules) > 0 + code + neutral + + + + SV-DN Pensionsversicherung (§ 62 Z 1 iVm § 16 Abs 3) + SVDN_PV + + + + python + result = payslip._l10n_at_svdn('pv', result_rules) > 0 + code + + + + SV-DN Arbeitslosenversicherung (§ 62 Z 1 iVm § 16 Abs 3) + SVDN_AV + + + + python + result = payslip._l10n_at_svdn('av', result_rules) > 0 + code + + + + AK-Umlage DN (§ 61 AKG; § 62 Z 3) + SVDN_AK + + + + python + result = payslip._l10n_at_svdn('ak', result_rules) > 0 + code + + + + WF-Beitrag DN (§ 62 Z 5; Wien 0,75 % via Company-Flag) + SVDN_WF + + + + python + result = payslip._l10n_at_svdn('wf', result_rules) > 0 + code + + + + + + Lohnsteuer laufend (§ 66, kumulativ mit Rollung) + LST_LFD + + + + python + result = payslip._l10n_at_lst_laufend(result_rules) > 0 + code + + + + Lohnsteuer sonstige Bezüge (§ 67 Fixsätze, Aufrollung) + LST_SZ + + + + python + result = payslip._l10n_at_lst_sonstige(result_rules) > 0 + code + + + \ No newline at end of file diff --git a/addons/l10n_at_hr_payroll_private/data/salary_rules_private.xml b/addons/l10n_at_hr_payroll_private/data/salary_rules_private.xml index 41a3d88..e666bf6 100644 --- a/addons/l10n_at_hr_payroll_private/data/salary_rules_private.xml +++ b/addons/l10n_at_hr_payroll_private/data/salary_rules_private.xml @@ -19,6 +19,7 @@ python result = bool(employee.kv_id and employee.kv_gruppe_id and (employee.ueberzahlung or employee.erfahrungsstufe)) + laufend code python result = payslip._at_nacht_sv_stunden() > 0 code + laufend + szfn + @@ -62,14 +67,17 @@ result = payslip._at_nacht_sv_stunden() * satz python result = 'ATP_UE_STD' in worked_days and worked_days['ATP_UE_STD'].number_of_hours > 0 code + laufend + ue_std + @@ -81,13 +89,17 @@ result = stunden * grund * (1 + zuschlag / 100.0) python result = 'ATP_UE_NACHT' in worked_days and worked_days['ATP_UE_NACHT'].number_of_hours > 0 code + laufend + szfn + @@ -99,13 +111,16 @@ result = stunden * grund * (1 + zuschlag / 100.0) python result = 'ATP_UE_NACHT_FRUEH' in worked_days and worked_days['ATP_UE_NACHT_FRUEH'].number_of_hours > 0 code + laufend + szfn + @@ -117,13 +132,16 @@ result = stunden * grund * (1 + zuschlag / 100.0) python result = 'ATP_UE_SOFEI' in worked_days and worked_days['ATP_UE_SOFEI'].number_of_hours > 0 code + laufend + szfn + @@ -135,14 +153,17 @@ result = stunden * grund * (1 + zuschlag / 100.0) python result = 'ATP_UE_SOFEI_NACHT' in worked_days and worked_days['ATP_UE_SOFEI_NACHT'].number_of_hours > 0 code + laufend + szfn + @@ -159,15 +180,18 @@ result = stunden * grund * (1 + zuschlag / 100.0) result = 'ATP_MEHR_VZ' in worked_days and worked_days['ATP_MEHR_VZ'].number_of_hours > 0 and bool(employee.kv_id._wert('mehrarbeit_zuschlag', payslip.date_to, raise_if_not_found=False)) ]]> code + laufend + ue_std + 50 %-Zuschlag sind ÜStd (§ 4a letzter Satz — -# Klassifikation stromauf). +# Normalstunde, 2748: ÷ 167); zählt nicht gegen das ÜStd-Ausmaß. +# LSt: Differenzstunden-Zuschläge abgabenrechtlich wie ÜStd-Zuschläge +# (LStR Rz 1146) → § 68 Abs 2-Bucket (Regel-Flag ue_std). grund = payslip._at_grundstunde_norm() zuschlag = float(employee.kv_id._wert('mehrarbeit_zuschlag', payslip.date_to)) -stunden = worked_days['ATP_MEHR_VZ'].number_of_hours -result = stunden * grund * (1 + zuschlag / 100.0) +result = grund * (1 + zuschlag / 100.0) +result_qty = worked_days['ATP_MEHR_VZ'].number_of_hours ]]> @@ -181,11 +205,14 @@ result = stunden * grund * (1 + zuschlag / 100.0) result = 'ATP_MEHR_VZ_NACHT' in worked_days and worked_days['ATP_MEHR_VZ_NACHT'].number_of_hours > 0 and bool(employee.kv_id._wert('mehrarbeit_zuschlag', payslip.date_to, raise_if_not_found=False)) ]]> code + laufend + ue_std + @@ -201,15 +228,18 @@ result = stunden * grund * (1 + zuschlag / 100.0) python result = 'ATP_MEHR_TZ' in worked_days and worked_days['ATP_MEHR_TZ'].number_of_hours > 0 code + laufend @@ -221,12 +251,13 @@ result = stunden * grund * (1 + zuschlag / 100.0) python result = 'ATP_MEHR_TZ_NACHT' in worked_days and worked_days['ATP_MEHR_TZ_NACHT'].number_of_hours > 0 code + laufend @@ -243,6 +274,7 @@ result = stunden * grund * (1 + zuschlag / 100.0) + laufend code python result = 'ATP_PRAMIE' in inputs and inputs['ATP_PRAMIE'].amount + laufend code python result = payslip._at_b13_faellig() + sonstig code python result = payslip._at_b14_faellig() + sonstig code + sonstig code 2.615 ✓ + pauschal → LST_SZ = (1.707,87 − 620) × 6 % = **65,27 €**. + +## RF-L2: Kumulative Rollung (Zuflussprinzip) + +- Januar LST_LFD 67,12; Februar: JBG unverändert → Soll kumuliert + 134,24 − bereits 67,12 = **67,12** — Korrekturen Vormonat + (Nachzahlung, Gehaltsänderung) rollen automatisch in den + Folgelauf (§ 66 kumulativ = Rollungsprinzip § 77 Abs 3). + +## RF-L3: Günstig-Aufrollung bei zweiter SZ + +- Okt (nur laufend), Nov B13 (LST_SZ 65,27 bezahlt), Dez B14 + (Dezember-Fallback ohne Urlaub): Jahres-SZ-Bemessung + 2 × 1.707,87 = 3.415,74 ≤ Sechstel 4.118,82 → Soll-Jahr + (3.415,74 − 620) × 6 % = 167,74 − 65,27 = **LST_SZ(Dez) 102,47 €** + (Neuberechnung bei jeder SZ-Zahlung, lb-son-04). + +## RF-L4: Sechstel-Freigrenze (2.615 €) — SZ tarifisch + +- Laufend 500 €/Monat: Sechstel = 500 × 60/30 = 1.000 ≤ 2.615 → + B14 läuft tarifisch über LST_LFD (LST_SZ = 0). + +## RF-L5: Sechstel-Überschuss (§ 67 Abs 10) + +- Laufend 2.000 €/Monat (Sechstel 4.000), SZ 6.000 €: + SV-SZ = 6.000 × 17,07 % = 1.024,20 → Bemessung 4.975,80; + 4.000 im Sechstel → Fixsteuer (4.000 − 620) × 6 % = **202,80 €**; + Überschuss 975,80 läuft dem laufenden Arbeitslohn des + Auszahlungsmonats zu (LSt-lfd-Kette). + +## RF-L6: § 68-Freibeträge (Buckets über Regel-Flags) + +- **SZFN (Abs 1):** Zuschlagsanteile der 100 %-Zuschläge + + Nacht-€-Sondervergütung bis 400 € (600 € bei überwiegender + Nachtarbeit — Vertrags-Flag) steuerfrei. +- **ÜStd (Abs 2 iVm § 124b Z 440 idF BGBl I 4/2026):** 50 %-Klasse + (UE_STD, MEHR_VZ-Differenzstunden, LStR Rz 1146): erste 15 ÜStd, + max 170 € (2026; ab 2027 10/120 — versioniert). Beispiel: + 2 ÜStd à 13,73 € + 50 % Zuschlag = 41,19 → davon 33,33 % = 13,73 € + steuerfrei. Teilzeit-Mehrarbeit § 19d: **kein** Freibetrag + (voll steuerpflichtig). +- Feiertagsentgelt: § 124b Z 492/Z 494 (idF BGBl I 43/2026) — + Wirkungsabgrenzung GP6/Feiertagsengine. + +## RF-L7: Absetzbeträge 2026 (Reform — AN-AB entfallen) + +- Verkehrsabsetzbetrag **496 €** (Pendler-Variante 853 € bei + Einkommen ≤ 15.069 — R1-Option mit Pendlerdaten; Zuschlag 804 € + nur Veranlagung). +- AVB/AVAB: Kind 1 **612 €**, 2 Kinder **828 €**, je weiteres + **+273 €** (Vertrags-Feld + Kinderzahl; AVB-Partnergrenze + 7.411 € mandantenseitig nachgewiesen). +- Arbeitnehmerabsetzbetrag: **entfallen** (im Tarif integriert — + Steuerreform; die historische 60 %-Werbungskosten-Regelung war + ohnehin nur Veranlagungsmechanik: monatlich liefen SV-Beiträge + stets voll über § 62 Z 1 iVm § 16 Abs 3). + +## RF-L8: Nachzahlungs-/Aufrollungs-Workflow (GP3+GP8) + +- Unterjährige Korrektur = Nachzahlungslinie im Zuflussmonat — + kumulative Engine bucht die Differenz automatisch (kein Storno). +- Echter Datenfehler: Odoo-Refund + Neuberechnung (YTD-Helfer + refundbewusst). +- **SV je Beitragsmonat (Anspruchsprinzip)** mit historischen + versionierten Sätzen/HBG + **Nachtrags-mBGM** (Storno + + Neumeldung): GP4 (Allokation) + GP7 (ELDA-Export). +- 15.2.-Cutoff (Vorjahres-L16 + berichtigter Lohnzettel), + Fünftelregelung § 67 Abs 8 lit c (`_l10n_at_fuenftelregelung`), + Willkür→Tarif: Datenmodell + Utility in GP3, Vollausbau GP8. \ No newline at end of file diff --git a/addons/l10n_at_hr_payroll_private/tests/__init__.py b/addons/l10n_at_hr_payroll_private/tests/__init__.py index 36016c6..e8ae740 100644 --- a/addons/l10n_at_hr_payroll_private/tests/__init__.py +++ b/addons/l10n_at_hr_payroll_private/tests/__init__.py @@ -1,3 +1,4 @@ # Part of the odoo-at-payroll project. License: LGPL-3. from . import test_kv_katalog -from . import test_entgelt_private \ No newline at end of file +from . import test_entgelt_private +from . import test_lst_private \ No newline at end of file diff --git a/addons/l10n_at_hr_payroll_private/tests/test_entgelt_private.py b/addons/l10n_at_hr_payroll_private/tests/test_entgelt_private.py index 1fd3c30..82f846e 100644 --- a/addons/l10n_at_hr_payroll_private/tests/test_entgelt_private.py +++ b/addons/l10n_at_hr_payroll_private/tests/test_entgelt_private.py @@ -368,8 +368,9 @@ class EntgeltPrivateTest(TransactionCase): # ------------------------------------------------------------------ # Netto / All-in # ------------------------------------------------------------------ - def test_20_netto_ohne_abzuege(self): - """R1: Netto = Brutto-Kategorien (AP3/AP4 folgen).""" + def test_20_netto_mit_dn_abzuegen(self): + """GP3: Netto = ATP_BRUTTO − ATP_ABZUG — SVDN + LSt laufen + real mit (AP3-Kern angebunden).""" employee = self._employee(stufe=1) slip = self._compute(employee, 11) brutto = sum( @@ -379,7 +380,12 @@ class EntgeltPrivateTest(TransactionCase): 'MEHR_VZ', 'MEHR_VZ_NACHT', 'MEHR_TZ', 'MEHR_TZ_NACHT', 'URL_UE', 'PRAM', 'B13', 'B14', 'B14_RUECK')) - self.assertAlmostEqual(self._total(slip, 'NETTO'), brutto, places=2) + abzug = sum( + self._total(slip, code) + for code in ('SVDN_KV', 'SVDN_PV', 'SVDN_AV', 'SVDN_AK', + 'SVDN_WF', 'LST_LFD', 'LST_SZ')) + self.assertAlmostEqual( + self._total(slip, 'NETTO'), brutto - abzug, places=2) def test_21_allin_deckungsrechnung(self): """§ 2g AVRAG: Jahresdeckung = 12 × Pauschale vs. geschuldete diff --git a/addons/l10n_at_hr_payroll_private/tests/test_lst_private.py b/addons/l10n_at_hr_payroll_private/tests/test_lst_private.py new file mode 100644 index 0000000..3b4c0ea --- /dev/null +++ b/addons/l10n_at_hr_payroll_private/tests/test_lst_private.py @@ -0,0 +1,188 @@ +# Part of the odoo-at-payroll project. License: LGPL-3. +"""GP3 Lohnsteuer-Integration auf der privatwirtschaftlichen +Structure: End-to-End-Abrechnung mit SVDN/LST-Regeln, B13 als +§-67-Bezug, Rollung, Günstig-Aufrollung, § 68-Freibetrag.""" +from datetime import date, datetime, timedelta + +from odoo.tests import TransactionCase, tagged + + +@tagged('post_install', '-at_install') +class LstPrivateTest(TransactionCase): + + def setUp(self): + super().setUp() + self.structure = self.env.ref( + 'l10n_at_hr_payroll_private.structure_at_privat') + self.kv2203 = self.env.ref( + 'l10n_at_hr_payroll_private.kv_si_2203') + self.gruppe_ii = self.env.ref( + 'l10n_at_hr_payroll_private.kv2203_grp_ii') + self.calendar = self.env['resource.calendar'].create({ + 'name': 'AT Test 40h Mo-Fr', + 'tz': 'Europe/Vienna', + 'hours_per_day': 8, + 'attendance_ids': [ + (0, 0, {'name': 'Tag %d' % wd, 'dayofweek': str(wd), + 'hour_from': 8.0, 'hour_to': 16.0}) + for wd in range(5) + ], + }) + self.env.company.resource_calendar_id = self.calendar + + def _employee(self): + employee = self.env['hr.employee'].create({ + 'name': 'Test LSt privat', + }) + version = self.env['hr.version'].search( + [('employee_id', '=', employee.id)], limit=1) + if not version: + version = self.env['hr.version'].create({ + 'employee_id': employee.id, + 'date_start': date(2020, 1, 1)}) + version.write({ + 'contract_date_start': date(2020, 1, 1), + 'kv_id': self.kv2203.id, + 'kv_gruppe_id': self.gruppe_ii.id, + 'erfahrungsstufe': 1, + 'resource_calendar_id': self.calendar.id, + }) + return employee + + def _slip(self, employee, monat, work_entries=(), confirm=False): + erster = date(2026, monat, 1) + naechster = (erster + timedelta(days=32)).replace(day=1) + slip = self.env['hr.payslip'].create({ + 'name': 'Test-LSt-Privat %d' % monat, + 'employee_id': employee.id, + 'struct_id': self.structure.id, + 'date_from': erster, + 'date_to': naechster - timedelta(days=1), + }) + for wet, tag, stunden in work_entries: + self.env['hr.work.entry'].create({ + 'name': 'Test-Eintrag', + 'version_id': slip.version_id.id, + 'employee_id': slip.employee_id.id, + 'work_entry_type_id': wet.id, + 'date': tag, + 'duration': stunden, + }) + slip.compute_sheet() + if confirm: + slip.action_payslip_done() + return slip + + def _total(self, slip, code): + return sum(slip.line_ids.filtered( + lambda l: l.code == code).mapped('total')) + + def test_01_end_to_end_november_mit_b13(self): + """Vollmonat VG II Stufe 1 mit B13: SVDN 18,07 %, LSt-lfd + (§ 66: JBG = Bemessung × 12 − 192), B13 nach § 67 (Abs 12-SV, + 620-Freibetrag, 6 %).""" + employee = self._employee() + slip = self._slip(employee, 11) + self.assertAlmostEqual(self._total(slip, 'KVGEO'), 2059.41, places=2) + self.assertAlmostEqual( + self._total(slip, 'SVDN_KV'), 2059.41 * 0.0387, places=2) + self.assertAlmostEqual( + self._total(slip, 'SVDN_PV'), 2059.41 * 0.1025, places=2) + self.assertAlmostEqual( + self._total(slip, 'SVDN_AV'), 2059.41 * 0.0295, places=2) + self.assertAlmostEqual( + self._total(slip, 'SVDN_AK'), 2059.41 * 0.005, places=2) + self.assertAlmostEqual( + self._total(slip, 'SVDN_WF'), 2059.41 * 0.005, places=2) + self.assertAlmostEqual(self._total(slip, 'B13'), 2059.41, places=2) + # LSt-lfd: Bemessung 1686,50 → JBG 20.046,06 → (1301,41 − 496)/12 + bem = 2059.41 - 2059.41 * 0.1807 + jbg = bem * 12 - 132 - 60 + erwartet_lfd = (max(0.0, 0.20 * (jbg - 13539.0) - 496.0)) / 12 + self.assertAlmostEqual( + self._total(slip, 'LST_LFD'), erwartet_lfd, places=1) + # LSt-SZ (§ 67): 2059,41 − SV-SZ (17,07 %) − 620 → 6 % + sz_bem = 2059.41 - 2059.41 * 0.1707 + erwartet_sz = (sz_bem - 620.0) * 0.06 + self.assertAlmostEqual( + self._total(slip, 'LST_SZ'), erwartet_sz, places=1) + # Netto-Konsistenz: ATP_BRUTTO − ATP_ABZUG + brutto = (self._total(slip, 'KVGEO') + self._total(slip, 'B13')) + abzug = sum( + self._total(slip, code) for code in + ('SVDN_KV', 'SVDN_PV', 'SVDN_AV', 'SVDN_AK', 'SVDN_WF', + 'LST_LFD', 'LST_SZ')) + self.assertAlmostEqual( + self._total(slip, 'NETTO'), brutto - abzug, places=2) + + def test_02_rollung_zweiter_monat(self): + """Kumulative §-66-Rollung: Februar zahlt die Differenz.""" + employee = self._employee() + slip_jan = self._slip(employee, 1, confirm=True) + jan = self._total(slip_jan, 'LST_LFD') + slip_feb = self._slip(employee, 2) + feb = self._total(slip_feb, 'LST_LFD') + self.assertAlmostEqual(feb, jan, places=2) + + def test_03_guenstig_aufrollung_b14(self): + """B13 November + B14 Dezember (ohne Urlaub): zweite SZ rechnet + die Jahres-SZ-Steuer neu (Günstig-Aufrollung, lb-son-04).""" + employee = self._employee() + self._slip(employee, 10, confirm=True) + slip_nov = self._slip(employee, 11, confirm=True) + sz_nov = self._total(slip_nov, 'LST_SZ') + sz_bem = 2059.41 - 2059.41 * 0.1707 + self.assertAlmostEqual(sz_nov, (sz_bem - 620.0) * 0.06, places=1) + slip_dez = self._slip(employee, 12) + self.assertAlmostEqual( + self._total(slip_dez, 'B14'), 2059.41, places=2) + soll_jahr = (2 * sz_bem - 620.0) * 0.06 + self.assertAlmostEqual( + self._total(slip_dez, 'LST_SZ'), soll_jahr - sz_nov, places=1) + + def test_04_ue_std_68_freibetrag(self): + """2 ÜStd Tag: UE_STD 41,19 (quantity=Stunden); §-68-Anteil + 13,73 mindert die LSt-Bemessung (§ 68 Abs 2 iVm § 124b Z 440).""" + employee = self._employee() + wet = self.env.ref('l10n_at_hr_payroll_private.wett_ue_std') + slip_ohne = self._slip(employee, 10, confirm=True) + lst_ohne = self._total(slip_ohne, 'LST_LFD') + slip_mit = self._slip(employee, 11, work_entries=[ + (wet, date(2026, 11, 5), 2.0), + ]) + self.assertAlmostEqual(self._total(slip_mit, 'UE_STD'), 41.19, places=2) + freibe = slip_mit._l10n_at_freibetraege_68() + self.assertAlmostEqual(freibe['ue_std'], 41.19 * 0.33333, places=1) + # LSt steigt (nur der nicht befreite Anteil wird besteuert) + self.assertGreater(self._total(slip_mit, 'LST_LFD'), lst_ohne) + + def test_05_wien_wf(self): + """Wiener WF-Zuschlag: SVDN_WF 0,75 % statt 0,50 %.""" + employee = self._employee() + slip = self._slip(employee, 11) + slip.company_id.write({'l10n_at_wf_wien': True}) + slip.compute_sheet() + self.assertAlmostEqual( + self._total(slip, 'SVDN_WF'), 2059.41 * 0.0075, places=2) + + def test_06_2748_november_basis_b13_dezember(self): + """2748: B13 im Dezember mit November-Basis; B14-Dezember- + fallback ohnt Urlaub läuft mit — §-67-Bemessung über beide + Bezüge (Abs 12-SV vorher).""" + employee = self._employee() + version = self.env['hr.version'].search( + [('employee_id', '=', employee.id)], limit=1) + version.write({ + 'kv_id': self.env.ref( + 'l10n_at_hr_payroll_private.kv_si_2748').id, + 'kv_gruppe_id': self.env.ref( + 'l10n_at_hr_payroll_private.kv2748_grp_ii').id, + }) + slip = self._slip(employee, 12) + self.assertAlmostEqual(self._total(slip, 'KVGEO'), 2199.15, places=2) + self.assertAlmostEqual(self._total(slip, 'B13'), 2199.15, places=2) + # B14-Dezember-Fallback (kein Urlaub im Jahr) — läuft mit + self.assertAlmostEqual(self._total(slip, 'B14'), 2199.15, places=2) + sz_bem = 2 * 2199.15 - 2 * 2199.15 * 0.1707 + self.assertAlmostEqual( + self._total(slip, 'LST_SZ'), (sz_bem - 620.0) * 0.06, places=1) \ No newline at end of file