Relative charges/allowances on document level

This commit is contained in:
Jochen Stärk
2020-10-08 14:51:33 +02:00
parent 66fd7b4316
commit 44c6509504
11 changed files with 131 additions and 41 deletions

View File

@@ -6,6 +6,7 @@
- removed jaxb - removed jaxb
- pushprovider - pushprovider
- new xrechnung profile - new xrechnung profile
- visualization? zugferdvisualizer?
- german bank account numbers can no longer be specified (dropped in favor of IBAN and BIC) - german bank account numbers can no longer be specified (dropped in favor of IBAN and BIC)
- factory for xrechnung - factory for xrechnung
- complete or discard read into push provider - complete or discard read into push provider
@@ -15,7 +16,7 @@
- getSellerTradePartyAddress (PR #157 ) thanks to aberndt-hub - getSellerTradePartyAddress (PR #157 ) thanks to aberndt-hub
- switched from eclipse to IntelliJ - switched from eclipse to IntelliJ
- added ph-schematron-maven-plugin so that xrechnung xslt can be generated - added ph-schematron-maven-plugin so that xrechnung xslt can be generated
- remove migration - removed migration feature (XSLT upgrade of ZF1)
- be able to recursively validate directories - be able to recursively validate directories
- be able to ignore input pdf errors with -i - be able to ignore input pdf errors with -i
- be able to recursively scan directories using validateExpectValid/validateExpectInvalid - be able to recursively scan directories using validateExpectValid/validateExpectInvalid
@@ -34,29 +35,30 @@ switch
- release notes - release notes
- new tradeparty class, Contact getOwnContact superseded by TradeParty getSender - new tradeparty class, Contact getOwnContact superseded by TradeParty getSender
- new invoicecorrection class - new invoicecorrection class
- order-x read support - order-x xml read support
- automated tests zuv/verapdf validate created library test files - automated tests zuv/verapdf validate created library test files
- trans.getTradeSettlementPayment() removed in favor of trans.getTradeSettlement() - trans.getTradeSettlementPayment() removed in favor of trans.getTradeSettlement()
- commandline option for no notices
- new features
- additional docs,
- contract id,
- delivery period,
- corrected invoices,
- contacts also for recipients
### 2.0 still todo ### 2.0 still todo
- dont show empty tax number field - dont show empty tax number field
- be able to specify iban via tradeparty object
- verapdf as prevalidation?
- visualization? zugferdvisualizer?
- new sample invoice - new sample invoice
- prompt for source file for validation has to be pdf
- be able to disable "source pdf set to timeout"
- *visualizer to work with Extended profile - *visualizer to work with Extended profile
- *visualizer tests - *visualizer tests
- *validator not to XR error on ZF files (only notices) - *validator not to XR error on ZF files (only notices)
- *from A3 does not seem tow ork see mustangreaderwriteredgetest:testedgeexport - *from A3 does not seem tow ork see mustangreaderwriteredgetest:testedgeexport
- xmp errors may not show correctly in log - xmp errors may not show correctly in log
- switch for no log and no notices
- confirm correct generation from pdf/a3 files zf2edgetest - confirm correct generation from pdf/a3 files zf2edgetest
- *correctiontest exports zf1+zf2? - *correctiontest exports zf1+zf2?
- *USt 0% wird aus invoice-klasse noch nicht sauber abgefangen - *USt 0% wird aus invoice-klasse noch nicht sauber abgefangen
- new features additional docs, contract id, periods, corrected invoices, discounts, occurrence dates and periods - absolute and relative allowances and charges on item and document level,
- finalize invoiceimporter
Alpha2 2020-09-15 Alpha2 2020-09-15
Alpha1 2020-08-06 Alpha1 2020-08-06

View File

@@ -1,5 +1,6 @@
package org.mustangproject; package org.mustangproject;
import org.mustangproject.ZUGFeRD.IAbsoluteValueProvider;
import org.mustangproject.ZUGFeRD.IExportableTransaction; import org.mustangproject.ZUGFeRD.IExportableTransaction;
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge; import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
@@ -55,27 +56,16 @@ public class Charge implements IZUGFeRDAllowanceCharge {
@Override @Override
public BigDecimal getTotalAmount(IZUGFeRDExportableItem currentItem) { public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
if (totalAmount!=null) { if (totalAmount!=null) {
return totalAmount; return totalAmount;
} else if (percent!=null) { } else if (percent!=null) {
return currentItem.getPrice().multiply(getPercent().divide(new BigDecimal(100))); return currentItem.getValue().multiply(getPercent().divide(new BigDecimal(100)));
} else { } else {
throw new RuntimeException("Either totalAmount or percent must be set"); throw new RuntimeException("Either totalAmount or percent must be set");
} }
} }
@Override
public BigDecimal getTotalAmount(IExportableTransaction currentTrans) {
// if (totalAmount!=null) {
return totalAmount;
// } else //if (percent!=null) {
// to be implemented return currentItem.get().multiply(getPercent().divide(new BigDecimal(100)));
//} else {
// throw new RuntimeException("Either totalAmount or percent must be set");
// }
}
public BigDecimal getPercent() { public BigDecimal getPercent() {
return percent; return percent;

View File

@@ -0,0 +1,27 @@
/** **********************************************************************
*
* Copyright 2018 Jochen Staerk
*
* Use is subject to license terms.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
*********************************************************************** */
package org.mustangproject.ZUGFeRD;
import java.math.BigDecimal;
public interface IAbsoluteValueProvider {
public BigDecimal getValue();
}

View File

@@ -32,7 +32,7 @@ import java.util.Date;
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
public interface IExportableTransaction { public interface IExportableTransaction {
/** /**
* appears in /rsm:CrossIndustryDocument/rsm:HeaderExchangedDocument/ram:Name * appears in /rsm:CrossIndustryDocument/rsm:HeaderExchangedDocument/ram:Name

View File

@@ -24,8 +24,7 @@ import java.math.BigDecimal;
*/ */
public interface IZUGFeRDAllowanceCharge { public interface IZUGFeRDAllowanceCharge {
BigDecimal getTotalAmount(IZUGFeRDExportableItem currentItem); BigDecimal getTotalAmount(IAbsoluteValueProvider trans);
BigDecimal getTotalAmount(IExportableTransaction trans);
String getReason(); String getReason();

View File

@@ -30,7 +30,7 @@ import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
import java.math.BigDecimal; import java.math.BigDecimal;
public interface IZUGFeRDExportableItem { public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
IZUGFeRDExportableProduct getProduct(); IZUGFeRDExportableProduct getProduct();
@@ -46,6 +46,10 @@ public interface IZUGFeRDExportableItem {
*/ */
BigDecimal getPrice(); BigDecimal getPrice();
@Override
default BigDecimal getValue() {
return getPrice();
}
/** /**
* how many get billed * how many get billed
* *

View File

@@ -38,7 +38,7 @@ import org.dom4j.io.XMLWriter;
import org.mustangproject.Invoice; import org.mustangproject.Invoice;
import org.mustangproject.XMLTools; import org.mustangproject.XMLTools;
public class ZUGFeRD2PullProvider implements IXMLProvider { public class ZUGFeRD2PullProvider implements IXMLProvider, IAbsoluteValueProvider {
//// MAIN CLASS //// MAIN CLASS
protected SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); protected SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd");
@@ -96,7 +96,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
return res; return res;
} }
//move
private BigDecimal getTotalPrepaid() { private BigDecimal getTotalPrepaid() {
if (trans.getTotalPrepaidAmount() == null) { if (trans.getTotalPrepaidAmount() == null) {
return new BigDecimal(0); return new BigDecimal(0);
@@ -121,7 +121,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges();
if ((charges != null) && (charges.length > 0)) { if ((charges != null) && (charges.length > 0)) {
for (IZUGFeRDAllowanceCharge currentCharge : charges) { for (IZUGFeRDAllowanceCharge currentCharge : charges) {
res = res.add(currentCharge.getTotalAmount(trans)); res = res.add(currentCharge.getTotalAmount(this));
} }
} }
return res; return res;
@@ -132,7 +132,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances();
if ((allowances != null) && (allowances.length > 0)) { if ((allowances != null) && (allowances.length > 0)) {
for (IZUGFeRDAllowanceCharge currentAllowance : allowances) { for (IZUGFeRDAllowanceCharge currentAllowance : allowances) {
res = res.add(currentAllowance.getTotalAmount(trans)); res = res.add(currentAllowance.getTotalAmount(this));
} }
} }
return res; return res;
@@ -183,7 +183,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (theAmount == null) { if (theAmount == null) {
theAmount = new VATAmount(new BigDecimal(0), new BigDecimal(0), "S"); theAmount = new VATAmount(new BigDecimal(0), new BigDecimal(0), "S");
} }
theAmount.setBasis(theAmount.getBasis().add(currentCharge.getTotalAmount(trans))); theAmount.setBasis(theAmount.getBasis().add(currentCharge.getTotalAmount(this)));
BigDecimal factor = currentCharge.getTaxPercent().divide(new BigDecimal(100)); BigDecimal factor = currentCharge.getTaxPercent().divide(new BigDecimal(100));
theAmount.setCalculated(theAmount.getBasis().multiply(factor)); theAmount.setCalculated(theAmount.getBasis().multiply(factor));
hm.put(currentCharge.getTaxPercent(), theAmount); hm.put(currentCharge.getTaxPercent(), theAmount);
@@ -196,7 +196,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (theAmount == null) { if (theAmount == null) {
theAmount = new VATAmount(new BigDecimal(0), new BigDecimal(0), "S"); theAmount = new VATAmount(new BigDecimal(0), new BigDecimal(0), "S");
} }
theAmount.setBasis(theAmount.getBasis().subtract(currentAllowance.getTotalAmount(trans))); theAmount.setBasis(theAmount.getBasis().subtract(currentAllowance.getTotalAmount(this)));
BigDecimal factor = currentAllowance.getTaxPercent().divide(new BigDecimal(100)); BigDecimal factor = currentAllowance.getTaxPercent().divide(new BigDecimal(100));
theAmount.setCalculated(theAmount.getBasis().multiply(factor)); theAmount.setCalculated(theAmount.getBasis().multiply(factor));
@@ -207,7 +207,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
return hm; return hm;
} }
@Override @Override
public Profile getProfile() { public Profile getProfile() {
return profile; return profile;
@@ -701,4 +700,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
return paymentTermsXml; return paymentTermsXml;
} }
@Override
public BigDecimal getValue() {
return getTotal();
}
} }

View File

@@ -27,12 +27,7 @@ public class IZUGFeRDAllowanceChargeImpl implements IZUGFeRDAllowanceCharge {
boolean isCharge=true; boolean isCharge=true;
@Override @Override
public BigDecimal getTotalAmount(IZUGFeRDExportableItem currentItem) { public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
return totalAmount;
}
@Override
public BigDecimal getTotalAmount(IExportableTransaction currentTransaction) {
return totalAmount; return totalAmount;
} }

View File

@@ -39,6 +39,7 @@ public class ZF2PushTest extends TestCase {
final String TARGET_CORRECTIONPDF = "./target/testout-ZF2PushCorrection.pdf"; final String TARGET_CORRECTIONPDF = "./target/testout-ZF2PushCorrection.pdf";
final String TARGET_ITEMCHARGESALLOWANCESPDF = "./target/testout-ZF2PushItemChargesAllowances.pdf"; final String TARGET_ITEMCHARGESALLOWANCESPDF = "./target/testout-ZF2PushItemChargesAllowances.pdf";
final String TARGET_CHARGESALLOWANCESPDF = "./target/testout-ZF2PushChargesAllowances.pdf"; final String TARGET_CHARGESALLOWANCESPDF = "./target/testout-ZF2PushChargesAllowances.pdf";
final String TARGET_RELATIVECHARGESALLOWANCESPDF = "./target/testout-ZF2PushRelativeChargesAllowances.pdf";
final String TARGET_ATTACHMENTSPDF = "./target/testout-ZF2PushAttachments.pdf"; final String TARGET_ATTACHMENTSPDF = "./target/testout-ZF2PushAttachments.pdf";
public void testPushExport() { public void testPushExport() {
@@ -233,6 +234,51 @@ public class ZF2PushTest extends TestCase {
} }
}
public void testRelativeChargesAllowancesExport() {
String orgname = "Test company";
String number = "123";
String amountStr = "3.00";
BigDecimal amount = new BigDecimal(amountStr);
try (InputStream SOURCE_PDF = this.getClass()
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
.setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).setProfile(Profiles.getByName("en16931")).ignorePDFAErrors()
.load(SOURCE_PDF)) {
ze.setTransaction(new Invoice().setCurrency("CHF").setDueDate(new Date()).setOccurrenceDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname,"teststr", "55232","teststadt","DE")).setOwnTaxID("4711").setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setNumber(number)
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)))
.addAllowance(new Allowance().setPercent(new BigDecimal(50 )).setTaxPercent(new BigDecimal(19)))
);
String theXML = new String(ze.getProvider().getXML());
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
ze.export(TARGET_RELATIVECHARGESALLOWANCESPDF);
} catch (IOException e) {
fail("IOException should not be raised in testEdgeExport");
}
// now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_RELATIVECHARGESALLOWANCESPDF);
assertFalse(zi.getUTF8().contains("EUR"));
// Reading ZUGFeRD
assertEquals("5.36", zi.getAmount());
assertEquals(zi.getHolder(), orgname);
assertEquals(zi.getForeignReference(), number);
try {
assertEquals(zi.getVersion(), 2);
} catch (Exception e) {
e.printStackTrace();
}
} }

View File

@@ -80,6 +80,25 @@ public class LibraryTest extends ResourceCase {
} }
public void testLibraryPushRelativeAllowances() {
File tempFile = new File("../library/target/testout-ZF2PushRelativeChargesAllowances.pdf");
assertTrue(tempFile.exists());
ZUGFeRDValidator zfv = new ZUGFeRDValidator();
String res = zfv.validate(tempFile.getAbsolutePath());
assertThat(res).valueByXPath("/validation/pdf/summary/@status")
.isEqualTo("valid");
assertThat(res).valueByXPath("/validation/xml/summary/@status")
.isEqualTo("valid");
assertThat(res).valueByXPath("/validation/summary/@status")
.isEqualTo("valid");
}
public void testLibraryPushAllowances() { public void testLibraryPushAllowances() {
File tempFile = new File("../library/target/testout-ZF2PushChargesAllowances.pdf"); File tempFile = new File("../library/target/testout-ZF2PushChargesAllowances.pdf");
assertTrue(tempFile.exists()); assertTrue(tempFile.exists());

View File

@@ -64,6 +64,11 @@ public class ZUGFeRDValidatorTest extends ResourceCase {
assertThat(res).valueByXPath("/validation/summary/@status") assertThat(res).valueByXPath("/validation/summary/@status")
.isEqualTo("invalid"); .isEqualTo("invalid");
zfv = new ZUGFeRDValidator();
res = zfv.validate("/does/not/exist");
assertThat(res).valueByXPath("/validation/summary/@status")
.isEqualTo("invalid");
} }
/*** /***