Merge branch 'master' of github.com:ZUGFeRD/mustangproject
This commit is contained in:
@@ -21,7 +21,9 @@ public class CashDiscount implements IZUGFeRDCashDiscount {
|
||||
/***
|
||||
* the period (usually days) count how long the percent apply
|
||||
*/
|
||||
protected Integer days=null;
|
||||
protected Integer days;
|
||||
|
||||
protected BigDecimal basisAmount;
|
||||
|
||||
/***
|
||||
* Create a cash discount (skonto) with the specified height in the specified period.
|
||||
@@ -61,18 +63,31 @@ public class CashDiscount implements IZUGFeRDCashDiscount {
|
||||
return this;
|
||||
}
|
||||
|
||||
public BigDecimal getBasisAmount() {
|
||||
return basisAmount;
|
||||
}
|
||||
|
||||
public CashDiscount setBasisAmount(BigDecimal basisAmount) {
|
||||
this.basisAmount = basisAmount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/***
|
||||
* @return this particular cash discount as cross industry invoice XML
|
||||
*/
|
||||
@JsonIgnore
|
||||
public String getAsCII() {
|
||||
return "<ram:SpecifiedTradePaymentTerms>"+
|
||||
"<ram:Description>Cash Discount</ram:Description>"+
|
||||
" <ram:ApplicableTradePaymentDiscountTerms>"+
|
||||
" <ram:BasisPeriodMeasure unitCode=\"DAY\">"+days+"</ram:BasisPeriodMeasure>"+
|
||||
" <ram:CalculationPercent>"+XMLTools.nDigitFormat(percent,3)+"</ram:CalculationPercent>"+
|
||||
" </ram:ApplicableTradePaymentDiscountTerms>"+
|
||||
"</ram:SpecifiedTradePaymentTerms>";
|
||||
String s = "<ram:SpecifiedTradePaymentTerms>"
|
||||
+ " <ram:Description>Cash Discount</ram:Description>"
|
||||
+ " <ram:ApplicableTradePaymentDiscountTerms>"
|
||||
+ " <ram:BasisPeriodMeasure unitCode=\"DAY\">" + days + "</ram:BasisPeriodMeasure>";
|
||||
if (basisAmount != null) {
|
||||
s += " <ram:BasisAmount>" + XMLTools.nDigitFormat(basisAmount, 2) + "</ram:BasisAmount>";
|
||||
}
|
||||
s += " <ram:CalculationPercent>"+XMLTools.nDigitFormat(percent,3)+"</ram:CalculationPercent>"+
|
||||
" </ram:ApplicableTradePaymentDiscountTerms>"+
|
||||
"</ram:SpecifiedTradePaymentTerms>";
|
||||
return s;
|
||||
}
|
||||
|
||||
/***
|
||||
@@ -84,8 +99,4 @@ public class CashDiscount implements IZUGFeRDCashDiscount {
|
||||
public String getAsXRechnung() {
|
||||
return "#SKONTO#TAGE="+days+"#PROZENT="+XMLTools.nDigitFormat(percent,2)+"#\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -41,28 +41,6 @@ public class DXExporterFromA1 extends DXExporterFromA3 {
|
||||
private static boolean isValidA1(DataSource dataSource) throws IOException {
|
||||
return getPDFAParserValidationResult(PreflightParserHelper.createPreflightParser (dataSource));
|
||||
}
|
||||
/***
|
||||
* internal helper function: get namespace for order-x
|
||||
* @param ver the delivery-x version
|
||||
* @return the URN of the namespace
|
||||
*/
|
||||
@Override
|
||||
public String getNamespaceForVersion(int ver) {
|
||||
// As of late 2022 the Delivery-X standard is not yet published. See specification:
|
||||
// Die digitale Ablösung des Papier-Lieferscheins, Version 1.1, April 2022
|
||||
// Chapter 7.1 XMP-Erweiterungsschema für PDF/A-3
|
||||
// http://docplayer.org/230301085-Der-digitale-lieferschein-dls.html
|
||||
return "urn:factur-x:pdfa:CrossIndustryDocument:despatchadvice:1p0#";
|
||||
}
|
||||
/***
|
||||
* internal helper: returns the namespace prefix for the given order-x version number
|
||||
* @param ver the ox version
|
||||
* @return the namespace prefix as string, without colon
|
||||
*/
|
||||
@Override
|
||||
public String getPrefixForVersion(int ver) {
|
||||
return "fx";
|
||||
}
|
||||
|
||||
private static boolean getPDFAParserValidationResult(PreflightParser parser) throws IOException {
|
||||
/*
|
||||
|
||||
@@ -130,6 +130,29 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
|
||||
private boolean attachZUGFeRDHeaders = true;
|
||||
|
||||
/***
|
||||
* internal helper function: get namespace for order-x
|
||||
* @param ver the delivery-x version
|
||||
* @return the URN of the namespace
|
||||
*/
|
||||
@Override
|
||||
public String getNamespaceForVersion(int ver) {
|
||||
// As of late 2022 the Delivery-X standard is not yet published. See specification:
|
||||
// Die digitale Ablösung des Papier-Lieferscheins, Version 1.1, April 2022
|
||||
// Chapter 7.1 XMP-Erweiterungsschema für PDF/A-3
|
||||
// http://docplayer.org/230301085-Der-digitale-lieferschein-dls.html
|
||||
return "urn:factur-x:pdfa:CrossIndustryDocument:despatchadvice:1p0#";
|
||||
}
|
||||
/***
|
||||
* internal helper: returns the namespace prefix for the given order-x version number
|
||||
* @param ver the ox version
|
||||
* @return the namespace prefix as string, without colon
|
||||
*/
|
||||
@Override
|
||||
public String getPrefixForVersion(int ver) {
|
||||
return "fx";
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on the
|
||||
* metadata level, this will not e.g. convert graphics to JPG-2000)
|
||||
|
||||
@@ -41,24 +41,6 @@ public class OXExporterFromA1 extends OXExporterFromA3 {
|
||||
private static boolean isValidA1(DataSource dataSource) throws IOException {
|
||||
return getPDFAParserValidationResult(PreflightParserHelper.createPreflightParser(dataSource));
|
||||
}
|
||||
/***
|
||||
* internal helper function: get namespace for order-x
|
||||
* @param ver the order-x version
|
||||
* @return the URN of the namespace
|
||||
*/
|
||||
@Override
|
||||
public String getNamespaceForVersion(int ver) {
|
||||
return "urn:factur-x:pdfa:CrossIndustryDocument:1p0#";
|
||||
}
|
||||
/***
|
||||
* internal helper: returns the namespace prefix for the given order-x version number
|
||||
* @param ver the ox version
|
||||
* @return the namespace prefix as string, without colon
|
||||
*/
|
||||
@Override
|
||||
public String getPrefixForVersion(int ver) {
|
||||
return "fx";
|
||||
}
|
||||
|
||||
private static boolean getPDFAParserValidationResult(PreflightParser parser) throws IOException {
|
||||
/*
|
||||
|
||||
@@ -126,9 +126,27 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
*/
|
||||
protected String orderXDocumentType = "ORDER";
|
||||
|
||||
|
||||
private boolean attachZUGFeRDHeaders = true;
|
||||
|
||||
/***
|
||||
* internal helper function: get namespace for order-x
|
||||
* @param ver the order-x version
|
||||
* @return the URN of the namespace
|
||||
*/
|
||||
@Override
|
||||
public String getNamespaceForVersion(int ver) {
|
||||
return "urn:factur-x:pdfa:CrossIndustryDocument:1p0#";
|
||||
}
|
||||
/***
|
||||
* internal helper: returns the namespace prefix for the given order-x version number
|
||||
* @param ver the ox version
|
||||
* @return the namespace prefix as string, without colon
|
||||
*/
|
||||
@Override
|
||||
public String getPrefixForVersion(int ver) {
|
||||
return "fx";
|
||||
}
|
||||
|
||||
/** Defines whether attachments to the PDF should be using FLATE compression */
|
||||
private boolean compressionEnabled = false;
|
||||
|
||||
|
||||
@@ -711,6 +711,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
+ "</ram:ActualDeliverySupplyChainEvent>";
|
||||
}
|
||||
|
||||
if (trans.getDespatchAdviceReferencedDocumentID() != null && !trans.getDespatchAdviceReferencedDocumentID().trim().isEmpty()) {
|
||||
xml += "<ram:DespatchAdviceReferencedDocument>";
|
||||
xml += "<ram:IssuerAssignedID>" + XMLTools.encodeXML(trans.getDespatchAdviceReferencedDocumentID()) + "</ram:IssuerAssignedID>";
|
||||
xml += "</ram:DespatchAdviceReferencedDocument>";
|
||||
}
|
||||
|
||||
if (trans.getDeliveryNoteReferencedDocumentID() != null && !trans.getDeliveryNoteReferencedDocumentID().trim().isEmpty()) {
|
||||
xml += "<ram:DeliveryNoteReferencedDocument>";
|
||||
xml += "<ram:IssuerAssignedID>" + XMLTools.encodeXML(trans.getDeliveryNoteReferencedDocumentID()) + "</ram:IssuerAssignedID>";
|
||||
@@ -719,14 +725,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
xml += "<ram:FormattedIssueDateTime><qdt:DateTimeString format=\"102\">"+XMLTools.encodeXML(dateFormat102.format(trans.getDeliveryNoteReferencedDocumentDate()))+"</qdt:DateTimeString></ram:FormattedIssueDateTime>";
|
||||
}
|
||||
xml += "</ram:DeliveryNoteReferencedDocument>";
|
||||
|
||||
}
|
||||
|
||||
if (trans.getDespatchAdviceReferencedDocumentID() != null && !trans.getDespatchAdviceReferencedDocumentID().trim().isEmpty()) {
|
||||
xml += "<ram:DespatchAdviceReferencedDocument>";
|
||||
xml += "<ram:IssuerAssignedID>" + XMLTools.encodeXML(trans.getDespatchAdviceReferencedDocumentID()) + "</ram:IssuerAssignedID>";
|
||||
xml += "</ram:DespatchAdviceReferencedDocument>";
|
||||
|
||||
}
|
||||
|
||||
xml += "</ram:ApplicableHeaderTradeDelivery>";
|
||||
@@ -822,8 +820,14 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
xml += "<ram:SpecifiedTradeAllowanceCharge>" +
|
||||
"<ram:ChargeIndicator>" +
|
||||
"<udt:Indicator>true</udt:Indicator>" +
|
||||
"</ram:ChargeIndicator>" +
|
||||
"<ram:ActualAmount>" + currencyFormat(charge.getTotalAmount(calc)) + "</ram:ActualAmount>";
|
||||
"</ram:ChargeIndicator>";
|
||||
if (charge.getPercent() != null && (profile == Profiles.getByName("EN16931") || (profile == Profiles.getByName("EXTENDED")))) {
|
||||
xml += "<ram:CalculationPercent>" + vatFormat(charge.getPercent()) + "</ram:CalculationPercent>";
|
||||
}
|
||||
if (charge.getBasisAmount() != null && (profile == Profiles.getByName("EN16931") || (profile == Profiles.getByName("EXTENDED")))) {
|
||||
xml += "<ram:BasisAmount>" + currencyFormat(charge.getBasisAmount()) + "</ram:BasisAmount>";
|
||||
}
|
||||
xml += "<ram:ActualAmount>" + currencyFormat(charge.getTotalAmount(calc)) + "</ram:ActualAmount>";
|
||||
if (charge.getReasonCode() != null) {
|
||||
xml += "<ram:ReasonCode>" + charge.getReasonCode() + "</ram:ReasonCode>";
|
||||
}
|
||||
@@ -866,14 +870,20 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
xml += "<ram:SpecifiedTradeAllowanceCharge>" +
|
||||
"<ram:ChargeIndicator>" +
|
||||
"<udt:Indicator>false</udt:Indicator>" +
|
||||
"</ram:ChargeIndicator>" +
|
||||
"<ram:ActualAmount>" + currencyFormat(allowance.getTotalAmount(calc)) + "</ram:ActualAmount>";
|
||||
if (allowance.getReason() != null) {
|
||||
xml += "<ram:Reason>" + XMLTools.encodeXML(allowance.getReason()) + "</ram:Reason>";
|
||||
"</ram:ChargeIndicator>";
|
||||
if (allowance.getPercent() != null) {
|
||||
xml += "<ram:CalculationPercent>" + vatFormat(allowance.getPercent()) + "</ram:CalculationPercent>";
|
||||
}
|
||||
if (allowance.getBasisAmount() != null) {
|
||||
xml += "<ram:BasisAmount>" + currencyFormat(allowance.getBasisAmount()) + "</ram:BasisAmount>";
|
||||
}
|
||||
xml += "<ram:ActualAmount>" + currencyFormat(allowance.getTotalAmount(calc)) + "</ram:ActualAmount>";
|
||||
if (allowance.getReasonCode() != null) {
|
||||
xml += "<ram:ReasonCode>" + allowance.getReasonCode() + "</ram:ReasonCode>";
|
||||
}
|
||||
if (allowance.getReason() != null) {
|
||||
xml += "<ram:Reason>" + XMLTools.encodeXML(allowance.getReason()) + "</ram:Reason>";
|
||||
}
|
||||
xml += "<ram:CategoryTradeTax>" +
|
||||
"<ram:TypeCode>VAT</ram:TypeCode>" +
|
||||
"<ram:CategoryCode>" + allowance.getCategoryCode() + "</ram:CategoryCode>";
|
||||
|
||||
@@ -78,6 +78,8 @@ import jakarta.activation.FileDataSource;
|
||||
|
||||
public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporter {
|
||||
|
||||
private static final String XML_DESCRIPTION = "Invoice metadata conforming to ZUGFeRD standard (https://www.ferd-net.de/en/standards/zugferd/factur-x)";
|
||||
|
||||
private boolean isFacturX = true;
|
||||
|
||||
public static final int DefaultZUGFeRDVersion = 2;
|
||||
@@ -684,8 +686,7 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
}
|
||||
|
||||
PDFAttachGenericFile(doc, filename, relationship,
|
||||
"Invoice metadata conforming to ZUGFeRD standard (http://www.ferd-net.de/front_content.php?idcat=231&lang=4)",
|
||||
"text/xml", xmlProvider.getXML());
|
||||
XML_DESCRIPTION, "text/xml", xmlProvider.getXML());
|
||||
|
||||
for (FileAttachment attachment : fileAttachments) {
|
||||
PDFAttachGenericFile(doc, attachment.getFilename(), attachment.getRelation(), attachment.getDescription(), attachment.getMimetype(), attachment.getData());
|
||||
|
||||
@@ -764,8 +764,9 @@ public class ZF2PushTest extends TestCase {
|
||||
.setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "H87", 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"))
|
||||
.addItem(new Item(new Product("Testprodukt", "", "H87", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||
.addCharge(new Charge().setPercent(new BigDecimal(50)).setBasisAmount(price).setTaxPercent(new BigDecimal(19)).setReasonCode("ABK").setReason("Verschiedenes"))
|
||||
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)).setReasonCode("95").setReason("Mengenrabatt"))
|
||||
);
|
||||
String theXML = new String(ze.getProvider().getXML(), StandardCharsets.UTF_8);
|
||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||
|
||||
Reference in New Issue
Block a user