Merge branch 'master' into bugfix/issue841b
This commit is contained in:
@@ -38,7 +38,7 @@ public class Allowance extends Charge {
|
||||
if(totalAmount != null) {
|
||||
return totalAmount;
|
||||
} else if (percent!=null) {
|
||||
BigDecimal singlePrice=currentItem.getValue().divide(BigDecimal.ONE.add(getPercent().divide(new BigDecimal(100))), 18, RoundingMode.HALF_UP);
|
||||
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;
|
||||
|
||||
@@ -145,10 +145,9 @@ public class Charge implements IZUGFeRDAllowanceCharge {
|
||||
if(totalAmount != null) {
|
||||
return totalAmount;
|
||||
} else if (percent!=null) {
|
||||
BigDecimal singlePrice=currentItem.getValue().divide(BigDecimal.ONE.add(getPercent().divide(new BigDecimal(100))), 18, RoundingMode.HALF_UP);
|
||||
// BigDecimal singlePrice=currentItem.getValue().multiply(BigDecimal.ONE.subtract(getPercent().divide(new BigDecimal(100))));
|
||||
BigDecimal singlePriceDiff=currentItem.getValue().add(singlePrice);
|
||||
return singlePriceDiff;
|
||||
BigDecimal factor=getPercent().divide(new BigDecimal(100), 18, RoundingMode.HALF_UP);
|
||||
BigDecimal singlePrice=currentItem.getValue().multiply(factor);
|
||||
return singlePrice;
|
||||
} else {
|
||||
throw new RuntimeException("percent must be set");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.mustangproject.Exceptions;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
/***
|
||||
* will be thrown if an invoice cant be reproduced numerically
|
||||
* ArithmetricException for backwards compatibility, was a spelling error
|
||||
*/
|
||||
public class ArithmeticException extends ArithmetricException {
|
||||
public ArithmeticException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ArithmeticException(String details) {
|
||||
super(details);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.text.ParseException;
|
||||
|
||||
/***
|
||||
* will be thrown if an invoice cant be reproduced numerically
|
||||
* (deprecated, because of typo)
|
||||
*/
|
||||
public class ArithmetricException extends ParseException {
|
||||
public ArithmetricException() {
|
||||
|
||||
@@ -591,11 +591,7 @@ public class Invoice implements IExportableTransaction {
|
||||
* @return fluent setter
|
||||
*/
|
||||
public Invoice setZFAllowances(Allowance[] iza) {
|
||||
Allowances=new ArrayList<>();
|
||||
|
||||
for (IZUGFeRDAllowanceCharge cz:iza) {
|
||||
Allowances.add(cz);
|
||||
}
|
||||
Allowances=new ArrayList<>(Arrays.asList(iza));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -616,9 +612,7 @@ public class Invoice implements IExportableTransaction {
|
||||
*/
|
||||
public Invoice setZFCharges(Charge[] iza) {
|
||||
Charges=new ArrayList<>();
|
||||
for (IZUGFeRDAllowanceCharge cz:iza) {
|
||||
Charges.add(cz);
|
||||
}
|
||||
Charges.addAll(Arrays.asList(iza));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.mustangproject;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import org.mustangproject.ZUGFeRD.IReferencedDocument;
|
||||
@@ -77,20 +78,21 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
icnm.getAsString("Name").ifPresent(product::setName);
|
||||
icnm.getAsString("Description").ifPresent(product::setDescription);
|
||||
|
||||
icnm.getAsNodeMap("SellersItemIdentification").ifPresent(SellersItemIdentification -> {
|
||||
SellersItemIdentification.getAsString("ID").ifPresent(product::setSellerAssignedID);
|
||||
});
|
||||
icnm.getAsNodeMap("SellersItemIdentification")
|
||||
.flatMap(SellersItemIdentification -> SellersItemIdentification.getAsString("ID"))
|
||||
.ifPresent(product::setSellerAssignedID);
|
||||
|
||||
icnm.getAsNodeMap("BuyersItemIdentification").ifPresent(BuyersItemIdentification -> {
|
||||
BuyersItemIdentification.getAsString("ID").ifPresent(product::setBuyerAssignedID);
|
||||
});
|
||||
icnm.getAsNodeMap("BuyersItemIdentification")
|
||||
.flatMap(BuyersItemIdentification -> BuyersItemIdentification.getAsString("ID"))
|
||||
.ifPresent(product::setBuyerAssignedID);
|
||||
|
||||
icnm.getAsNodeMap("ClassifiedTaxCategory").flatMap(m -> m.getAsBigDecimal("Percent"))
|
||||
icnm.getAsNodeMap("ClassifiedTaxCategory")
|
||||
.flatMap(m -> m.getAsBigDecimal("Percent"))
|
||||
.ifPresent(product::setVATPercent);
|
||||
});
|
||||
itemMap.getAsNodeMap("AssociatedDocumentLineDocument").ifPresent(icnm -> {
|
||||
icnm.getAsString("LineID").ifPresent(this::setId);
|
||||
});
|
||||
itemMap.getAsNodeMap("AssociatedDocumentLineDocument")
|
||||
.flatMap(icnm -> icnm.getAsString("LineID"))
|
||||
.ifPresent(this::setId);
|
||||
|
||||
itemMap.getAsNodeMap("Price").ifPresent(icnm -> {
|
||||
// ubl
|
||||
@@ -118,10 +120,16 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
itemMap.getAsString("ID")
|
||||
.ifPresent(this::setId);
|
||||
|
||||
|
||||
itemMap.getAsString("Note")
|
||||
.ifPresent(this::addNote);
|
||||
|
||||
if (product==null) { // CII
|
||||
if (itemMap.getNode("SpecifiedTradeProduct").isPresent()) {
|
||||
product = new Product(itemMap.getNode("SpecifiedTradeProduct").get());
|
||||
} else {
|
||||
product = new Product();
|
||||
}
|
||||
}
|
||||
|
||||
itemMap.getAsNodeMap("SpecifiedLineTradeAgreement", "SpecifiedSupplyChainTradeAgreement").ifPresent(icnm -> {
|
||||
icnm.getAsNodeMap("BuyerOrderReferencedDocument")
|
||||
@@ -136,14 +144,29 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
npptpNodes.getAsBigDecimal("ChargeAmount").ifPresent(this::setPrice);
|
||||
npptpNodes.getAsBigDecimal("BasisQuantity").ifPresent(this::setBasisQuantity);
|
||||
});
|
||||
icnm.getAsNodeMap("GrossPriceProductTradePrice").ifPresent(gpptpNodes -> {
|
||||
gpptpNodes.getAsNodeMap("AppliedTradeAllowanceCharge").ifPresent(gpptpAtacNodes -> {
|
||||
|
||||
/** mustang attributes differences between net and gross price to the product */
|
||||
String chargeIndicator = gpptpAtacNodes.getAsStringOrNull("ChargeIndicator");
|
||||
if ((chargeIndicator != null)&&(gpptpAtacNodes.getAsBigDecimal("ActualAmount").isPresent())) {
|
||||
BigDecimal actual = gpptpAtacNodes.getAsBigDecimal("ActualAmount").get();
|
||||
if (chargeIndicator.equals("true")) {
|
||||
product.addCharge(new Charge(actual));
|
||||
setPrice(getPrice().subtract(actual)); // the gross price affects the net price, which is read,
|
||||
// so if we do not ignore charges|allowances we have to re-compensate the net price
|
||||
} else {
|
||||
product.addAllowance(new Allowance(actual));
|
||||
setPrice(getPrice().add(actual));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
icnm.getAllNodes("AdditionalReferencedDocument").map(ReferencedDocument::fromNode).
|
||||
forEach(this::addReferencedDocument);
|
||||
});
|
||||
|
||||
itemMap.getNode("SpecifiedTradeProduct").map(Product::new).ifPresent(this::setProduct);//CII
|
||||
itemMap.getNode("SpecifiedTradeProduct").map(Product::new).ifPresent(this::setProduct);//UBL
|
||||
|
||||
// RequestedQuantity is for Order-X, BilledQuantity for FX and ZF
|
||||
itemMap.getAsNodeMap("SpecifiedLineTradeDelivery", "SpecifiedSupplyChainTradeDelivery")
|
||||
.flatMap(icnm -> icnm.getNode("BilledQuantity", "RequestedQuantity", "DespatchedQuantity"))
|
||||
@@ -180,7 +203,7 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
}
|
||||
if (amountString != null) {
|
||||
izac.setTotalAmount(new BigDecimal(amountString));
|
||||
if (percentString!=null&&(percentString!="0")) {
|
||||
if (percentString != null && (!percentString.equals("0"))) {
|
||||
izac.setTotalAmount(new BigDecimal(amountString).divide(getQuantity()));
|
||||
}
|
||||
}
|
||||
@@ -210,16 +233,16 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
|
||||
icnm.getAllNodes("AdditionalReferencedDocument").map(ReferencedDocument::fromNode).forEach(this::addAdditionalReference);
|
||||
|
||||
icnm.getAsString("ReceivableSpecifiedTradeAccountingAccount").ifPresent(s -> this.accountingReference = s == null ? null : s.trim());
|
||||
icnm.getAsString("ReceivableSpecifiedTradeAccountingAccount").ifPresent(s -> this.accountingReference = s.trim());
|
||||
|
||||
icnm.getAsNodeMap("BillingSpecifiedPeriod").ifPresent(periodNode -> {
|
||||
Date start = periodNode.getAsNodeMap("StartDateTime").flatMap(dateTimeNode -> dateTimeNode.getNode("DateTimeString")).map(dts -> XMLTools.tryDate(dts)).orElse(null);
|
||||
Date end = periodNode.getAsNodeMap("EndDateTime").flatMap(dateTimeNode -> dateTimeNode.getNode("DateTimeString")).map(dts -> XMLTools.tryDate(dts)).orElse(null);
|
||||
Date start = periodNode.getAsNodeMap("StartDateTime").flatMap(dateTimeNode -> dateTimeNode.getNode("DateTimeString")).map(XMLTools::tryDate).orElse(null);
|
||||
Date end = periodNode.getAsNodeMap("EndDateTime").flatMap(dateTimeNode -> dateTimeNode.getNode("DateTimeString")).map(XMLTools::tryDate).orElse(null);
|
||||
setDetailedDeliveryPeriod(start, end);
|
||||
});
|
||||
});
|
||||
|
||||
itemMap.getAllNodes("AllowanceCharge").map(NodeMap::new).forEach(stac -> { //UBL
|
||||
itemMap.getAllNodes("AllowanceCharge").map(NodeMap::new).forEach(stac -> { //CII
|
||||
|
||||
String isChargeString = stac.getAsString("ChargeIndicator").get();
|
||||
String percentString = stac.getAsStringOrNull("MultiplierFactorNumeric");
|
||||
@@ -301,13 +324,17 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public IZUGFeRDAllowanceCharge[] getAllowances() {
|
||||
IZUGFeRDAllowanceCharge[] izac=new IZUGFeRDAllowanceCharge[Allowances.size()];
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public IZUGFeRDAllowanceCharge[] getAllowances() { // in JSON is already returned as itemAllowances (and only read from there)
|
||||
IZUGFeRDAllowanceCharge[] izac = new IZUGFeRDAllowanceCharge[Allowances.size()];
|
||||
return Allowances.toArray(izac);
|
||||
}
|
||||
|
||||
@Override public IZUGFeRDAllowanceCharge[] getCharges() {
|
||||
IZUGFeRDAllowanceCharge[] izac=new IZUGFeRDAllowanceCharge[Charges.size()];
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public IZUGFeRDAllowanceCharge[] getCharges() { // in JSON is already returned as itemAllowances (and only read from there)
|
||||
IZUGFeRDAllowanceCharge[] izac = new IZUGFeRDAllowanceCharge[Charges.size()];
|
||||
return Charges.toArray(izac);
|
||||
}
|
||||
|
||||
@@ -425,9 +452,7 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
public void setItemAllowances(ArrayList<Allowance> theAllowances) {
|
||||
if (theAllowances != null) {
|
||||
Allowances.clear();
|
||||
for (Allowance theAllowance : theAllowances) {
|
||||
Allowances.add(theAllowance);
|
||||
}
|
||||
Allowances.addAll(theAllowances);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,9 +462,7 @@ public class Item implements IZUGFeRDExportableItem {
|
||||
public void setItemCharges(ArrayList<Charge> theCharges) {
|
||||
if (theCharges != null) {
|
||||
Charges.clear();
|
||||
for (Charge theCharge : theCharges) {
|
||||
Charges.add(theCharge);
|
||||
}
|
||||
Charges.addAll(theCharges);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package org.mustangproject;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
import com.fasterxml.jackson.annotation.*;
|
||||
import org.mustangproject.ZUGFeRD.IDesignatedProductClassification;
|
||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableProduct;
|
||||
import org.mustangproject.util.NodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@@ -107,7 +104,10 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
classifications.add(new DesignatedProductClassification(classCode, className)));
|
||||
});
|
||||
|
||||
nodeMap.getAsString("OriginTradeCounty").ifPresent(this::setCountryOfOrigin);
|
||||
nodeMap.getAsNodeMap("OriginTradeCountry")
|
||||
.flatMap(nodes -> nodes.getNode("ID"))
|
||||
.map(Node::getTextContent)
|
||||
.ifPresent(this::setCountryOfOrigin);
|
||||
}
|
||||
|
||||
/***
|
||||
@@ -406,6 +406,16 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Jackson courtesy function, please use addCharge if you have the choice
|
||||
* @return array of or null, if none
|
||||
*/
|
||||
public Product setCharges(ArrayList<Charge> charges) {
|
||||
this.charges=charges;
|
||||
return this;
|
||||
}
|
||||
|
||||
/***
|
||||
* returns the AppliedTradeAllowanceCharges of this product which are actually Charges
|
||||
* @return array of or null, if none
|
||||
@@ -432,5 +442,13 @@ public class Product implements IZUGFeRDExportableProduct {
|
||||
return allowances.toArray(allowanceArr);
|
||||
}
|
||||
|
||||
/***
|
||||
* Jackson courtesy function, please use addAllowance if you have the choice
|
||||
* @return array of or null, if none
|
||||
*/
|
||||
public Product setAllowances(ArrayList<Allowance> allowances) {
|
||||
this.allowances=allowances;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -541,6 +541,32 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
|
||||
return this;
|
||||
}
|
||||
|
||||
/***
|
||||
* for jackson, primarily, use addGlobalID(SchemedID) instead
|
||||
* @param ID the id part without scheme
|
||||
* @return fluent setter
|
||||
*/
|
||||
public TradeParty setGlobalID(String ID) {
|
||||
if (globalId==null) {
|
||||
globalId=new SchemedID();
|
||||
}
|
||||
globalId.setId(ID);
|
||||
return this;
|
||||
}
|
||||
|
||||
/***
|
||||
* for jackson, primarily, use addGlobalID(SchemedID) instead
|
||||
* @param scheme the scheme part without id
|
||||
* @return fluent setter
|
||||
*/
|
||||
public TradeParty setGlobalIDScheme(String scheme) {
|
||||
if (globalId==null) {
|
||||
globalId=new SchemedID();
|
||||
}
|
||||
globalId.setScheme(scheme);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TradeParty addGlobalID(SchemedID schemedID) {
|
||||
globalId = schemedID;
|
||||
return this;
|
||||
@@ -746,7 +772,7 @@ public class TradeParty implements IZUGFeRDExportableTradeParty {
|
||||
if (bankDetails.isEmpty() && debitDetails.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
List<IZUGFeRDTradeSettlement> tradeSettlements = Stream.concat(bankDetails.stream(), debitDetails.stream()).map(IZUGFeRDTradeSettlement.class::cast).collect(Collectors.toList());
|
||||
List<IZUGFeRDTradeSettlement> tradeSettlements = Stream.concat(bankDetails.stream(), debitDetails.stream()).collect(Collectors.toList());
|
||||
|
||||
IZUGFeRDTradeSettlement[] result = new IZUGFeRDTradeSettlement[tradeSettlements.size()];
|
||||
for (int i = 0; i < tradeSettlements.size(); i++) {
|
||||
|
||||
@@ -97,12 +97,12 @@ public class DAPullProvider extends ZUGFeRD2PullProvider {
|
||||
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
|
||||
}
|
||||
String allowanceChargeStr = "";
|
||||
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
|
||||
if (currentItem.getItemAllowances() != null) {
|
||||
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
|
||||
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
|
||||
}
|
||||
}
|
||||
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
||||
if (currentItem.getItemCharges() != null) {
|
||||
for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
||||
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class LineCalculator {
|
||||
|
||||
public LineCalculator(IZUGFeRDExportableItem currentItem) {
|
||||
|
||||
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
|
||||
if (currentItem.getItemAllowances() != null) {
|
||||
for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
|
||||
BigDecimal factor=BigDecimal.ONE;
|
||||
BigDecimal singleAllowance=allowance.getTotalAmount(currentItem);
|
||||
@@ -35,7 +35,7 @@ public class LineCalculator {
|
||||
|
||||
}
|
||||
}
|
||||
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
||||
if (currentItem.getItemCharges() != null) {
|
||||
for (IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
||||
BigDecimal factor=BigDecimal.ONE;
|
||||
BigDecimal singleCharge=charge.getTotalAmount(currentItem);
|
||||
@@ -47,7 +47,7 @@ public class LineCalculator {
|
||||
|
||||
}
|
||||
}
|
||||
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
|
||||
if (currentItem.getItemTotalAllowances() != null) {
|
||||
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getItemTotalAllowances()) {
|
||||
addAllowanceItemTotal(itemTotalAllowance.getTotalAmount(currentItem));
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public class LineCalculator {
|
||||
? BigDecimal.ONE.setScale(4)
|
||||
: currentItem.getBasisQuantity();
|
||||
itemTotalNetAmount = quantity.multiply(price).divide(basisQuantity, 18, RoundingMode.HALF_UP)
|
||||
.add(lineCharge).subtract(lineAllowance).subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
|
||||
.add(lineCharge).subtract(lineAllowance).subtract(allowanceItemTotal.setScale(2, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP);
|
||||
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);//.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public class OXPullProvider extends ZUGFeRD2PullProvider {
|
||||
paymentTermsDescription = XMLTools.encodeXML(trans.getPaymentTermDescription());
|
||||
}
|
||||
|
||||
if ((paymentTermsDescription == null) && (trans.getDocumentCode() != CORRECTEDINVOICE)/* && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)*/) {
|
||||
if (paymentTermsDescription == null && !CORRECTEDINVOICE.equals(trans.getDocumentCode())/* && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)*/) {
|
||||
paymentTermsDescription = "Zahlbar ohne Abzug bis " + germanDateFormat.format(trans.getDueDate());
|
||||
|
||||
}
|
||||
@@ -125,12 +125,12 @@ public class OXPullProvider extends ZUGFeRD2PullProvider {
|
||||
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
|
||||
}
|
||||
String allowanceChargeStr = "";
|
||||
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
|
||||
if (currentItem.getItemAllowances() != null) {
|
||||
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
|
||||
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
|
||||
}
|
||||
}
|
||||
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
||||
if (currentItem.getItemCharges() != null) {
|
||||
for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
||||
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
|
||||
|
||||
@@ -313,8 +313,9 @@ public class OXPullProvider extends ZUGFeRD2PullProvider {
|
||||
for (final IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) {
|
||||
if (payment != null) {
|
||||
hasDueDate = true;
|
||||
// xml += payment.getSettlementXML();
|
||||
}
|
||||
break;
|
||||
// xml += payment.getSettlementXML();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trans.getTradeSettlement() != null) {
|
||||
|
||||
@@ -89,7 +89,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
|
||||
|
||||
private BigDecimal sumAllowanceCharge(BigDecimal percent, IZUGFeRDAllowanceCharge[] charges) {
|
||||
BigDecimal res = BigDecimal.ZERO;
|
||||
if ((charges != null) && (charges.length > 0)) {
|
||||
if (charges != null) {
|
||||
for (IZUGFeRDAllowanceCharge currentCharge : charges) {
|
||||
if ((percent == null) || (currentCharge.getTaxPercent().compareTo(percent) == 0)) {
|
||||
res = res.add(currentCharge.getTotalAmount(this));
|
||||
@@ -172,6 +172,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
|
||||
* @return item sum +- charges/allowances
|
||||
*/
|
||||
public BigDecimal getTaxBasis() {
|
||||
BigDecimal debug_1=getTotal();
|
||||
return getTotal().add(getChargesForPercent(null).setScale(2, RoundingMode.HALF_UP))
|
||||
.subtract(getAllowancesForPercent(null).setScale(2, RoundingMode.HALF_UP))
|
||||
.setScale(2, RoundingMode.HALF_UP);
|
||||
@@ -211,7 +212,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
|
||||
}
|
||||
|
||||
IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges();
|
||||
if ((charges != null) && (charges.length > 0)) {
|
||||
if (charges != null) {
|
||||
for (IZUGFeRDAllowanceCharge currentCharge : charges) {
|
||||
BigDecimal taxPercent = currentCharge.getTaxPercent();
|
||||
if (taxPercent != null) {
|
||||
@@ -229,7 +230,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
|
||||
}
|
||||
}
|
||||
IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances();
|
||||
if ((allowances != null) && (allowances.length > 0)) {
|
||||
if (allowances != null) {
|
||||
for (IZUGFeRDAllowanceCharge currentAllowance : allowances) {
|
||||
BigDecimal taxPercent = currentAllowance.getTaxPercent();
|
||||
if (taxPercent != null) {
|
||||
@@ -285,8 +286,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
|
||||
}
|
||||
|
||||
final IZUGFeRDAllowanceCharge[] charges = this.trans.getZFCharges();
|
||||
if (charges != null && charges.length > 0)
|
||||
{
|
||||
if (charges != null) {
|
||||
for (final IZUGFeRDAllowanceCharge currentCharge : charges)
|
||||
{
|
||||
final BigDecimal taxPercent = currentCharge.getTaxPercent();
|
||||
@@ -309,8 +309,7 @@ public class TransactionCalculator implements IAbsoluteValueProvider {
|
||||
}
|
||||
}
|
||||
final IZUGFeRDAllowanceCharge[] allowances = this.trans.getZFAllowances();
|
||||
if (allowances != null && allowances.length > 0)
|
||||
{
|
||||
if (allowances != null) {
|
||||
for (final IZUGFeRDAllowanceCharge currentAllowance : allowances)
|
||||
{
|
||||
final BigDecimal taxPercent = currentAllowance.getTaxPercent();
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.mustangproject.XMLTools;
|
||||
import org.slf4j.Logger;
|
||||
@@ -18,7 +19,7 @@ public class XRechnungImporter extends ZUGFeRDImporter {
|
||||
try {
|
||||
setRawXML(rawXml);
|
||||
containsMeta = true;
|
||||
} catch (final IOException e) {
|
||||
} catch (final IOException | ParseException e) {
|
||||
LOGGER.error ("Failed to set raw XML", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
@@ -30,24 +31,21 @@ public class XRechnungImporter extends ZUGFeRDImporter {
|
||||
try {
|
||||
setRawXML(Files.readAllBytes(Paths.get(filename)));
|
||||
containsMeta = true;
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error ("Failed to set raw XML", e);
|
||||
} catch (final IOException | ParseException e) {
|
||||
LOGGER.error ("Failed to set raw XML", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
|
||||
}
|
||||
public XRechnungImporter(InputStream fileinput) {
|
||||
super();
|
||||
|
||||
try {
|
||||
setRawXML(XMLTools.getBytesFromStream(fileinput));
|
||||
containsMeta = true;
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error ("Failed to set raw XML", e);
|
||||
} catch (final IOException | ParseException e) {
|
||||
LOGGER.error ("Failed to set raw XML", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -359,7 +359,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
}
|
||||
paymentTermsDescription += discount.getAsXRechnung();
|
||||
}
|
||||
} else if ((paymentTermsDescription == null) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CORRECTEDINVOICE) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)) {
|
||||
} else if (paymentTermsDescription == null
|
||||
&& !DocumentCodeTypeConstants.CORRECTEDINVOICE.equals(trans.getDocumentCode())
|
||||
&& !DocumentCodeTypeConstants.CREDITNOTE.equals(trans.getDocumentCode())
|
||||
) {
|
||||
if (trans.getDueDate() != null) {
|
||||
paymentTermsDescription = "Please remit until " + germanDateFormat.format(trans.getDueDate());
|
||||
}
|
||||
@@ -434,11 +437,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
}
|
||||
|
||||
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>";
|
||||
if (currentItem.getProduct().getDescription() != null && currentItem.getProduct().getDescription().length() > 0) {
|
||||
if (currentItem.getProduct().getDescription() != null) {
|
||||
xml += "<ram:Description>" +
|
||||
XMLTools.encodeXML(currentItem.getProduct().getDescription()) +
|
||||
"</ram:Description>";
|
||||
}
|
||||
|
||||
if (currentItem.getProduct().getAttributes() != null) {
|
||||
for (Entry<String, String> entry : currentItem.getProduct().getAttributes().entrySet()) {
|
||||
xml += "<ram:ApplicableProductCharacteristic>" +
|
||||
@@ -447,7 +451,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
"</ram:ApplicableProductCharacteristic>";
|
||||
}
|
||||
}
|
||||
if (currentItem.getProduct().getClassifications() != null && currentItem.getProduct().getClassifications().length > 0) {
|
||||
if (currentItem.getProduct().getClassifications() != null) {
|
||||
for (IDesignatedProductClassification classification : currentItem.getProduct().getClassifications()) {
|
||||
xml += "<ram:DesignatedProductClassification>"
|
||||
+ "<ram:ClassCode listID=\"" + XMLTools.encodeXML(classification.getClassCode().getListID()) + "\"";
|
||||
@@ -702,7 +706,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((trans.getDocumentCode() == DocumentCodeTypeConstants.CORRECTEDINVOICE) || (trans.getDocumentCode() == DocumentCodeTypeConstants.CREDITNOTE)) {
|
||||
if (DocumentCodeTypeConstants.CORRECTEDINVOICE.equals(trans.getDocumentCode())
|
||||
|| DocumentCodeTypeConstants.CREDITNOTE.equals(trans.getDocumentCode())
|
||||
) {
|
||||
hasDueDate = false;
|
||||
}
|
||||
|
||||
@@ -857,7 +863,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
} else {
|
||||
xml += buildPaymentTermsXml();
|
||||
}
|
||||
if ((profile == Profiles.getByName("Extended")) && (trans.getCashDiscounts() != null) && (trans.getCashDiscounts().length > 0)) {
|
||||
if (profile == Profiles.getByName("Extended") && trans.getCashDiscounts() != null) {
|
||||
for (IZUGFeRDCashDiscount discount : trans.getCashDiscounts()
|
||||
) {
|
||||
xml += discount.getAsCII();
|
||||
|
||||
@@ -564,10 +564,9 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
|
||||
// iterate over all pdf pages
|
||||
|
||||
for (Object object : doc.getPages()) {
|
||||
if (object instanceof PDPage) {
|
||||
for (PDPage page : doc.getPages()) {
|
||||
if (page != null) {
|
||||
|
||||
PDPage page = (PDPage) object;
|
||||
PDResources res = page.getResources();
|
||||
|
||||
// Check for fonts in PDXObjects:
|
||||
|
||||
@@ -14,6 +14,7 @@ package org.mustangproject.ZUGFeRD;
|
||||
* @author jstaerk
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@@ -351,6 +352,16 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
|
||||
|
||||
|
||||
public String getHolder() {
|
||||
if (importedInvoice!=null && importedInvoice.getTradeSettlement()!=null) {
|
||||
for (IZUGFeRDTradeSettlement settlement : importedInvoice.getTradeSettlement()) {
|
||||
if (settlement instanceof IZUGFeRDTradeSettlementPayment) {
|
||||
String s = ((IZUGFeRDTradeSettlementPayment) settlement).getAccountName();
|
||||
if ( s != null ) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return extractString("//*[local-name() = 'SellerTradeParty']/*[local-name() = 'Name']");
|
||||
}
|
||||
|
||||
@@ -452,7 +463,11 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
|
||||
* @throws IOException if raw can not be set
|
||||
*/
|
||||
public void setMeta(String meta) throws IOException {
|
||||
setRawXML(meta.getBytes());
|
||||
try {
|
||||
setRawXML(meta.getBytes());
|
||||
} catch (ParseException e) {
|
||||
LOGGER.error("Failed to parse", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.apache.pdfbox.pdmodel.common.PDNameTreeNode;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
import org.mustangproject.*;
|
||||
import org.mustangproject.Exceptions.ArithmetricException;
|
||||
import org.mustangproject.Exceptions.StructureException;
|
||||
import org.mustangproject.util.NodeMap;
|
||||
import org.slf4j.Logger;
|
||||
@@ -127,8 +126,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
if (Arrays.equals(pad, pdfSignature)) { // we have a pdf
|
||||
|
||||
|
||||
try {
|
||||
PDDocument doc = Loader.loadPDF(IOUtils.toByteArray(pdfStream));
|
||||
try(PDDocument doc = Loader.loadPDF(IOUtils.toByteArray(pdfStream))) {
|
||||
// PDDocumentInformation info = doc.getDocumentInformation();
|
||||
final PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
|
||||
//start
|
||||
@@ -174,7 +172,12 @@ public class ZUGFeRDInvoiceImporter {
|
||||
} else {
|
||||
// no PDF probably XML
|
||||
containsMeta = true;
|
||||
setRawXML(XMLTools.getBytesFromStream(pdfStream));
|
||||
try {
|
||||
setRawXML(XMLTools.getBytesFromStream(pdfStream));
|
||||
} catch(ParseException e) {
|
||||
LOGGER.error("Failed to parse PDF", e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -209,7 +212,16 @@ public class ZUGFeRDInvoiceImporter {
|
||||
*/
|
||||
|
||||
final PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
|
||||
if ((filename.equals("ZUGFeRD-invoice.xml") || (filename.equals("zugferd-invoice.xml")) || filename.equals("factur-x.xml")) || filename.equals("xrechnung.xml") || filename.equals("order-x.xml") || filename.equals("cida.xml")) {
|
||||
Set<String> validFilenames = Set.of(
|
||||
"ZUGFeRD-invoice.xml",
|
||||
"zugferd-invoice.xml",
|
||||
"factur-x.xml",
|
||||
"xrechnung.xml",
|
||||
"order-x.xml",
|
||||
"cida.xml"
|
||||
);
|
||||
|
||||
if (validFilenames.contains(filename)) {
|
||||
containsMeta = true;
|
||||
|
||||
// String embeddedFilename = filePath + filename;
|
||||
@@ -219,8 +231,11 @@ public class ZUGFeRDInvoiceImporter {
|
||||
// ByteArrayOutputStream();
|
||||
// FileOutputStream fos = new FileOutputStream(file);
|
||||
|
||||
setRawXML(embeddedFile.toByteArray());
|
||||
|
||||
try {
|
||||
setRawXML(embeddedFile.toByteArray());
|
||||
} catch (ParseException e) {
|
||||
LOGGER.error("Failed to parse XML", e);
|
||||
}
|
||||
// fos.write(embeddedFile.getByteArray());
|
||||
// fos.close();
|
||||
}
|
||||
@@ -237,7 +252,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
* @param doParse automatically parse input for zugferdImporter (not ZUGFeRDInvoiceImporter)
|
||||
* @throws IOException if parsing xml throws it (unlikely its string based)
|
||||
*/
|
||||
public void setRawXML(byte[] rawXML, boolean doParse) throws IOException {
|
||||
public void setRawXML(byte[] rawXML, boolean doParse) throws IOException, ParseException {
|
||||
this.containsMeta = true;
|
||||
this.rawXML = rawXML;
|
||||
this.version = null;
|
||||
@@ -245,7 +260,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
|
||||
try {
|
||||
setDocument();
|
||||
} catch (ParserConfigurationException | SAXException | ParseException e) {
|
||||
} catch (ParserConfigurationException | SAXException e) {
|
||||
LOGGER.error("Failed to parse XML", e);
|
||||
throw new ZUGFeRDExportException(e);
|
||||
}
|
||||
@@ -257,7 +272,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
* @param rawXML the cii(?) as a string
|
||||
* @throws IOException if parsing xml throws it (unlikely its string based)
|
||||
*/
|
||||
public void setRawXML(byte[] rawXML) throws IOException {
|
||||
public void setRawXML(byte[] rawXML) throws IOException, ParseException {
|
||||
setRawXML(rawXML, true);
|
||||
}
|
||||
|
||||
@@ -353,39 +368,31 @@ public class ZUGFeRDInvoiceImporter {
|
||||
delivery.addGlobalID(sID);
|
||||
}
|
||||
});
|
||||
deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> {
|
||||
s.getAsString("StreetName").ifPresent(t -> delivery.setStreet(t));
|
||||
});
|
||||
deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> {
|
||||
s.getAsString("AdditionalStreetName").ifPresent(t -> delivery.setAdditionalAddress(t));
|
||||
});
|
||||
deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> {
|
||||
s.getAsString("CityName").ifPresent(t -> delivery.setLocation(t));
|
||||
});
|
||||
deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> {
|
||||
s.getAsString("PostalZone").ifPresent(t -> delivery.setZIP(t));
|
||||
});
|
||||
deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> {
|
||||
s.getAsNodeMap("Country").ifPresent(t -> t.getAsString("IdentificationCode").ifPresent(u -> delivery.setCountry(u)));
|
||||
});
|
||||
deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> {
|
||||
s.getAsNodeMap("AddressLine").ifPresent(t -> t.getAsString("Line").ifPresent(u -> delivery.setAdditionalAddressExtension(u)));
|
||||
});
|
||||
deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> {
|
||||
s.getAsString("AdditionalStreetName").ifPresent(t -> delivery.setAdditionalAddress(t));
|
||||
});
|
||||
deliveryLocationNodeMap.getAsNodeMap("Address").ifPresent(s -> {
|
||||
s.getAsString("AdditionalStreetName").ifPresent(t -> delivery.setAdditionalAddress(t));
|
||||
});
|
||||
Optional<NodeMap> addressNodeMapp = deliveryLocationNodeMap.getAsNodeMap("Address");
|
||||
addressNodeMapp.flatMap(s -> s.getAsString("StreetName"))
|
||||
.ifPresent(delivery::setStreet);
|
||||
addressNodeMapp.flatMap(s -> s.getAsString("AdditionalStreetName"))
|
||||
.ifPresent(delivery::setAdditionalAddress);
|
||||
addressNodeMapp.flatMap(s -> s.getAsString("CityName"))
|
||||
.ifPresent(delivery::setLocation);
|
||||
addressNodeMapp.flatMap(s -> s.getAsString("PostalZone"))
|
||||
.ifPresent(delivery::setZIP);
|
||||
addressNodeMapp.flatMap(s -> s.getAsNodeMap("Country")).flatMap(t -> t.getAsString("IdentificationCode"))
|
||||
.ifPresent(delivery::setCountry);
|
||||
addressNodeMapp.flatMap(s -> s.getAsNodeMap("AddressLine")).flatMap(t -> t.getAsString("Line"))
|
||||
.ifPresent(delivery::setAdditionalAddressExtension);
|
||||
addressNodeMapp.flatMap(s -> s.getAsString("AdditionalStreetName"))
|
||||
.ifPresent(delivery::setAdditionalAddress);
|
||||
addressNodeMapp.flatMap(s -> s.getAsString("AdditionalStreetName"))
|
||||
.ifPresent(delivery::setAdditionalAddress);
|
||||
});
|
||||
|
||||
|
||||
new NodeMap(deliveryNode).getAsNodeMap("DeliveryParty").ifPresent(partyMap -> {
|
||||
partyMap.getAsNodeMap("PartyName").ifPresent(s -> {
|
||||
s.getAsString("Name").ifPresent(t -> delivery.setName(t));
|
||||
});
|
||||
});
|
||||
String street, name, additionalStreet, city, postal, countrySubentity, line, country = null;
|
||||
new NodeMap(deliveryNode).getAsNodeMap("DeliveryParty")
|
||||
.flatMap(partyMap -> partyMap.getAsNodeMap("PartyName"))
|
||||
.flatMap(s -> s.getAsString("Name"))
|
||||
.ifPresent(delivery::setName);
|
||||
|
||||
zpp.setDeliveryAddress(delivery);
|
||||
|
||||
}
|
||||
@@ -424,7 +431,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
|
||||
xpr = xpath.compile("//*[local-name()=\"ExchangedDocument\"]|//*[local-name()=\"HeaderExchangedDocument\"]");
|
||||
NodeList ExchangedDocumentNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
|
||||
|
||||
xpr = xpath.compile("//*[local-name()=\"GrandTotalAmount\"]|//*[local-name()=\"TaxInclusiveAmount\"]");
|
||||
BigDecimal expectedGrandTotal = null;
|
||||
NodeList totalNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||
@@ -572,11 +579,11 @@ public class ZUGFeRDInvoiceImporter {
|
||||
}
|
||||
|
||||
String creditorReferenceID = extractString("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"CreditorReferenceID\"]").trim();//BT-90
|
||||
if ((creditorReferenceID == null)||(creditorReferenceID.length()==0)) {
|
||||
if (creditorReferenceID == null || creditorReferenceID.isEmpty()) {
|
||||
//maybe it's there in UBL?
|
||||
creditorReferenceID = extractString("//*[local-name()=\"AccountingSupplierParty\"]/*[local-name()=\"Party\"]/*[local-name()=\"PartyIdentification\"]/*[local-name()=\"ID\"]").trim();
|
||||
}
|
||||
if ((creditorReferenceID != null)&&(creditorReferenceID.length()>0)) {
|
||||
if (creditorReferenceID != null && !creditorReferenceID.isEmpty()) {
|
||||
zpp.setCreditorReferenceID(creditorReferenceID);
|
||||
}
|
||||
|
||||
@@ -1088,7 +1095,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
.collect(Collectors.joining(" + "));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
throw new ArithmetricException("Payable total in XML is " + payableTotalFromXml + ", but calculated total is " + calculatedPayableTotal + moreDetails);
|
||||
throw new ArithmeticException("Payable total in XML is " + payableTotalFromXml + ", but calculated total is " + calculatedPayableTotal + moreDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1205,7 +1212,7 @@ public class ZUGFeRDInvoiceImporter {
|
||||
* sets the XML for the importer to parse
|
||||
* @param XML the UBL or CII
|
||||
*/
|
||||
public void fromXML(String XML) {
|
||||
public void fromXML(String XML) throws ParseException{
|
||||
try {
|
||||
containsMeta = true;
|
||||
setRawXML(XML.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
Reference in New Issue
Block a user