Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Having two items with different VATs and adding a charge/allowance will generate an invalid or wrong XML #640

Open
FrankHossfeld opened this issue Jan 2, 2025 · 2 comments

Comments

@FrankHossfeld
Copy link

FrankHossfeld commented Jan 2, 2025

It looks like that there is an issue when having an invoice with two items and different VAT. Adding a charge/allowance will generate an invalid XML or has a wrong calculation. A n invoice where all items have the same VAT works as expected.

Generate an invoice with the following two items:

  • item 1: quantity: 10, price: 10, VAT 19 %

  • item 2: quantity: 1, price: 10, VAT: 19 %

  • invoice with two items and same VAT without a charge/allowance -> works (XML is valid)

  • invoice with two items and same VAT with a charge/allowance -> works (XML is valid)

  • invoice with two items (one item 19% VAT, second 7 % VAT) without a charge/allowance -> works (XML is valid)

  • invoice with two items (one item 19% VAT, second 7 % VAT) with a charge/allowance -> works (XML is invalid or calculation is wrong depending on the input)

  1. Setting up a charge with reason and percent and without VAT will result in an invalid XML
  2. Setting up a charge with reason, percent and VAT will result in an valid XML but a wrong calculation

In the first case the XML for the charges look like this:

      <ram:SpecifiedTradeAllowanceCharge>
        <ram:ChargeIndicator>
          <udt:Indicator>true</udt:Indicator>
        </ram:ChargeIndicator>
        <ram:ActualAmount>11.00</ram:ActualAmount>
        <ram:Reason>Teuerungszuschlag</ram:Reason>
        <ram:CategoryTradeTax>
          <ram:TypeCode>VAT</ram:TypeCode>
          <ram:CategoryCode>S</ram:CategoryCode>
          <ram:RateApplicablePercent>0.00</ram:RateApplicablePercent>
        </ram:CategoryTradeTax>
      </ram:SpecifiedTradeAllowanceCharge>

The XML is invalid due to the fact that the tax percents are missing/is by default BigDEcimal.ZERO.

In the second case adding two charges (one for VAT 19% and a second one for 7 %) generates the following XML:

      <ram:SpecifiedTradeAllowanceCharge>
        <ram:ChargeIndicator>
          <udt:Indicator>true</udt:Indicator>
        </ram:ChargeIndicator>
        <ram:ActualAmount>11.00</ram:ActualAmount>
        <ram:Reason>Teuerungszuschlag</ram:Reason>
        <ram:CategoryTradeTax>
          <ram:TypeCode>VAT</ram:TypeCode>
          <ram:CategoryCode>S</ram:CategoryCode>
          <ram:RateApplicablePercent>7.00</ram:RateApplicablePercent>
        </ram:CategoryTradeTax>
      </ram:SpecifiedTradeAllowanceCharge>
      <ram:SpecifiedTradeAllowanceCharge>
        <ram:ChargeIndicator>
          <udt:Indicator>true</udt:Indicator>
        </ram:ChargeIndicator>
        <ram:ActualAmount>11.00</ram:ActualAmount>
        <ram:Reason>Teuerungszuschlag</ram:Reason>
        <ram:CategoryTradeTax>
          <ram:TypeCode>VAT</ram:TypeCode>
          <ram:CategoryCode>S</ram:CategoryCode>
          <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
        </ram:CategoryTradeTax>
      </ram:SpecifiedTradeAllowanceCharge>

Now, the XML is valid, but the totalamount is now the amount of all items and not the sum of items with VAT 19 % or VAT 7%.

Expected behavior

Setting up a charge using

          invoice.addAllowance(new Allowance().setReason(model.getText())
                                              .setPercent(model.getValue()));

