Merge branch 'master' into issue-830

This commit is contained in:
jayddaniels
2025-06-25 12:46:59 +02:00
committed by GitHub
43 changed files with 3973 additions and 2939 deletions

View File

@@ -3,8 +3,10 @@ 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.IAbsoluteValueProvider;
import java.math.BigDecimal;
import java.math.RoundingMode;
/***
* (absolute) allowances on item and document level
@@ -29,6 +31,22 @@ public class Allowance extends Charge {
}
@Override
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
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().subtract(singlePrice);
return singlePriceDiff;
} else {
throw new RuntimeException("percent must be set");
}
}
/***
* Always to return false for IZUGFeRDAllowanceCharge
* @return false since its not supposed to be calculated negatively

View File

@@ -23,6 +23,14 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment {
* the "name" of the bank account (holder)
*/
protected String accountName = null;
/**
* payment means code
*/
protected String paymentMeansCode = "58";
/**
* payment means information
*/
protected String paymentMeansInformation = "SEPA credit transfer";
/***
* bean constructor
@@ -123,5 +131,31 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment {
return accountName;
}
/**
* set payment means code
*
* @param paymentMeansCode the payment means code
* @return fluent setter
*/
public BankDetails setPaymentMeansCode(String paymentMeansCode) {
this.paymentMeansCode = paymentMeansCode;
return this;
}
@Override
public String getPaymentMeansCode() { return paymentMeansCode; }
/**
* set payment means information
*
* @param paymentMeansInformation the payment mean information
* @return fluent setter
*/
public BankDetails setPaymentMeansInformation(String paymentMeansInformation) {
this.paymentMeansInformation = paymentMeansInformation;
return this;
}
@Override
public String getPaymentMeansInformation() { return paymentMeansInformation; }
}

View File

