fix: multi-tax detection and net_amount calculation#256
Conversation
Greptile SummaryThis PR fixes two bugs in e-invoice generation for Sales Invoices with multiple tax rows: incorrect basis-amount calculation for multi-rate "On Net Total" rows, and false 0% VAT rate assignment when an Item Tax Template contains a zero-rate entry for a matched account.
Confidence Score: 4/5Safe to merge for the common case the PR targets, but invoices that mix items with and without Item Tax Templates under multiple tax rates can get a wrong BasisAmount without any error signal The _sum_item_net_matching_on_net_total_rate method silently returns a partial sum when some items lack item_tax_template in a multi-tax invoice, and because the fallback chain is or-chained, a non-zero partial sum prevents the reliable calculated fallback from firing. The emitted BasisAmount would be lower than the actual taxable amount for that rate, potentially causing downstream schema validation failures. eu_einvoice/european_e_invoice/custom/sales_invoice.py — specifically the or-chain in _add_taxes_and_charges (lines 574–581) and the _sum_item_net_matching_on_net_total_rate method that feeds it Important Files Changed
|
In V16+ not_applicable is set, so it can be used as the "stronger" link, that this row should be skipped. In V15 and below, if a tax_rate is 0, it is skipped.
* feat(eu_einvoice): configurable base name for auto-attached XRechnung XML
Add optional pattern on E Invoice Settings (auto_name_format_for_xml_file) for the
file base name when auto-attaching XML on Sales Invoice submit. Empty pattern keeps
using the document name; otherwise use naming-series-style segments (dot-separated,
parse_naming_series, {field} placeholders, date tokens), strip leading # per
segment so counter-only parts do not consume Series, sanitize with get_safe_file_name,
and fall back to the document name on error.
Colocate get_xml_attachment_file_base_name with Sales Invoice custom logic and cover
naming edge cases in test_sales_invoice.py.
Refresh E Invoice Settings controller and de / template catalogs for the new strings.
* refactor(eu_einvoice): enhance download_xrechnung to use configurable base name
Update the download_xrechnung function to retrieve the Sales Invoice document
and check permissions before generating the XML file.
The filename now utilizes a configurable base name from E Invoice Settings,
improving flexibility for file naming.
This change ensures that the generated XML file adheres to the specified naming format.
* chore(eu_einvoice): update E Invoice Settings and localization files
Rearrange fields in e_invoice_settings.json for better organization, adding a label for
the XML Settings section. Update localization files (de.po and main.pot) to reflect
changes in field names and add new translations for XML Settings.
Adjust POT creation dates for consistency.
* refactor(eu_einvoice): centralize sales invoice xml stem naming
Resolve the downloadable XML filename stem in get_xml_attachment_file_base_name:
read *Auto name format for XML file* from **E Invoice Settings** when the pattern
argument is omitted, accept an optional keyword-only pattern override, and build
the stem with parse_naming_series plus a no-op number generator so naming has no
series counter DB side effects. Sanitize with get_safe_file_name and fall back to
doc.name when the pattern is empty or fails.
Call sites use the helper without duplicating settings reads. Tests pass pattern=
for empty or whitespace patterns, and assert the settings-backed path by patching
frappe.get_single_value only for **E Invoice Settings** / auto_name_format_for_xml_file.
---------
Co-authored-by: Daniel Rose <26166128+dafrose@users.noreply.github.com>
* chore: ignore translatable strings from frappe and erpnext * chore: update translations
|
Commitlint complains about a commit message body line being too long. This can be fixed with the following command: FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --msg-filter '
if test "$GIT_COMMIT" = "3171c881365067f1561dd9e7dfdb818913fc67ab"; then
cat <<EOF
chore: return to standard
In V16+ not_applicable is set, so it can be used as the "stronger" link, that this row
should be skipped. In V15 and below, if a tax_rate is 0, it is skipped.
EOF
else
cat
fi
' 3171c88^..HEADfollowed by force-push:
@barredterra: Does this need to be fixed or can the pull request be merged regardless? |
We usually squash+merge, so it should be fine. |
PR Description
This PR addresses two connected issues when generating e-invoices for Sales Invoices with multiple tax rows or configurations where a row in Sales Taxes and Charges is present but not applicable.
Example: Sales Invoice
ACC-SINV-2025-00035Expected e-invoice settlement lines:
1) Basis amount for multi-tax "On Net Total" rows
In multi-tax environments, ERPNext v15 does not provide a
net_amounton tax rows for use as the taxable basis. The existing logic relied on fallback options (hasattr(tax, "net_amount")) that could match an uninitialized or zero-valued field, resulting inbasis_amount = 0.Without this PR:
hasattr(tax, "net_amount")evaluated toTrue(for example due to a Custom Field or attribute initialization on the site), the basis could become0or any other value for both tax lines, producing an incorrect e-invoice tax basis.With this PR:
tax_amount / rate * 100(here:41.61 / 19 * 100 = 219.0and7.21 / 7 * 100 = 103.0).net_amountvalues whose resolved VAT rate matches the tax row's rate.This keeps the fast path for exact results and guarantees a correct basis when rounding would otherwise distort the taxable amount.
2) Highest non-zero rate from Item Tax Template
When multiple accounts are listed in Sales Taxes and Charges and an Item Tax Template contains a matching account with 0% tax, the old logic returned the first match, which could be 0%.
Without this PR:
tax_type= "3806 - Umsatzsteuer 19%",tax_rate= 0tax_type= "3801 - Umsatzsteuer 7%",tax_rate= 7With this PR:
tax_rate = 0are excluded in the applicable-account matching path.tax_rateis returned.income_accountis available, direct account matching is still preferred.This avoids false 0% assignments and keeps mixed-tax invoices consistent.