diff --git a/README.md b/README.md index cf8daaa..cdce845 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Add Gallop to your project via [Maven Central](https://central.sonatype.com/arti ```groovy dependencies { - implementation 'de.codebarista:gallop:2.1.0' + implementation 'de.codebarista:gallop:2.2.0' } ``` @@ -53,7 +53,7 @@ dependencies { de.codebarista gallop - 2.1.0 + 2.2.0 ``` @@ -154,7 +154,8 @@ public class InvoiceGenerator { .taxTotalAmount(new BigDecimal("100.60")) // Total VAT amount .grandTotalAmount(new BigDecimal("630.08")) // Invoice total with VAT .paidAmount(new BigDecimal("100.00")) // Already paid amount - .duePayableAmount(new BigDecimal("530.08")) // Amount due for payment + .roundingAmount(new BigDecimal("0.02")) // Rounding amount + .duePayableAmount(new BigDecimal("530.10")) // Amount due for payment // Sales order reference .salesOrderReference("SO-98765"); @@ -168,6 +169,7 @@ public class InvoiceGenerator { ### Changelog +- 2.2.0: Add BT-114 (Rounding amount) - 2.1.0: Add BT-30/BT-47 (Seller/Buyer legal registration identifier), BT-32 (Seller tax registration identifier), BT-33 (Seller additional legal information), diff --git a/build.gradle b/build.gradle index ebcc184..bedbe8d 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ plugins { } group = 'de.codebarista' -version = '2.1.0' +version = '2.2.0' java { toolchain { diff --git a/src/main/java/de/codebarista/gallop/xrechnung/XRechnungWriter.java b/src/main/java/de/codebarista/gallop/xrechnung/XRechnungWriter.java index 3538bcc..e7dff1d 100644 --- a/src/main/java/de/codebarista/gallop/xrechnung/XRechnungWriter.java +++ b/src/main/java/de/codebarista/gallop/xrechnung/XRechnungWriter.java @@ -360,6 +360,11 @@ private Element createTradeSettlement(XmlDocumentBuilder builder) { taxTotal.setTextContent(invoice.getTaxTotalAmount().toString()); sum.appendChild(taxTotal); } + if (invoice.getRoundingAmount() != null) { + Element roundingAmount = builder.createElement(NS_RAM, "RoundingAmount"); // BT-114 + roundingAmount.setTextContent(invoice.getRoundingAmount().toString()); + sum.appendChild(roundingAmount); + } Element grandTotal = builder.createElement(NS_RAM, "GrandTotalAmount"); // BT-112 if (invoice.getGrandTotalAmount() != null) { grandTotal.setTextContent(invoice.getGrandTotalAmount().toString()); diff --git a/src/main/java/de/codebarista/gallop/xrechnung/model/Invoice.java b/src/main/java/de/codebarista/gallop/xrechnung/model/Invoice.java index de3e47a..ef622b2 100644 --- a/src/main/java/de/codebarista/gallop/xrechnung/model/Invoice.java +++ b/src/main/java/de/codebarista/gallop/xrechnung/model/Invoice.java @@ -109,6 +109,11 @@ public class Invoice { */ private BigDecimal paidAmount; + /** + * The amount by which the grand total amount was rounded (BT-114) + */ + private BigDecimal roundingAmount; + /** * Amount due for payment (BT-115) */ @@ -346,6 +351,14 @@ public Invoice paidAmount(BigDecimal paidAmount) { return this; } + /** + * Sets the {@link #roundingAmount} + */ + public Invoice roundingAmount(BigDecimal roundingAmount) { + this.roundingAmount = roundingAmount; + return this; + } + /** * Sets the {@link #duePayableAmount} */ @@ -564,6 +577,13 @@ public BigDecimal getPaidAmount() { return paidAmount; } + /** + * Gets the {@link #roundingAmount}. + */ + public BigDecimal getRoundingAmount() { + return roundingAmount; + } + /** * Gets the {@link #duePayableAmount}. */ diff --git a/src/test/java/de/codebarista/gallop/xrechnung/BuildInvoiceTest.java b/src/test/java/de/codebarista/gallop/xrechnung/BuildInvoiceTest.java index 1fd128d..6c2fd3e 100644 --- a/src/test/java/de/codebarista/gallop/xrechnung/BuildInvoiceTest.java +++ b/src/test/java/de/codebarista/gallop/xrechnung/BuildInvoiceTest.java @@ -117,7 +117,8 @@ public void buildInvoice() { .taxTotalAmount(new BigDecimal("100.60")) // Total VAT amount .grandTotalAmount(new BigDecimal("630.08")) // Invoice total with VAT .paidAmount(new BigDecimal("100.00")) // Already paid amount - .duePayableAmount(new BigDecimal("530.08")) // Amount due for payment + .roundingAmount(new BigDecimal("0.02")) // Rounding amount + .duePayableAmount(new BigDecimal("530.10")) // Amount due for payment // Sales order reference .salesOrderReference("SO-98765"); diff --git a/src/test/java/de/codebarista/gallop/xrechnung/XRechnungWriterScenariosTest.java b/src/test/java/de/codebarista/gallop/xrechnung/XRechnungWriterScenariosTest.java index 6a8c28e..0b6b59a 100644 --- a/src/test/java/de/codebarista/gallop/xrechnung/XRechnungWriterScenariosTest.java +++ b/src/test/java/de/codebarista/gallop/xrechnung/XRechnungWriterScenariosTest.java @@ -50,6 +50,7 @@ public class XRechnungWriterScenariosTest { "order_with_shipping_costs_with_multiple_taxes", "order_with_tax_free_product", "order_with_already_paid_amount", + "order_with_rounding_amount", "order_without_vatid", "order_with_legal_registration_identifiers" }) diff --git a/src/test/resources/invoice/order_with_rounding_amount/invoice.json b/src/test/resources/invoice/order_with_rounding_amount/invoice.json new file mode 100644 index 0000000..d6b793e --- /dev/null +++ b/src/test/resources/invoice/order_with_rounding_amount/invoice.json @@ -0,0 +1,122 @@ +{ + "documentTypeCode": "380", + "documentId": "1012", + "leitwegId": null, + "currency": "EUR", + "paymentInstructions": { + "meansType": "10", + "meansText": "Cash on delivery", + "remittanceInfo": null, + "paymentTerms": "Die Ware bleibt, bis zur vollständigen Bezahlung, unser Eigentum.\nLeistungsdatum entspricht Rechnungsdatum", + "creditTransfers": [], + "paymentCardInformation": null, + "directDebit": null + }, + "issueDate": "2024-11-30T13:12:11.781+00:00", + "seller": { + "name": "Example Company", + "tradingName": "Examply Company Doing Things", + "vatId": "DE987654321", + "electronicAddress": "mail@company.com", + "electronicAddressScheme": "EM", + "address": { + "addressLineOne": "Tribute Avenue 777", + "addressLineTwo": null, + "addressLineThree": null, + "city": "Taxora", + "zipCode": "12345", + "countryIsoCode": "DE" + }, + "contact": { + "name": "Kim Elliot", + "phone": "123456789", + "email": "mail@company.com" + } + }, + "buyer": { + "name": "Test Test", + "tradingName": null, + "vatId": null, + "electronicAddress": "test@test.test", + "electronicAddressScheme": null, + "address": { + "addressLineOne": "Test", + "addressLineTwo": null, + "addressLineThree": null, + "city": "Foo", + "zipCode": "11223", + "countryIsoCode": "BH" + }, + "contact": null + }, + "deliveryInfo": { + "name": "Test Test", + "deliveryAddress": { + "addressLineOne": "Test", + "addressLineTwo": null, + "addressLineThree": null, + "city": "Foo", + "zipCode": "11223", + "countryIsoCode": "BH" + }, + "actualDeliveryDate": null + }, + "items": [ + { + "id": 1, + "quantity": 1, + "unitCode": "XPP", + "itemTotalNetAmount": 16.80, + "name": "Main product with properties", + "description": null, + "unitPrice": 16.8000, + "vat": { + "rate": 19, + "category": "S", + "taxableAmount": null, + "taxAmount": null, + "vatExemptionReasonText": null, + "vatExemptionReasonCode": null + }, + "sellerAssignedId": "10007.1", + "itemAttributes": [ + { + "name": "Size", + "value": "S" + } + ], + "netAmount": 16.80 + } + ], + "vatTotals": [ + { + "rate": 19, + "category": "S", + "taxableAmount": 16.80, + "taxAmount": 3.19, + "vatExemptionReasonText": null, + "vatExemptionReasonCode": null + } + ], + "precedingInvoiceReferences": [], + "lineTotalAmount": 16.80, + "allowanceTotalAmount": 0.00, + "chargeTotalAmount": 0.00, + "taxBasisTotalAmount": 16.80, + "taxTotalAmount": 3.19, + "grandTotalAmount": 19.99, + "roundingAmount": 0.01, + "paidAmount": 10.00, + "duePayableAmount": 10.00, + "salesOrderReference": "10000", + "invoiceNotes": [], + "allowances": [], + "charges": [ + { + "netAmount": 0.00, + "vatCategory": "S", + "vatRate": 19, + "reason": "Shipping costs" + } + ] +} diff --git a/src/test/resources/invoice/order_with_rounding_amount/xrechnung.xml b/src/test/resources/invoice/order_with_rounding_amount/xrechnung.xml new file mode 100644 index 0000000..9bf4f41 --- /dev/null +++ b/src/test/resources/invoice/order_with_rounding_amount/xrechnung.xml @@ -0,0 +1,148 @@ + + + + + urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 + + + urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0 + + + + 1012 + 380 + + 20241130 + + + + + + 1 + + + 10007.1 + Main product with properties + + Size + S + + + + + 16.8000 + 1 + + + + 1 + + + + VAT + S + 19 + + + 16.80 + + + + + N/A + + Example Company + + Kim Elliot + + 123456789 + + + mail@company.com + + + + 12345 + Tribute Avenue 777 + Taxora + DE + + + mail@company.com + + + DE987654321 + + + + Test Test + + 11223 + Test + Foo + BH + + + test@test.test + + + + 10000 + + + + + Test Test + + 11223 + Test + Foo + BH + + + + + EUR + + 10 + Cash on delivery + + + 3.19 + VAT + 16.80 + S + 19 + + + + true + + 0.00 + Shipping costs + + VAT + S + 19 + + + + Die Ware bleibt, bis zur vollständigen Bezahlung, unser Eigentum. +Leistungsdatum entspricht Rechnungsdatum + + + 16.80 + 0.00 + 0.00 + 16.80 + 3.19 + 0.01 + 19.99 + 10.00 + 10.00 + + + +