From 2e4ab561af85ab2cc310fc2c00d9c2096cf3f411 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Wed, 20 Aug 2025 17:45:51 +0200 Subject: [PATCH] closes #917 --- History.md | 2 +- .../java/org/mustangproject/Allowance.java | 3 +- .../main/java/org/mustangproject/Charge.java | 7 +-- .../main/java/org/mustangproject/Item.java | 3 -- .../ZUGFeRD/IAbsoluteValueProvider.java | 3 ++ .../ZUGFeRD/LineCalculator.java | 13 +---- .../ZUGFeRD/CalculationTest.java | 54 +++++++++++++++++++ 7 files changed, 65 insertions(+), 20 deletions(-) diff --git a/History.md b/History.md index 8a51971b..49adceb6 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,5 @@ - added JSONIgnore for Products intra community supply, reverse charge and invoice's isValid (which rather means isComplete, by the way) -- 917? +- #917 2.19.0 ======= diff --git a/library/src/main/java/org/mustangproject/Allowance.java b/library/src/main/java/org/mustangproject/Allowance.java index cca2033a..ab8bc8e9 100644 --- a/library/src/main/java/org/mustangproject/Allowance.java +++ b/library/src/main/java/org/mustangproject/Allowance.java @@ -39,9 +39,8 @@ public class Allowance extends Charge { return totalAmount; } else if (percent!=null) { BigDecimal singlePrice=currentItem.getValue().multiply(BigDecimal.ONE.subtract(getPercent().divide(new BigDecimal(100)))); -// BigDecimal singlePrice=currentItem.getValue().multiply(BigDecimal.ONE.subtract(getPercent().divide(new BigDecimal(100)))); BigDecimal singlePriceDiff=currentItem.getValue().subtract(singlePrice); - return singlePriceDiff; + return singlePriceDiff.multiply(currentItem.getQuantity()); } else { throw new RuntimeException("percent must be set"); } diff --git a/library/src/main/java/org/mustangproject/Charge.java b/library/src/main/java/org/mustangproject/Charge.java index 3d647757..524c8ce0 100644 --- a/library/src/main/java/org/mustangproject/Charge.java +++ b/library/src/main/java/org/mustangproject/Charge.java @@ -145,9 +145,10 @@ public class Charge implements IZUGFeRDAllowanceCharge { if(totalAmount != null) { return totalAmount; } else if (percent!=null) { - BigDecimal factor=getPercent().divide(new BigDecimal(100), 18, RoundingMode.HALF_UP); - BigDecimal singlePrice=currentItem.getValue().multiply(factor); - return singlePrice; + BigDecimal singlePrice=currentItem.getValue().multiply(BigDecimal.ONE.subtract(getPercent().divide(new BigDecimal(100), 18, RoundingMode.HALF_UP))); + BigDecimal singlePriceDiff=currentItem.getValue().subtract(singlePrice); + return singlePriceDiff.multiply(currentItem.getQuantity()); + } else { throw new RuntimeException("percent must be set"); } diff --git a/library/src/main/java/org/mustangproject/Item.java b/library/src/main/java/org/mustangproject/Item.java index b8afa6be..fabc88de 100644 --- a/library/src/main/java/org/mustangproject/Item.java +++ b/library/src/main/java/org/mustangproject/Item.java @@ -203,9 +203,6 @@ public class Item implements IZUGFeRDExportableItem { } if (amountString != null) { izac.setTotalAmount(new BigDecimal(amountString)); - if (percentString != null && (!percentString.equals("0"))) { - izac.setTotalAmount(new BigDecimal(amountString).divide(getQuantity())); - } } if (basisAmountString != null) { izac.setBasisAmount(new BigDecimal(basisAmountString)); diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IAbsoluteValueProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IAbsoluteValueProvider.java index 3c4be8b5..cf3e50dc 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IAbsoluteValueProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IAbsoluteValueProvider.java @@ -24,4 +24,7 @@ public interface IAbsoluteValueProvider { public BigDecimal getValue(); + default BigDecimal getQuantity() { + return BigDecimal.ONE; + } } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java index 50ea54ae..33f883f4 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/LineCalculator.java @@ -24,26 +24,17 @@ public class LineCalculator { if (currentItem.getItemAllowances() != null) { for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) { - BigDecimal factor=BigDecimal.ONE; BigDecimal singleAllowance=allowance.getTotalAmount(currentItem); addItemAllowance(singleAllowance); - - if ((allowance.getPercent()!=null)&&(allowance.getPercent().compareTo(BigDecimal.ZERO)!=0)) { - factor=currentItem.getQuantity(); - } - addAllowanceItemTotal(singleAllowance.multiply(factor)); + addAllowanceItemTotal(singleAllowance); } } if (currentItem.getItemCharges() != null) { for (IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) { - BigDecimal factor=BigDecimal.ONE; BigDecimal singleCharge=charge.getTotalAmount(currentItem); addItemCharge(singleCharge); - if ((charge.getPercent()!=null)&&(charge.getPercent().compareTo(BigDecimal.ZERO)!=0)) { - factor=currentItem.getQuantity(); - } - subtractAllowanceItemTotal(singleCharge.multiply(factor)); + subtractAllowanceItemTotal(singleCharge); } } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/CalculationTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/CalculationTest.java index 80bf4b35..680b312e 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/CalculationTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/CalculationTest.java @@ -302,6 +302,60 @@ public class CalculationTest extends ResourceCase { assertEquals(new BigDecimal("4.95"), calculator.getGrandTotal().stripTrailingZeros()); } + public void testSimpleItemPercentCharge() { + /*** + * a product with net 1.10 and qty 5 and relative item allowance of 10% should return 5 as line and grand total + */ + SimpleDateFormat sqlDate = new SimpleDateFormat("yyyy-MM-dd"); + + Invoice invoice = new Invoice(); + invoice.setDocumentName("Rechnung"); + invoice.setNumber("777777"); + try { + invoice.setIssueDate(sqlDate.parse("2020-12-31")); + invoice.setDetailedDeliveryPeriod(sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[0]), sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[1])); + invoice.setDeliveryDate(sqlDate.parse("2020-12-31")); + invoice.setDueDate(sqlDate.parse("2021-01-15")); + } catch (Exception e) { + LOGGER.error("Failed to set dates", e); + + } + TradeParty sender = new TradeParty("Maier GmbH", "Musterweg 5", "11111", "Testung", "DE"); + sender.addVATID("DE2222222222"); + invoice.setSender(sender); + + /* trade party (recipient) */ + TradeParty recipient = new TradeParty("Teston GmbH" + " " + "Zentrale" + " " + "", "Testweg 5", "11111", "Testung", "DE"); + recipient.setID("111111"); + recipient.addVATID("DE111111111"); + invoice.setRecipient(recipient); + + /* item */ + Product product; + Item item; + + product = new Product("AAA", "", "H87", BigDecimal.ZERO); + item = new Item(product, new BigDecimal("1.10"), new BigDecimal(5.00)); + + item.addCharge(new Charge().setPercent(new BigDecimal(10)).setTaxPercent(BigDecimal.ZERO)); + invoice.addItem(item); + + + ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider(); + zf2p.setProfile(Profiles.getByName("XRechnung")); + zf2p.generateXML(invoice); + + + String theXML = new String(zf2p.getXML()); + assertThat(theXML).valueByXPath("//*[local-name()='ActualAmount']") + .asString() + .isEqualTo("0.55");// test for issue #917 + + + TransactionCalculator calculator = new TransactionCalculator(invoice); + assertEquals(new BigDecimal("6.05"), calculator.getGrandTotal().stripTrailingZeros()); + } + public void testSimpleDocumentPercentCharge() { String orgname = "Test company";