@@ -103,7 +103,6 @@ public class CalculatedInvoice extends Invoice implements Serializable {
* @return a updated transactioncalulator
*/
public TransactionCalculator getCalculation() {
calculate();
return tc;
}

View File

@@ -7,6 +7,7 @@ import org.mustangproject.ZUGFeRD.IAbsoluteValueProvider;
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
import java.math.BigDecimal;
import java.math.RoundingMode;
/***
* Absolute and relative charges for document and item level
@@ -23,6 +24,10 @@ public class Charge implements IZUGFeRDAllowanceCharge {
* the absolute value if not percentage
*/
protected BigDecimal totalAmount;
/**
* the value the percentage is applied upon
*/
protected BigDecimal basisAmount;
/**
* the tax rate the charge belongs to
*/
@@ -103,6 +108,22 @@ public class Charge implements IZUGFeRDAllowanceCharge {
}
@Override
public BigDecimal getBasisAmount() {
return basisAmount;
}
/***
* sets a potential basis for the potential percentage
* @param basis the basis amount
* @return fluid setter
*/
public Charge setBasisAmount(BigDecimal basis) {
this.basisAmount = basis;
return this;
}
@Override
public String getReasonCode() {
return reasonCode;
@@ -121,10 +142,13 @@ public class Charge implements IZUGFeRDAllowanceCharge {
@Override
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
if (percent!=null) {
return currentItem.getValue().multiply(getPercent().divide(new BigDecimal(100)));
} else if(totalAmount != null) {
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;
} else {
throw new RuntimeException("percent must be set");
}

View File

@@ -72,8 +72,6 @@ public class Item implements IZUGFeRDExportableItem {
//we need: name description unitcode
//and we additionally have vat%
// Bharti's homework 20241126:Streams https://www.youtube.com/watch?v=Lf01cBzmuXw
// and Lambdas https://www.youtube.com/watch?v=HCyx31NW8xg
setProduct(new Product(itemMap.getNode("Item").get()));
icnm.getAsString("Name").ifPresent(product::setName);
icnm.getAsString("Description").ifPresent(product::setDescription);
@@ -86,17 +84,6 @@ public class Item implements IZUGFeRDExportableItem {
BuyersItemIdentification.getAsString("ID").ifPresent(product::setBuyerAssignedID);
});
// String name = icnm.getAsStringOrNull("Name");
// String val = icnm.getAsStringOrNull("Value");
// if (name != null && val != null) {
// if (attributes == null) {
// attributes = new HashMap<>();
// }
// product.attributes.put(name, val);
// }
//icnm.getNode("AdditionalItemProperty").flatMap(n ->n.getAttributes()).ifPresent(product::setAttributes);
icnm.getAsNodeMap("ClassifiedTaxCategory").flatMap(m -> m.getAsBigDecimal("Percent"))
.ifPresent(product::setVATPercent);
});
@@ -175,11 +162,12 @@ public class Item implements IZUGFeRDExportableItem {
.ifPresent(product::setTaxExemptionReason);
icnm.getAllNodes("SpecifiedTradeAllowanceCharge").map(NodeMap::new).forEach(stac -> {
stac.getAsNodeMap("ChargeIndicator").ifPresent(ci -> { //CII
stac.getAsNodeMap("ChargeIndicator").ifPresent(ci -> {
String isChargeString = ci.getAsString("Indicator").get();
String percentString = stac.getAsStringOrNull("CalculationPercent");//MultiplierFactorNumeric
String amountString = stac.getAsStringOrNull("ActualAmount");//Amount
String reason = stac.getAsStringOrNull("Reason");//AllowanceChargeReason
String percentString = stac.getAsStringOrNull("CalculationPercent");
String amountString = stac.getAsStringOrNull("ActualAmount");
String basisAmountString = stac.getAsStringOrNull("BasisAmount");
String reason = stac.getAsStringOrNull("Reason");
Charge izac = new Charge();
if (isChargeString.equalsIgnoreCase("false")) {
izac = new Allowance();
@@ -188,6 +176,12 @@ public class Item implements IZUGFeRDExportableItem {
}
if (amountString != null) {
izac.setTotalAmount(new BigDecimal(amountString));
if (percentString!=null&&(percentString!="0")) {
izac.setTotalAmount(new BigDecimal(amountString).divide(getQuantity()));
}
}
if (basisAmountString != null) {
izac.setBasisAmount(new BigDecimal(basisAmountString));
}
if (percentString != null) {
izac.setPercent(new BigDecimal(percentString));
@@ -288,6 +282,16 @@ public class Item implements IZUGFeRDExportableItem {
return this;
}
@Override public IZUGFeRDAllowanceCharge[] getAllowances() {
IZUGFeRDAllowanceCharge[] izac=new IZUGFeRDAllowanceCharge[Allowances.size()];
return Allowances.toArray(izac);
}
@Override public IZUGFeRDAllowanceCharge[] getCharges() {
IZUGFeRDAllowanceCharge[] izac=new IZUGFeRDAllowanceCharge[Charges.size()];
return Charges.toArray(izac);
}
/***
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
* @return the line ID of the order (BT132)
@@ -461,6 +465,7 @@ public class Item implements IZUGFeRDExportableItem {
* @return fluent setter
*/
public Item addAllowance(IZUGFeRDAllowanceCharge izac) {
Allowances.add(izac);
return this;
}

View File

@@ -32,6 +32,8 @@ public class Product implements IZUGFeRDExportableProduct {
protected boolean isIntraCommunitySupply = false;
protected SchemedID globalId = null;
protected String countryOfOrigin = null;
protected ArrayList<Charge> charges=new ArrayList<>();
protected ArrayList<Allowance> allowances=new ArrayList<>();
protected HashMap<String, String> attributes = new HashMap<>();
protected List<IDesignatedProductClassification> classifications = new ArrayList<>();
@@ -393,4 +395,42 @@ public class Product implements IZUGFeRDExportableProduct {
this.classifications.add(classification);
return this;
}
public Product addCharge(Charge e) {
charges.add(e);
return this;
}
public Product addAllowance(Allowance a) {
allowances.add(a);
return this;
}
/***
* returns the AppliedTradeAllowanceCharges of this product which are actually Charges
* @return array of or null, if none
*/
@Override
public Charge[] getCharges() {
if (charges.size()==0) {
return null;
}
Charge[] chargeArr = new Charge[charges.size()];
return charges.toArray(chargeArr);
}
@Override
/***
* returns the AppliedTradeAllowanceCharges of this product which are actually Allowances
* @return array of or null, if none
*/
public Allowance[] getAllowances() {
if (allowances.size()==0) {
return null;
}
Allowance[] allowanceArr = new Allowance[allowances.size()];
return allowances.toArray(allowanceArr);
}
}

View File

@@ -38,6 +38,12 @@ public interface IZUGFeRDAllowanceCharge {
*/
default BigDecimal getPercent() {return null;}
/***
* returns a basis the precentage is calculated from
* @return null or the basis
*/
default BigDecimal getBasisAmount() {return null;}
/***
* get a description for the allowance/charge
* @return the description

View File

@@ -43,7 +43,11 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
* item level discounts
* @return array of the discounts on a single item
*/
@Deprecated
default IZUGFeRDAllowanceCharge[] getItemAllowances() {
if (getProduct()!=null) {
return getProduct().getAllowances();
}
return null;
}
@@ -51,10 +55,27 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
* item level price additions
* @return array of the additional charges on the item
*/
@Deprecated
default IZUGFeRDAllowanceCharge[] getItemCharges() {
if (getProduct()!=null) {
return getProduct().getCharges();
}
return null;
}
@Deprecated
default IZUGFeRDAllowanceCharge[] getAllowances() {
return null;
}
/**
* item level price additions
* @return array of the additional charges on the item
*/
@Deprecated
default IZUGFeRDAllowanceCharge[] getCharges() {
return null;
}
/***
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
@@ -147,9 +168,9 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
}
/***
* specify allowances amount for the line item total
* get all (allowances and charges) SpecifiedTradeAllowanceCharges
*
* @return the sum of allowances for this item
* @return the real item lecel SpecifiedTradeAllowanceCharges
*/
default IZUGFeRDAllowanceCharge[] getItemTotalAllowances() {
return null;

View File

@@ -166,6 +166,25 @@ public interface IZUGFeRDExportableProduct {
return null;
}
/**
* product level discounts (AppliedTradeAllowanceCharge, will change net price)
* @return array of the discounts on a single product
*/
default IZUGFeRDAllowanceCharge[] getAllowances() {
return null;
}
/**
* product level charges (AppliedTradeAllowanceCharge, will change net price)
* @return array of the additional charges on the product
*/
default IZUGFeRDAllowanceCharge[] getCharges() {
return null;
}
/**
* Detailed information about the product
*

View File

@@ -59,6 +59,16 @@ public interface IZUGFeRDTradeSettlementPayment extends IZUGFeRDTradeSettlement
*/
default String getAccountName() { return null; }
/***
* @return payment means code (BT-81 / UNTDID 4461)
*/
default String getPaymentMeansCode() { return null; };
/***
* @return payment means description (BT-82) (optional)
*/
default String getPaymentMeansInformation() { return null; };
@Override
@JsonIgnore
@@ -70,12 +80,14 @@ public interface IZUGFeRDTradeSettlementPayment extends IZUGFeRDTradeSettlement
}
String xml = "<ram:SpecifiedTradeSettlementPaymentMeans>"
+ "<ram:TypeCode>58</ram:TypeCode>"
+ "<ram:Information>SEPA credit transfer</ram:Information>"
+ "<ram:PayeePartyCreditorFinancialAccount>"
+ "<ram:IBANID>" + XMLTools.encodeXML(getOwnIBAN()) + "</ram:IBANID>";
xml+= accountNameStr;
xml+= "</ram:PayeePartyCreditorFinancialAccount>";
+ "<ram:TypeCode>" + XMLTools.encodeXML(getPaymentMeansCode()) + "</ram:TypeCode>"
+ "<ram:Information>" + XMLTools.encodeXML(getPaymentMeansInformation()) + "</ram:Information>";
if (getOwnIBAN() != null) {
xml += "<ram:PayeePartyCreditorFinancialAccount>"
+ "<ram:IBANID>" + XMLTools.encodeXML(getOwnIBAN()) + "</ram:IBANID>"
+ accountNameStr
+ "</ram:PayeePartyCreditorFinancialAccount>";
}
if (getOwnBIC()!=null) {
xml+= "<ram:PayeeSpecifiedCreditorFinancialInstitution>"
+ "<ram:BICID>" + XMLTools.encodeXML(getOwnBIC()) + "</ram:BICID>"

View File

@@ -2,30 +2,49 @@ package org.mustangproject.ZUGFeRD;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.List;
/***
* the linecalculator does the math within an item line, and e.g. calculates quantity*price.
* @see TransactionCalculator
*/
public class LineCalculator {
private final BigDecimal price;
private final BigDecimal priceGross;
private final BigDecimal itemTotalNetAmount;
private final BigDecimal itemTotalVATAmount;
private BigDecimal allowance = BigDecimal.ZERO;
private BigDecimal charge = BigDecimal.ZERO;
private BigDecimal allowanceItemTotal = BigDecimal.ZERO;
protected BigDecimal price;
protected BigDecimal priceGross;
protected BigDecimal itemTotalNetAmount;
protected BigDecimal itemTotalVATAmount;
protected BigDecimal lineAllowance = BigDecimal.ZERO;
protected BigDecimal lineCharge = BigDecimal.ZERO;
protected BigDecimal itemAllowance = BigDecimal.ZERO;
protected BigDecimal itemCharge = BigDecimal.ZERO;
protected BigDecimal allowanceItemTotal = BigDecimal.ZERO;
public LineCalculator(IZUGFeRDExportableItem currentItem) {
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
addAllowance(allowance.getTotalAmount(currentItem));
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));
}
}
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
for (IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
addCharge(charge.getTotalAmount(currentItem));
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));
}
}
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
@@ -42,22 +61,41 @@ public class LineCalculator {
vatPercent = BigDecimal.ZERO;
}
BigDecimal multiplicator = vatPercent.divide(BigDecimal.valueOf(100));
priceGross = currentItem.getPrice(); // see https://github.com/ZUGFeRD/mustangproject/issues/159
price = priceGross.subtract(allowance).add(charge);
BigDecimal quantity=BigDecimal.ZERO;
if ((currentItem!=null)&&(currentItem.getQuantity()!=null)) {
quantity=currentItem.getQuantity();
}
price=currentItem.getPrice();
priceGross=price;
// price=price.subtract(itemAllowance).add(itemCharge);
// BigDecimal delta=charge.subtract(allowanceItemTotal).subtract(allowance);
// delta=delta.divide(currentItem.getQuantity(), 18, RoundingMode.HALF_UP);
BigDecimal delta=BigDecimal.ZERO;
if(currentItem.getProduct()!=null){
if (currentItem.getProduct().getAllowances()!=null) {
for (IZUGFeRDAllowanceCharge ccaf:currentItem.getProduct().getAllowances()) {
delta=delta.subtract(ccaf.getTotalAmount(currentItem));
}
}
if (currentItem.getProduct().getCharges()!=null) {
for (IZUGFeRDAllowanceCharge ccaf : currentItem.getProduct().getCharges()) {
delta = delta.subtract(ccaf.getTotalAmount(currentItem));
}
}
}
price=price.add(delta);
// Division/Zero occurred here.
// Used the setScale only because that's also done in getBasisQuantity
BigDecimal basisQuantity = currentItem.getBasisQuantity().compareTo(BigDecimal.ZERO) == 0
? BigDecimal.ONE.setScale(4)
: currentItem.getBasisQuantity();
itemTotalNetAmount = quantity.multiply(price).divide(basisQuantity, 18, RoundingMode.HALF_UP)
.subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);
.add(lineCharge).subtract(lineAllowance).subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);//.setScale(2, RoundingMode.HALF_UP);
}
public BigDecimal getPrice() {
@@ -80,16 +118,27 @@ public class LineCalculator {
return priceGross;
}
public void addAllowance(BigDecimal b) {
allowance = allowance.add(b);
public void addLineAllowance(BigDecimal b) {
lineAllowance = lineAllowance.add(b);
}
public void addCharge(BigDecimal b) {
charge = charge.add(b);
public void addLineCharge(BigDecimal b) {
lineCharge = lineCharge.add(b);
}
public void addItemAllowance(BigDecimal b) {
itemAllowance = itemAllowance.add(b);
}
public void addItemCharge(BigDecimal b) {
itemCharge = itemCharge.add(b);
}
public void addAllowanceItemTotal(BigDecimal b) {
allowanceItemTotal = allowanceItemTotal.add(b);
}
public void subtractAllowanceItemTotal(BigDecimal b) {
allowanceItemTotal = allowanceItemTotal.subtract(b);
}
}

View File

@@ -145,7 +145,7 @@ public class VATAmount {
}
public VATAmount add(VATAmount v) {
return new VATAmount(basis.add(v.getBasis()), calculated.add(v.getCalculated()), this.categoryCode, this.dueDateTypeCode).setVatExemptionReasonText(v.getVatExemptionReasonText());
return new VATAmount(basis.add(v.getBasis()), calculated.add(v.getCalculated()), this.categoryCode, this.dueDateTypeCode).setVatExemptionReasonText(v.getVatExemptionReasonText() != null ? v.getVatExemptionReasonText(): this.vatExemptionReasonText);
}
public VATAmount subtract(VATAmount v) {

View File

@@ -48,6 +48,7 @@ import org.mustangproject.IncludedNote;
import org.mustangproject.ReferencedDocument;
import org.mustangproject.XMLTools;
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -152,12 +153,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (profile == Profiles.getByName("Minimum")) {
xml += "<ram:ID>" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + "</ram:ID>";
} else {
String schemeAttribute="";
if ((party.getLegalOrganisation().getSchemedID().getScheme()!=null)&&(party.getLegalOrganisation().getSchemedID().getScheme().length()>0)) {
schemeAttribute="schemeID=\"" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getScheme())+"\"";
String schemeAttribute = "";
if ((party.getLegalOrganisation().getSchemedID().getScheme() != null) && (party.getLegalOrganisation().getSchemedID().getScheme().length() > 0)) {
schemeAttribute = "schemeID=\"" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getScheme()) + "\"";
}
xml += "<ram:ID "+schemeAttribute+">" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + "</ram:ID>";
xml += "<ram:ID " + schemeAttribute + ">" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + "</ram:ID>";
}
}
if (party.getLegalOrganisation().getTradingBusinessName() != null) {
@@ -320,11 +321,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
String reason = "";
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) {
boolean isEN16931=(profile == Profiles.getByName("XRechnung")) || (profile == Profiles.getByName("EN16931"));
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || isEN16931)) {
reason = "<ram:Reason>" + XMLTools.encodeXML(allowance.getReason()) + "</ram:Reason>";
}
String reasonCode = "";
if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("XRechnung"))) {
if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("Extended") || isEN16931)) {
// only in XRechnung profile
reasonCode = "<ram:ReasonCode>" + allowance.getReasonCode() + "</ram:ReasonCode>";
}
@@ -395,20 +397,20 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ "</rsm:ExchangedDocumentContext>"
+ "<rsm:ExchangedDocument>"
+ "<ram:ID>" + XMLTools.encodeXML(trans.getNumber()) + "</ram:ID>";
if (profile == Profiles.getByName("Extended") && trans.getDocumentName() != null) {
xml += "<ram:Name>" + XMLTools.encodeXML(trans.getDocumentName()) + "</ram:Name>";
}
xml += "<ram:TypeCode>" + typecode + "</ram:TypeCode>"
+ "<ram:IssueDateTime>" + DATE.udtFormat(trans.getIssueDate()) + "</ram:IssueDateTime>" // date
+ buildNotes(trans)
+ "</rsm:ExchangedDocument>"
+ "<rsm:SupplyChainTradeTransaction>";
if (profile == Profiles.getByName("Extended") && trans.getDocumentName() != null) {
xml += "<ram:Name>" + XMLTools.encodeXML(trans.getDocumentName()) + "</ram:Name>";
}
xml += "<ram:TypeCode>" + typecode + "</ram:TypeCode>"
+ "<ram:IssueDateTime>" + DATE.udtFormat(trans.getIssueDate()) + "</ram:IssueDateTime>" // date
+ buildNotes(trans)
+ "</rsm:ExchangedDocument>"
+ "<rsm:SupplyChainTradeTransaction>";
int lineID = 0;
for (final IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
lineID++;
String lineIDStr = Integer.toString(lineID);
if (currentItem.getId()!=null) {
lineIDStr=currentItem.getId();
if (currentItem.getId() != null) {
lineIDStr = currentItem.getId();
}
final LineCalculator lc = new LineCalculator(currentItem);
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BasicWL"))) {
@@ -432,24 +434,29 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
}
String allowanceChargeStr = "";
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
if (currentItem.getProduct().getAllowances() != null && currentItem.getProduct().getAllowances().length > 0) {
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getProduct().getAllowances()) {
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
}
}
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
if (currentItem.getProduct().getCharges() != null && currentItem.getProduct().getCharges().length > 0) {
for (final IZUGFeRDAllowanceCharge charge : currentItem.getProduct().getCharges()) {
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
}
}
String itemTotalAllowanceChargeStr = "";
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getItemTotalAllowances()) {
if (currentItem.getAllowances() != null && currentItem.getAllowances().length > 0) {
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getAllowances()) {
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalAllowance, currentItem);
}
}
if (currentItem.getCharges() != null && currentItem.getCharges().length > 0) {
for (final IZUGFeRDAllowanceCharge itemTotalCharges : currentItem.getCharges()) {
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalCharges, currentItem);
}
}
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>";
if (currentItem.getProduct().getDescription() != null && currentItem.getProduct().getDescription().length() > 0) {
@@ -531,15 +538,16 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ "<ram:SpecifiedLineTradeSettlement>"
+ "<ram:ApplicableTradeTax>"
+ "<ram:TypeCode>VAT</ram:TypeCode>";
if (currentItem.getProduct().getTaxExemptionReason() != null) {
xml += "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
}
xml += "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>"
+ "<ram:RateApplicablePercent>"
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>"
+ "</ram:ApplicableTradeTax>";
xml += "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>";
if (!currentItem.getProduct().getTaxCategoryCode().equals(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE)) {
xml += "<ram:RateApplicablePercent>"
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>";
}
xml += "</ram:ApplicableTradeTax>";
if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) {
xml += "<ram:BillingSpecifiedPeriod>";
if (currentItem.getDetailedDeliveryPeriodFrom() != null) {
@@ -551,7 +559,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
xml += "</ram:BillingSpecifiedPeriod>";
}
xml += itemTotalAllowanceChargeStr;
// item charges/allowances
if (!itemTotalAllowanceChargeStr.isEmpty()) {
xml += itemTotalAllowanceChargeStr ;
}
xml += "<ram:SpecifiedTradeSettlementLineMonetarySummation>"
+ "<ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount())
@@ -725,9 +736,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ exemptionReasonTextXML
+ "<ram:BasisAmount>" + currencyFormat(amount.getBasis()) + "</ram:BasisAmount>" // currencyID=\"EUR\"
+ "<ram:CategoryCode>" + amountCategoryCode + "</ram:CategoryCode>"
+ (amountDueDateTypeCode != null ? "<ram:DueDateTypeCode>" + amountDueDateTypeCode + "</ram:DueDateTypeCode>" : "")
+ "<ram:RateApplicablePercent>"
+ vatFormat(amount.getApplicablePercent()) + "</ram:RateApplicablePercent></ram:ApplicableTradeTax>";
+ (amountDueDateTypeCode != null ? "<ram:DueDateTypeCode>" + amountDueDateTypeCode + "</ram:DueDateTypeCode>" : "");
if (!amountCategoryCode.equals(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE)) {
xml += "<ram:RateApplicablePercent>"
+ vatFormat(amount.getApplicablePercent()) + "</ram:RateApplicablePercent>";
}
xml += "</ram:ApplicableTradeTax>";
}
}
}
@@ -743,7 +757,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
if ((trans.getZFCharges() != null) && (trans.getZFCharges().length > 0)) {
if ((profile == Profiles.getByName("XRechnung")) || (profile == Profiles.getByName("EN16931")) || (profile == Profiles.getByName("EXTENDED"))) {
if ((profile == Profiles.getByName("XRechnung")) || (profile == Profiles.getByName("EN16931")) || (profile == Profiles.getByName("EXTENDED"))) {
for (IZUGFeRDAllowanceCharge charge : trans.getZFCharges()) {
xml += "<ram:SpecifiedTradeAllowanceCharge>" +
"<ram:ChargeIndicator>" +
@@ -759,7 +773,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
xml += "<ram:CategoryTradeTax>" +
"<ram:TypeCode>VAT</ram:TypeCode>" +
"<ram:CategoryCode>" + charge.getCategoryCode() + "</ram:CategoryCode>";
if (charge.getTaxPercent() != null) {
if (charge.getTaxPercent() != null && !charge.getCategoryCode().equals(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE)) {
xml += "<ram:RateApplicablePercent>" + vatFormat(charge.getTaxPercent()) + "</ram:RateApplicablePercent>";
}
xml += "</ram:CategoryTradeTax>" +
@@ -842,7 +856,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (paymentTermsDescription != null) {
xml += "<ram:Description>" + paymentTermsDescription + "</ram:Description>";
}
if (trans.getDueDate() != null) {
xml += "<ram:DueDateDateTime>" // $NON-NLS-2$
+ DATE.udtFormat(trans.getDueDate())
@@ -874,7 +888,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
final String chargesTotalLine = "<ram:ChargeTotalAmount>" + currencyFormat(calc.getChargesForPercent(null)) + "</ram:ChargeTotalAmount>";
xml += "<ram:SpecifiedTradeSettlementHeaderMonetarySummation>";
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BASICWL"))) {
if ((getProfile() != Profiles.getByName("Minimum"))) {
xml += "<ram:LineTotalAmount>" + currencyFormat(calc.getTotal()) + "</ram:LineTotalAmount>";
xml += chargesTotalLine
+ allowanceTotalLine;
@@ -910,12 +924,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
if (trans.getInvoiceReferencedDocuments() != null) {
for (ReferencedDocument doc : trans.getInvoiceReferencedDocuments()) {
xml += "<ram:InvoiceReferencedDocument>"
+ "<ram:IssuerAssignedID>"
+ XMLTools.encodeXML(doc.getIssuerAssignedID()) + "</ram:IssuerAssignedID>";
+ "<ram:IssuerAssignedID>"
+ XMLTools.encodeXML(doc.getIssuerAssignedID()) + "</ram:IssuerAssignedID>";
if (doc.getFormattedIssueDateTime() != null) {
xml += "<ram:FormattedIssueDateTime>"
+ DATE.qdtFormat(doc.getFormattedIssueDateTime())
+ "</ram:FormattedIssueDateTime>";
+ DATE.qdtFormat(doc.getFormattedIssueDateTime())
+ "</ram:FormattedIssueDateTime>";
}
xml += "</ram:InvoiceReferencedDocument>";
}

View File

@@ -383,29 +383,7 @@ public class ZUGFeRDInvoiceImporter {
});
});
String street, name, additionalStreet, city, postal, countrySubentity, line, country = null;
/*
String idx = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"ID\"]");
street = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name()=\"Address\"]/*[local-name()=\"StreetName\"]");
additionalStreet = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"AdditionalStreetName\"]");
city = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"CityName\"]");
postal = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"PostalZone\"]");
countrySubentity = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"CountrySubentity\"]");
line = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]//*[local-name() = \"AddressLine\"]/*[local-name() = \"Line\"]");
country = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]//*[local-name() = \"Country\"]/*[local-name() = \"IdentificationCode\"]");
name = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"DeliveryParty\"]//*[local-name() = \"PartyName\"]/*[local-name() = \"Name\"]");
*/
zpp.setDeliveryAddress(delivery);
/*
zpp.setDeliveryAddress(new TradeParty()
.setStreet(street)
.setAdditionalAddress(additionalStreet)
.setLocation(city)
.setZIP(postal)
.setAdditionalAddressExtension(line)
.setCountry(country)
.setName(name)
);
*/
}
@@ -420,14 +398,6 @@ public class ZUGFeRDInvoiceImporter {
XPathExpression shipPayee = xpath.compile("//*[local-name()=\"PayeeParty\"]/*");
NodeList ublPayeeNodes = (NodeList) shipPayee.evaluate(getDocument(), XPathConstants.NODESET);
// if(ublPayeeNodes != null) {
// TradeParty payee = new TradeParty();
// NodeMap nodeMap = new NodeMap(ublPayeeNodes).getAsNodeMap("PayeeParty").get();
// nodeMap.getNode("ID").ifPresent(s -> {
// SchemedID sID = new SchemedID().setScheme(s.getAttributes().getNamedItem("schemeID").getTextContent()).setId(s.getTextContent());
// payee.addGlobalID(sID);
// });
// }
//NodeList UBLpayeeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
if (ublPayeeNodes.getLength() > 0) {
zpp.setPayee(new TradeParty(ublPayeeNodes));
@@ -598,6 +568,15 @@ public class ZUGFeRDInvoiceImporter {
}
}
String creditorReferenceID = extractString("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"CreditorReferenceID\"]").trim();//BT-90
if ((creditorReferenceID == null)||(creditorReferenceID.length()==0)) {
//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)) {
zpp.setCreditorReferenceID(creditorReferenceID);
}
xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeDelivery\"]|//*[local-name()=\"Delivery\"]");
NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
@@ -836,9 +815,6 @@ public class ZUGFeRDInvoiceImporter {
}
}
}
// if ((paymentMeansChilds.item(paymentTermChildIndex).getLocalName() != null) && (paymentTermChilds.item(paymentTermChildIndex).getLocalName().equals("DirectDebitMandateID"))) {
// directDebitMandateID = paymentTermChilds.item(paymentTermChildIndex).getTextContent();
// }
if ((paymentMeansChilds.item(meansChildIndex).getLocalName() != null)
&& (paymentMeansChilds.item(meansChildIndex).getLocalName().equals("PaymentMandate"))) {
NodeList paymentMandateChilds = paymentMeansChilds.item(meansChildIndex).getChildNodes();
@@ -974,6 +950,7 @@ public class ZUGFeRDInvoiceImporter {
NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes();
boolean isCharge = true;
String chargeAmount = null;
String basisAmount = null;
String reason = null;
String reasonCode = null;
String taxPercent = null;
@@ -1001,6 +978,8 @@ public class ZUGFeRDInvoiceImporter {
} else if (chargeChildName.equals("ActualAmount") || chargeChildName.equals("Amount")) {
chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
} else if (chargeChildName.equals("BasisAmount")) {
basisAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
} else if (chargeChildName.equals("Reason") || chargeChildName.equals("AllowanceChargeReason")) {
reason = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
} else if (chargeChildName.equals("ReasonCode") || chargeChildName.equals("AllowanceChargeReasonCode")) {
@@ -1028,6 +1007,9 @@ public class ZUGFeRDInvoiceImporter {
if (taxPercent != null) {
c.setTaxPercent(new BigDecimal(taxPercent));
}
if (basisAmount != null) {
c.setBasisAmount(new BigDecimal(basisAmount));
}
zpp.addCharge(c);
} else {
Allowance a = new Allowance(new BigDecimal(chargeAmount));
@@ -1040,6 +1022,9 @@ public class ZUGFeRDInvoiceImporter {
if (taxPercent != null) {
a.setTaxPercent(new BigDecimal(taxPercent));
}
if (basisAmount != null) {
a.setBasisAmount(new BigDecimal(basisAmount));
}
zpp.addAllowance(a);
}

View File

@@ -1,21 +1,23 @@
/** **********************************************************************
*
/**
* *********************************************************************
* <p>
* Copyright 2018 Jochen Staerk
*
* <p>
* Use is subject to license terms.
*
* <p>
* 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.
*
* <p>
* 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.
*
* <p>
* See the License for the specific language governing permissions and
* limitations under the License.
*
*********************************************************************** */
* <p>
* **********************************************************************
*/
package org.mustangproject.ZUGFeRD.model;
import java.util.Set;
@@ -31,5 +33,5 @@ public class TaxCategoryCodeTypeConstants {
public static final String INTRACOMMUNITY = "K";
public static final String FREEEXPORT = "G";
public static Set<String> CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT, FREEEXPORT).collect(Collectors.toSet());
public static Set<String> CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT, FREEEXPORT, UNTAXEDSERVICE).collect(Collectors.toSet());
}

View File

@@ -136,7 +136,7 @@
<entry key="xr:Tender_or_lot_reference" id="BT-17">Vergabenummer</entry>
<entry key="xr:Receiving_advice_reference" id="BT-15">Kennung der Empfangsbestätigung</entry>
<entry key="xr:Despatch_advice_reference" id="BT-16">Kennung der Versandanzeige</entry>
<entry key="xr:Business_process_type_identifier" id="BT-23">Prozesskennung</entry>
<entry key="xr:Business_process_type" id="BT-23">Prozesskennung</entry>
<entry key="xr:Specification_identifier" id="BT-24">Spezifikationskennung</entry>
<entry key="xr:Invoiced_object_identifier" id="BT-18">Objektkennung</entry>
<entry key="xr:Invoiced_object_identifier/@scheme_identifier" id="BT-18_scheme">Schema der Objektkennung</entry>

View File

@@ -99,11 +99,11 @@
<xsl:attribute name="xr:id" select="'BG-2'"/>
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
<xsl:if test="./cbc:ProfileID">
<xr:Business_process_type_identifier>
<xr:Business_process_type>
<xsl:attribute name="xr:id" select="'BT-23'"/>
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
<xsl:value-of select="./cbc:ProfileID"/>
</xr:Business_process_type_identifier>
</xr:Business_process_type>
</xsl:if>
<xr:Specification_identifier>
<xsl:attribute name="xr:id" select="'BT-24'"/>

View File

@@ -98,11 +98,11 @@
<xsl:attribute name="xr:id" select="'BG-2'"/>
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
<xsl:if test="./cbc:ProfileID">
<xr:Business_process_type_identifier>
<xr:Business_process_type>
<xsl:attribute name="xr:id" select="'BT-23'"/>
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
<xsl:value-of select="./cbc:ProfileID"/>
</xr:Business_process_type_identifier>
</xr:Business_process_type>
</xsl:if>
<xr:Specification_identifier>
<xsl:attribute name="xr:id" select="'BT-24'"/>

View File

@@ -818,7 +818,6 @@
<xsl:apply-templates mode="list-entry" select="xr:Despatch_advice_reference"/>
<xsl:apply-templates mode="list-entry" select="xr:PROCESS_CONTROL/xr:Business_process_type"/>
<xsl:apply-templates mode="list-entry" select="xr:PROCESS_CONTROL/xr:Specification_identifier"/>
<xsl:apply-templates mode="list-entry" select="xr:PROCESS_CONTROL/xr:Business_process_type_identifier"/>
<xsl:apply-templates mode="list-entry" select="xr:Invoiced_object_identifier"/>
<xsl:apply-templates mode="list-entry" select="xr:Invoiced_object_identifier/@scheme_identifier">
<xsl:with-param name="field-mapping-identifier" select="'xr:Invoiced_object_identifier/@scheme_identifier'"/>

View File

@@ -1797,7 +1797,7 @@ function downloadData (element_id) {
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende "><xsl:value-of select="$i18n.bt147"/>:</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"><xsl:value-of select="format-number(xr:PRICE_DETAILS/xr:Item_price_discount,'###.##0,00','decimal')"/></div>
<div id="BT-147" title="BT-147" class="boxdaten wert"><xsl:value-of select="format-number(sum(xr:PRICE_DETAILS/xr:Item_price_discount),'###.##0,00','decimal')"/></div>
</div>
<div class="boxzeile">
<div class="boxdaten legende "><xsl:value-of select="$i18n.bt148"/>:</div>

View File

@@ -54,9 +54,9 @@ public class CalculationTest extends ResourceCase {
final LineCalculator calculator = new LineCalculator(currentItem);
assertEquals(valueOf(133.857).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
assertEquals(valueOf(1606.28).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
assertEquals(valueOf(257.0048).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
assertEquals(valueOf(148.73).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
assertEquals(valueOf(1769.89).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
assertEquals(valueOf(283.1824).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
}
@Test
@@ -74,17 +74,20 @@ public class CalculationTest extends ResourceCase {
final LineCalculator calculator = new LineCalculator(currentItem);
assertEquals(valueOf(163.603).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
assertEquals(valueOf(1963.24).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
assertEquals(valueOf(314.1184).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
assertEquals(valueOf(148.73).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
assertEquals(valueOf(1799.63).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
assertEquals(valueOf(287.9408).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
}
@Test
public void testLineCalculatorForeignCurrencyExample() {
/*
/*** xml of official fx sample with allowances and charges
* 10x100 with 10% and 50€ item discount =850€
* +8,75 charges on document level=858,75, +19%VAT=1021,91
* prepaid 500->due payable=521,91
*/
File inputCII = getResourceAsFile("Extended_fremdwaehrung.xml");
inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250407\\fremdwaehrung.xml");
ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter();
Invoice invoice=null;
zii.doIgnoreCalculationErrors();
@@ -104,9 +107,9 @@ inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250
final TransactionCalculator calculator = new TransactionCalculator(invoice);
assertEquals(valueOf(521.91).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
assertEquals(valueOf(521.91).stripTrailingZeros(), calculator.getDuePayable().stripTrailingZeros());
*/
}
@@ -221,9 +224,94 @@ inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250
invoice.addAllowance(new Allowance().setPercent(total_discount_percent).setTaxPercent(sales_tax_percent1).setReasonCode("95").setReason("Rabatte"));
}
TransactionCalculator calculator = new TransactionCalculator(invoice);
assertEquals(valueOf(101.86).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
assertEquals(valueOf(307.18).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
}
public void testSimpleItemPercentAllowance() {
/***
* 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", "", "H84", BigDecimal.ZERO);
item = new Item(product, new BigDecimal("1.10"), new BigDecimal(5.00));
item.addAllowance(new Allowance().setPercent(new BigDecimal(10)).setTaxPercent(BigDecimal.ZERO));
invoice.addItem(item);
TransactionCalculator calculator = new TransactionCalculator(invoice);
assertEquals(new BigDecimal(5), calculator.getGrandTotal().stripTrailingZeros());
}
public void testSimpleItemTotalAllowance() {
/***
* a product with net 1 and qty 5 and absolute _item_ allowance of 1 should return 4 as line total, 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", "", "H84", BigDecimal.ZERO);
item = new Item(product, new BigDecimal("1.00"), new BigDecimal(5.00));
item.addAllowance(new Allowance(new BigDecimal(1)).setTaxPercent(BigDecimal.ZERO));
invoice.addItem(item);
TransactionCalculator calculator = new TransactionCalculator(invoice);
assertEquals(new BigDecimal(4), calculator.getGrandTotal().stripTrailingZeros());
}
/**
* LineCalculator should not throw an exception when calculating a non-terminating decimal expansion
* */

View File

@@ -395,7 +395,7 @@ public class DeSerializationTest extends ResourceCase {
try {
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
TransactionCalculator tc=new TransactionCalculator(newInvoiceFromJSON);
assertEquals(new BigDecimal("19.52"),tc.getGrandTotal());
assertEquals(new BigDecimal("18.92"),tc.getGrandTotal());
} catch (JsonProcessingException e) {
throw new RuntimeException(e);

View File

@@ -32,6 +32,8 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class VisualizationTest extends ResourceCase {
@@ -80,7 +82,7 @@ public class VisualizationTest extends ResourceCase {
} catch (ParserConfigurationException e) {
fail("ParserConfigurationException should not happen: " + e.getMessage());
}
assertNotNull(result);
/* remove file endings so that tests can also pass after checking
out from git with arbitrary options (which may include CSRF changes)
@@ -94,6 +96,7 @@ public class VisualizationTest extends ResourceCase {
.replace(" ", ""));
}
public void testPDFVisualizationCII() {
File CIIinputFile = getResourceAsFile("cii/01.01a-INVOICE.cii.xml");

View File

@@ -34,6 +34,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.BufferedWriter;
@@ -61,8 +62,8 @@ public class XRTest extends TestCase {
TradeParty recipient = new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE");
recipient.setEmail("quack@ducktown.org");
Invoice i = createInvoice(recipient);
String legalOrgID="aCustomSellerLegalOrgId";
String sellerID="aSellerTradePartyID";
String legalOrgID = "aCustomSellerLegalOrgId";
String sellerID = "aSellerTradePartyID";
i.getSender().setLegalOrganisation(new LegalOrganisation(legalOrgID));
i.getSender().setID(sellerID);
ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider();
@@ -70,8 +71,8 @@ public class XRTest extends TestCase {
zf2p.generateXML(i);
String theXML = new String(zf2p.getXML(), StandardCharsets.UTF_8);
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
assertTrue(theXML.contains("<ram:ID>"+sellerID+"</ram:ID>"));// must be possible without scheme #
assertTrue(theXML.contains("<ram:ID>"+legalOrgID+"</ram:ID>"));// must be possible without scheme #
assertTrue(theXML.contains("<ram:ID>" + sellerID + "</ram:ID>"));// must be possible without scheme #
assertTrue(theXML.contains("<ram:ID>" + legalOrgID + "</ram:ID>"));// must be possible without scheme #
assertThat(theXML).valueByXPath("count(//*[local-name()='IncludedSupplyChainTradeLineItem'])")
.asInt()
.isEqualTo(1); //2 errors are OK because there is a known bug
@@ -90,6 +91,7 @@ public class XRTest extends TestCase {
}
public void testXREdgeExport() {
// the writing part
@@ -109,7 +111,7 @@ public class XRTest extends TestCase {
.setReferenceNumber("991-01484-64")//leitweg-id
// not using any VAT, this is also a test of zero-rated goods:
.setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO).setTaxExemptionReason("Kleinunternehmer"), amount, new BigDecimal(1.0)))
.setPayee( new TradeParty().setName("VR Factoring GmbH").setID("DE813838785").setLegalOrganisation(new LegalOrganisation("391200LDDFJDMIPPMZ54", "0199")))
.setPayee(new TradeParty().setName("VR Factoring GmbH").setID("DE813838785").setLegalOrganisation(new LegalOrganisation("391200LDDFJDMIPPMZ54", "0199")))
.embedFileInXML(fe1);
@@ -149,9 +151,9 @@ public class XRTest extends TestCase {
fail("ParseException not expected");
} catch (IOException e) {
fail("IOException not expected");
}
FileAttachment[] attachedFiles=readInvoice.getAdditionalReferencedDocuments();
assertNotNull(attachedFiles);
}
FileAttachment[] attachedFiles = readInvoice.getAdditionalReferencedDocuments();
assertNotNull(attachedFiles);
assertEquals(attachedFiles.length, 1);
assertTrue(Arrays.equals(attachedFiles[0].getData(), b));
@@ -289,6 +291,36 @@ public class XRTest extends TestCase {
}
public void testApplicablePercentInUntaxedService() {
// the writing part
TradeParty recipient = new TradeParty("Franz Müller", null, "55232", "Entenhausen", "DE");
String orgname = "Test company";
String number = "123";
String amountStr = "1.00";
BigDecimal amount = new BigDecimal(amountStr);
var i = new Invoice().setDueDate(new java.util.Date()).setIssueDate(new java.util.Date()).setDeliveryDate(new java.util.Date())
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("DE4711").addVATID("DE0815").setEmail("info@example.org").setContact(new org.mustangproject.Contact("Hans Test", "+49123456789", "test@example.org")).addBankDetails(new org.mustangproject.BankDetails("DE12500105170648489890", "COBADEFXXX")))
.setRecipient(recipient)
.setReferenceNumber("991-01484-64")//leitweg-id
// not using any VAT, this is also a test of zero-rated goods:
.setNumber(number).addItem(new org.mustangproject.Item(new org.mustangproject.Product("Testprodukt", "", "C62", java.math.BigDecimal.ZERO).setTaxCategoryCode(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE).setTaxExemptionReason("Expemtion reason"), amount, new java.math.BigDecimal(1.0)));
ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider();
zf2p.setProfile(Profiles.getByName("XRechnung"));
zf2p.generateXML(i);
String theXML = new String(zf2p.getXML(), StandardCharsets.UTF_8);
// Untaxed services don't have the field RateApplicablePercent, since it would be always 0. An error is thrown on validation, if 0 is set.
assertThat(theXML).valueByXPath("count(//*[local-name()='RateApplicablePercent'])")
.asInt()
.isEqualTo(0);
//Exemption reason needs to be set if TaxCategoryCode == "O", reason should be at the product and in the ApplicableTradeTax
assertThat(theXML).valueByXPath("count(//*[local-name()='ExemptionReason'])")
.asInt()
.isEqualTo(2);
}
private org.mustangproject.Invoice createInvoice(TradeParty recipient) {
String orgname = "Test company";
String number = "123";

View File

@@ -141,7 +141,7 @@ public class ZF2PushTest extends TestCase {
String senderDescription = "Kleinunternehmer";
String taxID = "9990815";
String theNote="oh lala";
String theNote = "oh lala";
BigDecimal price = new BigDecimal(priceStr);
try {
InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
@@ -177,7 +177,7 @@ public class ZF2PushTest extends TestCase {
throw new RuntimeException(e);
}
assertEquals(i.getZFItems()[0].getNotesWithSubjectCode().get(0).getContent(),theNote);
assertEquals(i.getZFItems()[0].getNotesWithSubjectCode().get(0).getContent(), theNote);
assertEquals(senderDescription, i.getSender().getDescription());
// now check the contents (like MustangReaderTest)
@@ -255,16 +255,16 @@ public class ZF2PushTest extends TestCase {
// ze.setTransaction(new Invoice().setDueDate(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)).addAllowance(new Allowance().setPercent(new BigDecimal(50)))));
Invoice i=new Invoice().setDueDate(new Date()).setIssueDate(new Date())
Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date())
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")
.setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562")))
.setNumber(number)
.addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AReason").setTaxPercent(new BigDecimal(19)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1"))))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50))))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1")).setReasonCode("95")))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50)).setReason("In love with salesperson")))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(2.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AnotherReason")))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1))).addAllowance(new Allowance(new BigDecimal("1"))));
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("Yet another reason")).addAllowance(new Allowance(new BigDecimal("1")).setReason("Something completely strange")));
ze.setTransaction(i);
@@ -275,21 +275,20 @@ public class ZF2PushTest extends TestCase {
fail("IOException should not be raised");
}
// now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ITEMCHARGESALLOWANCESPDF);
assertEquals("EUR", zi.getInvoiceCurrencyCode());
assertTrue(zi.getUTF8().contains("0911623562")); // fax number
assertTrue(zi.getUTF8().contains("ABK"));
// Reading ZUGFeRD
assertEquals("19.52", zi.getAmount());
assertEquals(orgname, zi.getHolder());
assertEquals(number, zi.getForeignReference());
try {
// now check the contents (like MustangReaderTest)
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ITEMCHARGESALLOWANCESPDF);
assertEquals("EUR", zi.getInvoiceCurrencyCode());
assertTrue(zi.getUTF8().contains("0911623562")); // fax number
assertTrue(zi.getUTF8().contains("ABK"));
// Reading ZUGFeRD
assertEquals("18.92", zi.getAmount());
assertEquals(orgname, zi.getHolder());
assertEquals(number, zi.getForeignReference());
assertEquals(zi.getVersion(), 2);
} catch (Exception e) {
e.printStackTrace();
fail("Exception should not be raised");
}
}
@@ -595,7 +594,7 @@ public class ZF2PushTest extends TestCase {
assertEquals(1, i.getInvoiceReferencedDocuments().size());
assertEquals("abcd1234", i.getInvoiceReferencedDocuments().get(0).getIssuerAssignedID());
assertEquals("4304171000002", i.getRecipient().getGlobalID());
SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
assertEquals(occurrenceFrom, sdf.format(i.getDetailedDeliveryPeriodFrom()));
assertEquals(occurrenceTo, sdf.format(i.getDetailedDeliveryPeriodTo()));
assertEquals("2001015001325", i.getZFItems()[0].getProduct().getGlobalID());
@@ -629,7 +628,7 @@ public class ZF2PushTest extends TestCase {
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE"))
.setNumber(number)
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19))))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).addAllowance(new Allowance(BigDecimal.ONE)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19))))
.addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19)))
);
String theXML = new String(ze.getProvider().getXML());
@@ -645,7 +644,7 @@ public class ZF2PushTest extends TestCase {
assertEquals("EUR", zi.getInvoiceCurrencyCode());
// Reading ZUGFeRD
assertEquals("4046.00", zi.getAmount());
assertEquals("10805.20", zi.getAmount());
assertEquals(orgname, zi.getHolder());
assertEquals(number, zi.getForeignReference());
try {
@@ -675,8 +674,8 @@ public class ZF2PushTest extends TestCase {
.setNumber(number)
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)).addCharge(new Charge().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19))))
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)).addCharge(new Charge().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)).setReasonCode("ABK")))
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)).setReason("Mengenrabatt"))
);
String theXML = new String(ze.getProvider().getXML());
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
@@ -689,7 +688,7 @@ public class ZF2PushTest extends TestCase {
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_RELATIVECHARGESALLOWANCESPDF);
assertEquals("CHF", zi.getInvoiceCurrencyCode());
assertEquals("6.25", zi.getAmount());
assertEquals("11.10", zi.getAmount());
assertEquals(orgname, zi.getHolder());
assertEquals(number, zi.getForeignReference());
try {

View File

@@ -34,12 +34,14 @@ import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
@@ -262,9 +264,27 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase {
}
assertFalse(hasExceptions);
TransactionCalculator tc = new TransactionCalculator(invoice);
assertEquals(new BigDecimal("19.52"), tc.getGrandTotal());
assertEquals(new BigDecimal("18.92"), tc.getGrandTotal());
}
public void testIBANImport() {
File CIIinputFile = getResourceAsFile("cii/lastschrift_iban_bug.xml");
try {
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(new FileInputStream(CIIinputFile));
CalculatedInvoice invoice = new CalculatedInvoice();
zii.extractInto(invoice);
assertEquals("DE11111111111111111111", invoice.getCreditorReferenceID());
assertEquals("DE22222222222222222222", invoice.getSender().getBankDetails().stream().map(BankDetails::getIBAN).collect(Collectors.joining(",")));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (XPathExpressionException e) {
throw new RuntimeException(e);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public void testBasisQuantityImport() {
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter("./target/testout-ZF2newEdge.pdf");

View File

@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:a="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:10" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<rsm:ExchangedDocumentContext>
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:cen.eu:en16931:2017</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
</rsm:ExchangedDocumentContext>
<rsm:ExchangedDocument>
<ram:ID>123456</ram:ID>
<ram:TypeCode>380</ram:TypeCode>
<ram:IssueDateTime>
<udt:DateTimeString format="102">20250426</udt:DateTimeString>
</ram:IssueDateTime>
<ram:IncludedNote>
<ram:Content>Jahresbeitrag</ram:Content>
</ram:IncludedNote>
</rsm:ExchangedDocument>
<rsm:SupplyChainTradeTransaction>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>1</ram:LineID>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:Name>Product: Plus</ram:Name>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>239.00</ram:ChargeAmount>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:BilledQuantity unitCode="H87">1.00</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>239.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>1</ram:LineID>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:Name>Getting Started-Rabatt</ram:Name>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>120.00</ram:ChargeAmount>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:BilledQuantity unitCode="H87">-1.00</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>-120.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:ApplicableHeaderTradeAgreement>
<ram:BuyerReference>7777777</ram:BuyerReference>
<ram:SellerTradeParty>
<ram:Name>---</ram:Name>
<ram:DefinedTradeContact>
<ram:PersonName>---</ram:PersonName>
<ram:DepartmentName>Geschäftsführer</ram:DepartmentName>
<ram:TelephoneUniversalCommunication>
<ram:CompleteNumber>---</ram:CompleteNumber>
</ram:TelephoneUniversalCommunication>
<ram:EmailURIUniversalCommunication>
<ram:URIID>q@q.com</ram:URIID>
</ram:EmailURIUniversalCommunication>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>12345</ram:PostcodeCode>
<ram:LineOne>Str. 11</ram:LineOne>
<ram:CityName>---</ram:CityName>
<ram:CountryID>DE</ram:CountryID>
</ram:PostalTradeAddress>
<ram:URIUniversalCommunication>
<ram:URIID schemeID="EM">a@a.com</ram:URIID>
</ram:URIUniversalCommunication>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">DE111111111</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:SellerTradeParty>
<ram:BuyerTradeParty>
<ram:Name>a &amp; b GmbH</ram:Name>
<ram:PostalTradeAddress>
<ram:PostcodeCode>123456</ram:PostcodeCode>
<ram:LineOne>--</ram:LineOne>
<ram:LineTwo>Str. 17</ram:LineTwo>
<ram:CityName>--</ram:CityName>
<ram:CountryID>DE</ram:CountryID>
</ram:PostalTradeAddress>
</ram:BuyerTradeParty>
</ram:ApplicableHeaderTradeAgreement>
<ram:ApplicableHeaderTradeDelivery/>
<ram:ApplicableHeaderTradeSettlement>
<ram:CreditorReferenceID>DE11111111111111111111</ram:CreditorReferenceID>
<ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
<ram:SpecifiedTradeSettlementPaymentMeans>
<ram:TypeCode>59</ram:TypeCode>
<ram:PayerPartyDebtorFinancialAccount>
<ram:IBANID>DE22222222222222222222</ram:IBANID>
</ram:PayerPartyDebtorFinancialAccount>
</ram:SpecifiedTradeSettlementPaymentMeans>
<ram:ApplicableTradeTax>
<ram:CalculatedAmount>22.61</ram:CalculatedAmount>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:BasisAmount>119.00</ram:BasisAmount>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:BillingSpecifiedPeriod>
<ram:StartDateTime>
<udt:DateTimeString format="102">20250426</udt:DateTimeString>
</ram:StartDateTime>
<ram:EndDateTime>
<udt:DateTimeString format="102">20250525</udt:DateTimeString>
</ram:EndDateTime>
</ram:BillingSpecifiedPeriod>
<ram:SpecifiedTradePaymentTerms>
<ram:Description>Zahlbar sofort</ram:Description>
<ram:DueDateDateTime>
<udt:DateTimeString format="102">20250426</udt:DateTimeString>
</ram:DueDateDateTime>
</ram:SpecifiedTradePaymentTerms>
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
<ram:LineTotalAmount>119.00</ram:LineTotalAmount>
<ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>
<ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>
<ram:TaxBasisTotalAmount>119.00</ram:TaxBasisTotalAmount>
<ram:TaxTotalAmount currencyID="EUR">22.61</ram:TaxTotalAmount>
<ram:GrandTotalAmount>141.61</ram:GrandTotalAmount>
<ram:TotalPrepaidAmount>0.00</ram:TotalPrepaidAmount>
<ram:DuePayableAmount>141.61</ram:DuePayableAmount>
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
</ram:ApplicableHeaderTradeSettlement>
</rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>

File diff suppressed because it is too large Load Diff

View File

@@ -1665,7 +1665,7 @@
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende ">Discount (net):</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende ">Net list price:</div>
@@ -1977,7 +1977,7 @@
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende ">Discount (net):</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende ">Net list price:</div>
@@ -2133,7 +2133,7 @@
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende ">Discount (net):</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende ">Net list price:</div>
@@ -2629,4 +2629,4 @@ function downloadData (element_id) {
});
//
</script></html>
</script></html>

View File

@@ -1379,7 +1379,7 @@
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende ">Discount (net):</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende ">Net list price:</div>
@@ -1535,7 +1535,7 @@
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende ">Discount (net):</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende ">Net list price:</div>
@@ -1758,7 +1758,7 @@
</div>
<div class="boxzeile">
<div class="boxdaten legende">Process ID:</div>
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
<div id="BT-23" title="BT-23" class="boxdaten wert">urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende">Specification ID:</div>
@@ -1948,4 +1948,4 @@ function downloadData (element_id) {
});
//
</script></html>
</script></html>

View File

@@ -1395,7 +1395,7 @@
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende ">Remise nette:</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende ">Prix catalogue (net):</div>
@@ -1551,7 +1551,7 @@
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende ">Remise nette:</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende ">Prix catalogue (net):</div>
@@ -1707,7 +1707,7 @@
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
<div class="boxzeile">
<div class="boxdaten legende ">Remise nette:</div>
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
</div>
<div class="boxzeile">
<div class="boxdaten legende ">Prix catalogue (net):</div>

View File

@@ -1,174 +1,174 @@
<?xml version="1.0" encoding="UTF-8"?><Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>RE-20201121/508</cbc:ID>
<cbc:IssueDate>2020-11-21</cbc:IssueDate>
<cbc:DueDate>2020-12-12</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>AB321</cbc:BuyerReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PostalAddress>
<cbc:StreetName>Ecke 12</cbc:StreetName>
<cbc:CityName>Stadthausen</cbc:CityName>
<cbc:PostalZone>12345</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE136695976</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Bei Spiel GmbH</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PartyIdentification>
<cbc:ID>2</cbc:ID>
</cac:PartyIdentification>
<cac:PostalAddress>
<cbc:StreetName>Bahnstr. 42</cbc:StreetName>
<cbc:CityName>Spielkreis</cbc:CityName>
<cbc:PostalZone>88802</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Theodor Est</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:Delivery>
<cbc:ActualDeliveryDate>2020-11-10</cbc:ActualDeliveryDate>
</cac:Delivery>
<cac:PaymentMeans>
<cbc:PaymentMeansCode name="Bank transfer">42</cbc:PaymentMeansCode>
<cbc:PaymentID>RE-20201121/508</cbc:PaymentID>
<cac:PayeeFinancialAccount>
<cbc:ID>DE88200800000970375700</cbc:ID>
<cbc:Name>Max Mustermann</cbc:Name>
<cac:FinancialInstitutionBranch>
<cbc:ID>COBADEFFXXX</cbc:ID>
</cac:FinancialInstitutionBranch>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:PaymentTerms>
<cbc:Note>Zahlbar ohne Abzug bis 12.12.2020</cbc:Note>
</cac:PaymentTerms>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">75.04</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">160</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">11.2</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>7</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">336</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">63.84</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">496</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">496</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">571.04</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="EUR">0</cbc:AllowanceTotalAmount>
<cbc:ChargeTotalAmount currencyID="EUR">0</cbc:ChargeTotalAmount>
<cbc:PrepaidAmount currencyID="EUR">0</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="EUR">571.04</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="HUR">1</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">160</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>Of a sample invoice</cbc:Description>
<cbc:Name>Design (hours)</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>7</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">160</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="HUR">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="EUR">0</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">160</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>
<cbc:ID>RE-20201121/508</cbc:ID>
<cbc:IssueDate>2020-11-21</cbc:IssueDate>
<cbc:DueDate>2020-12-12</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>AB321</cbc:BuyerReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PostalAddress>
<cbc:StreetName>Ecke 12</cbc:StreetName>
<cbc:CityName>Stadthausen</cbc:CityName>
<cbc:PostalZone>12345</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE136695976</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Bei Spiel GmbH</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PartyIdentification>
<cbc:ID>2</cbc:ID>
<cbc:InvoicedQuantity unitCode="H87">400</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">316</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>various colors, ~2000ml</cbc:Description>
<cbc:Name>Ballons</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">0.79</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="H87">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="EUR">0</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">0.79</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>3</cbc:ID>
<cbc:InvoicedQuantity unitCode="LTR">800</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">20</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Hot air „heiße Luft“ (litres)</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">0.025</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="LTR">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="EUR">0</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">0.025</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
</cac:PartyIdentification>
<cac:PostalAddress>
<cbc:StreetName>Bahnstr. 42</cbc:StreetName>
<cbc:CityName>Spielkreis</cbc:CityName>
<cbc:PostalZone>88802</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Theodor Est</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:Delivery>
<cbc:ActualDeliveryDate>2020-11-10</cbc:ActualDeliveryDate>
</cac:Delivery>
<cac:PaymentMeans>
<cbc:PaymentMeansCode name="Bank transfer">42</cbc:PaymentMeansCode>
<cbc:PaymentID>RE-20201121/508</cbc:PaymentID>
<cac:PayeeFinancialAccount>
<cbc:ID>DE88200800000970375700</cbc:ID>
<cbc:Name>Max Mustermann</cbc:Name>
<cac:FinancialInstitutionBranch>
<cbc:ID>COBADEFFXXX</cbc:ID>
</cac:FinancialInstitutionBranch>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:PaymentTerms>
<cbc:Note>Zahlbar ohne Abzug bis 12.12.2020</cbc:Note>
</cac:PaymentTerms>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">75.04</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">160</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">11.2</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>7</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">336</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">63.84</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">496</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">496</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">571.04</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="EUR">0</cbc:AllowanceTotalAmount>
<cbc:ChargeTotalAmount currencyID="EUR">0</cbc:ChargeTotalAmount>
<cbc:PrepaidAmount currencyID="EUR">0</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="EUR">571.04</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="HUR">1</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">160</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>Of a sample invoice</cbc:Description>
<cbc:Name>Design (hours)</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>7</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">160</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="HUR">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="EUR">0</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">160</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>2</cbc:ID>
<cbc:InvoicedQuantity unitCode="H87">400</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">316</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>various colors, ~2000ml</cbc:Description>
<cbc:Name>Ballons</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">0.79</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="H87">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="EUR">0</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">0.79</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>3</cbc:ID>
<cbc:InvoicedQuantity unitCode="LTR">800</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">20</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Hot air „heiße Luft“ (litres)</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">0.025</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="LTR">1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="EUR">0</cbc:Amount>
<cbc:BaseAmount currencyID="EUR">0.025</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
</Invoice>