should result in the following XML:

      <ram:SpecifiedTradeAllowanceCharge>
        <ram:ChargeIndicator>
          <udt:Indicator>true</udt:Indicator>
        </ram:ChargeIndicator>
        <ram:ActualAmount>1.00</ram:ActualAmount>
        <ram:Reason>charge me</ram:Reason>
        <ram:CategoryTradeTax>
          <ram:TypeCode>VAT</ram:TypeCode>
          <ram:CategoryCode>S</ram:CategoryCode>
          <ram:RateApplicablePercent>7.00</ram:RateApplicablePercent>
        </ram:CategoryTradeTax>
      </ram:SpecifiedTradeAllowanceCharge>
      <ram:SpecifiedTradeAllowanceCharge>
        <ram:ChargeIndicator>
          <udt:Indicator>true</udt:Indicator>
        </ram:ChargeIndicator>
        <ram:ActualAmount>10.00</ram:ActualAmount>
        <ram:Reason>charge me</ram:Reason>
        <ram:CategoryTradeTax>
          <ram:TypeCode>VAT</ram:TypeCode>
          <ram:CategoryCode>S</ram:CategoryCode>
          <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
        </ram:CategoryTradeTax>
      </ram:SpecifiedTradeAllowanceCharge>

macOS, Java 17 & version 2.15.2

@FrankHossfeld FrankHossfeld changed the title Having two items with different VATs and adding a charge/allowance will generate a invalid XML Having two items with different VATs and adding a charge/allowance will generate an invalid XML Jan 2, 2025
@FrankHossfeld
Copy link
Author

FrankHossfeld commented Jan 2, 2025

I looked into the code and I think the problem is related to the fact, that the getTotal-method inside the TransactionCalculator-class does not respect the the VAT, the charge is calculated for.

In the method getVATPercentAmountMap charges and allowance will be calculated using this code (showing it for charges):

    IZUGFeRDAllowanceCharge[] charges = this.trans.getZFCharges();
    if (charges != null && charges.length > 0) {
      for(IZUGFeRDAllowanceCharge currentCharge : charges) {
        BigDecimal taxPercent = currentCharge.getTaxPercent();
        if (taxPercent != null) {
          VATAmount theAmount = (VATAmount)hm.get(taxPercent.stripTrailingZeros());
          if (theAmount == null) {
            theAmount = new VATAmount(BigDecimal.ZERO, BigDecimal.ZERO, currentCharge.getCategoryCode() != null ? currentCharge.getCategoryCode() : "S", vatDueDateTypeCode);
          }

          theAmount.setBasis(theAmount.getBasis().add(currentCharge.getTotalAmount(this)));
          BigDecimal factor = taxPercent.divide(new BigDecimal(100));
          theAmount.setCalculated(theAmount.getBasis().multiply(factor));
          hm.put(taxPercent.stripTrailingZeros(), theAmount);
        }
      }
    }

First confusing part is, that the charges needs to have set the taxPercent. where as all VATs can be get from the keys of the hm-map. So there is no need to add the taxPercent to the charges class. Actually if not set, BigDecimal.ZERO is used as taxPercent.

Second, if percent are set inside the Charges-class, the line of code will be used to calculate the total amount:

      return currentItem.getValue().multiply(this.getPercent().divide(new BigDecimal(100)));

This code is problematic, because currentItem.getValue()will call the method inside the TransactionCalculator-class, which calls getTotal() (line 162) which will return the amount for all items without respecting the VAT. This will cause problems, in case items have different VATs.

Setting the totalAmount to the calculated charge will work as expected.

In case it is a bug, I can create a PR.

@FrankHossfeld FrankHossfeld changed the title Having two items with different VATs and adding a charge/allowance will generate an invalid XML Having two items with different VATs and adding a charge/allowance will generate an invalid or wrong XML Jan 2, 2025
@jstaerk
Copy link
Collaborator

jstaerk commented Jan 7, 2025

Hi,
would you maybe have a short source code snippet available which I could use to
validate the issue and make a testcase out of it?
thanks
Jochen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants