Relative charges/allowances on document level
This commit is contained in:
22
History.md
22
History.md
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|||||||
Reference in New Issue
Block a user