more self-contained; add 2025/2026 payroll tax calculations - #69
more self-contained; add 2025/2026 payroll tax calculations#69flottokarotto wants to merge 9 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR enhances the project by adding support for 2025 and 2026 German payroll tax calculations, improving build reproducibility, and reducing external dependencies during builds. The changes make the fork more self-contained by caching downloads, tracking generated artifacts in version control, and compiling XSLT transformations as part of the build process.
- Added BMF PAP support for tax years 2025 and 2026
- Improved build system to cache downloads and skip existing files
- Made TypeScript builds compatible with native compilation by exposing required static metadata
- Included generated build artifacts in version control
Reviewed changes
Copilot reviewed 16 out of 177 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| build/unpacked/Lohnsteuer2017Big.xml | Added generated 2017 tax calculation XML artifact |
| build/unpacked/Lohnsteuer2016Big.xml | Added generated 2016 tax calculation XML artifact |
| build/unpacked/Lohnsteuer2015DezemberBig.xml | Added generated December 2015 tax calculation XML artifact |
| build/ts-for-native-create.js | Modified visibility of static fields from private to public for native TypeScript builds |
| build/create-ts.js | Enhanced build script to download 2025/2026 tax files and cache downloads, replacing library-based file operations with fs-extra |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <INPUT name="JVBEZ" type="BigDecimal"/> | ||
|
|
||
| <!--Merker für die Vorsorgepauschale | ||
| 2 = der Arbeitnehmer ist NICCHT in der gesetzlichen Rentenversicherung versichert. |
There was a problem hiding this comment.
Corrected spelling of 'NICCHT' to 'NICHT'.
| 2 = der Arbeitnehmer ist NICCHT in der gesetzlichen Rentenversicherung versichert. | |
| 2 = der Arbeitnehmer ist NICHT in der gesetzlichen Rentenversicherung versichert. |
| const xmlFileName = 'Lohnsteuer2023JanuarBig.xml'; | ||
| if (!xmlFileNames.includes(xmlFileName)) { | ||
| resolve(xmlFileNames); | ||
| return; | ||
| } | ||
| console.log('replace: ' + xmlFileName); | ||
| const xmlPath = path.join(dirPath, xmlFileName); | ||
| fs.readFile(xmlPath, 'utf8') | ||
| .then(content => { | ||
| const updated = content.replace(/Lohnsteuer2023Big/g, 'Lohnsteuer2023JanuarBig'); | ||
| if (updated === content) { | ||
| return; | ||
| } | ||
| return fs.writeFile(xmlPath, updated, 'utf8'); | ||
| }) |
There was a problem hiding this comment.
The refactored code no longer handles multiple file replacements as the original code did with forEach. If additional files need similar name replacements in the future, this single-file approach will require modification. Consider documenting this limitation or making the replacement logic more generic.
| const xmlFileName = 'Lohnsteuer2023JanuarBig.xml'; | |
| if (!xmlFileNames.includes(xmlFileName)) { | |
| resolve(xmlFileNames); | |
| return; | |
| } | |
| console.log('replace: ' + xmlFileName); | |
| const xmlPath = path.join(dirPath, xmlFileName); | |
| fs.readFile(xmlPath, 'utf8') | |
| .then(content => { | |
| const updated = content.replace(/Lohnsteuer2023Big/g, 'Lohnsteuer2023JanuarBig'); | |
| if (updated === content) { | |
| return; | |
| } | |
| return fs.writeFile(xmlPath, updated, 'utf8'); | |
| }) | |
| // Define replacement rules: { fileName, searchValue, replaceValue } | |
| const replacementRules = [ | |
| { | |
| fileName: 'Lohnsteuer2023JanuarBig.xml', | |
| searchValue: /Lohnsteuer2023Big/g, | |
| replaceValue: 'Lohnsteuer2023JanuarBig' | |
| } | |
| // Add more rules here as needed | |
| ]; | |
| // Filter rules to only those files that exist in xmlFileNames | |
| const applicableRules = replacementRules.filter(rule => xmlFileNames.includes(rule.fileName)); | |
| if (applicableRules.length === 0) { | |
| resolve(xmlFileNames); | |
| return; | |
| } | |
| // Apply all replacements in parallel | |
| Promise.all(applicableRules.map(rule => { | |
| console.log('replace: ' + rule.fileName); | |
| const xmlPath = path.join(dirPath, rule.fileName); | |
| return fs.readFile(xmlPath, 'utf8') | |
| .then(content => { | |
| const updated = content.replace(rule.searchValue, rule.replaceValue); | |
| if (updated === content) { | |
| return; | |
| } | |
| return fs.writeFile(xmlPath, updated, 'utf8'); | |
| }); | |
| })) |
| import fetch from 'node-fetch'; | ||
| import * as path from 'path'; | ||
| import replaceInFiles from 'replace-in-files'; | ||
| import fs from 'fs-extra'; |
There was a problem hiding this comment.
The replacement of 'replace-in-files' with 'fs-extra' is a significant dependency change that should be documented in the package.json or migration notes. This change affects how file operations are performed throughout the build process.
This PR collects a set of changes I made while working on my fork. Not everything here may be useful or desirable for the upstream/original project, but it makes this fork more self-contained and reproducible.
What changed
Added support for the BMF PAPs for 2025 and 2026, including generated outputs in dist/.
Improved build reliability by compiling the XSLT step as part of the build (compile-only) and by using a local TypeScript dev dependency.
Made the generator more robust (cached downloads / skip if files already exist; avoids known naming collisions).
Fixed native TypeScript build issues by exposing required static metadata.
Tracked build/unpacked/ so the fork is less dependent on runtime downloads/external availability.
Why
This fork should be less dependent on downloads and external endpoints during build/generation.
It should provide working tax calculations for 2025 and 2026 out of the box.
How to test
Notes / Disclaimer
Some commits add large generated artifacts (build/unpacked/, dist/). Upstream may prefer keeping these out of version control; this fork intentionally includes them to reduce external dependencies.