org.mustangproject.ZUGFeRD.ZUGFeRD2PullProvider Maven / Gradle / Ivy
Show all versions of library Show documentation
/**
* *********************************************************************
*
* Copyright 2018 Jochen Staerk
*
* Use is subject to license terms.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
* **********************************************************************
*/
package org.mustangproject.ZUGFeRD;
import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE;
import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.stream.Collectors;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.mustangproject.FileAttachment;
import org.mustangproject.IncludedNote;
import org.mustangproject.XMLTools;
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ZUGFeRD2PullProvider implements IXMLProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(ZUGFeRD2PullProvider.class);
protected byte[] zugferdData;
protected IExportableTransaction trans;
protected TransactionCalculator calc;
private String paymentTermsDescription;
protected Profile profile = Profiles.getByName("EN16931");
/**
* enables the flag to indicate a test invoice in the XML structure
*/
@Override
public void setTest() {
}
protected String vatFormat(BigDecimal value) {
return XMLTools.nDigitFormat(value, 2);
}
protected String currencyFormat(BigDecimal value) {
return XMLTools.nDigitFormat(value, 2);
}
protected String priceFormat(BigDecimal value) {
// 18 decimals are max for price and qty due to xml restrictions,
// see Chapter 3.2.3 of https://www.w3.org/TR/xmlschema-2/
return XMLTools.nDigitFormatDecimalRange(value, 18, 4);
}
protected String quantityFormat(BigDecimal value) {
return XMLTools.nDigitFormatDecimalRange(value, 18, 4);
}
@Override
public byte[] getXML() {
byte[] res = zugferdData;
final StringWriter sw = new StringWriter();
Document document = null;
try {
document = DocumentHelper.parseText(new String(zugferdData));
} catch (final DocumentException e1) {
LOGGER.error("Failed to parse ZUGFeRD data", e1);
}
try {
final OutputFormat format = OutputFormat.createPrettyPrint();
format.setTrimText(false);
final XMLWriter writer = new XMLWriter(sw, format);
writer.write(document);
res = sw.toString().getBytes(StandardCharsets.UTF_8);
} catch (final IOException e) {
LOGGER.error("Failed to write ZUGFeRD data", e);
}
return res;
}
@Override
public Profile getProfile() {
return profile;
}
// @todo check if the two boolean args can be refactored
/***
* returns the UN/CEFACT CII XML for companies(tradeparties), which is actually
* the same for ZF1 (v 2013b) and ZF2 (v 2016b)
* @param party any sender, recipient, seller or legal party involved
* @param isSender some attributes are allowed only for senders in certain profiles
* @param isShipToTradeParty some attributes are allowed only for senders or recipients
* @return CII XML
*/
protected String getTradePartyAsXML(IZUGFeRDExportableTradeParty party, boolean isSender, boolean isShipToTradeParty) {
String xml = "";
// According EN16931 either GlobalID or seller assigned ID might be present for BuyerTradeParty
// and ShipToTradeParty, but not both. Prefer seller assigned ID for now.
if (party.getID() != null) {
xml += "" + XMLTools.encodeXML(party.getID()) + " ";
}
if ((party.getGlobalIDScheme() != null) && (party.getGlobalID() != null)) {
xml += ""
+ XMLTools.encodeXML(party.getGlobalID()) + " ";
}
xml += "" + XMLTools.encodeXML(party.getName()) + " ";
if (party.getDescription() != null) {
xml += "" + XMLTools.encodeXML(party.getDescription()) + " ";
}
if (party.getLegalOrganisation() != null) {
xml += " ";
if (party.getLegalOrganisation().getSchemedID() != null) {
if (profile == Profiles.getByName("Minimum")) {
xml += "" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + " ";
} else {
xml += "" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + " ";
}
}
if (party.getLegalOrganisation().getTradingBusinessName() != null) {
xml += "" + XMLTools.encodeXML(party.getLegalOrganisation().getTradingBusinessName()) + " ";
}
xml += " ";
}
if ((party.getContact() != null) && (isSender || profile == Profiles.getByName("EN16931") || profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) {
xml += "";
if (party.getContact().getName() != null) {
xml += ""
+ XMLTools.encodeXML(party.getContact().getName())
+ " ";
}
if (party.getContact().getPhone() != null) {
xml += ""
+ XMLTools.encodeXML(party.getContact().getPhone()) + " "
+ " ";
}
if ((party.getContact().getFax() != null) && (profile == Profiles.getByName("Extended"))) {
xml += ""
+ XMLTools.encodeXML(party.getContact().getFax()) + " "
+ " ";
}
if (party.getContact().getEMail() != null) {
xml += ""
+ XMLTools.encodeXML(party.getContact().getEMail()) + " "
+ " ";
}
xml += " ";
}
xml += "";
if (party.getZIP() != null) {
xml += "" + XMLTools.encodeXML(party.getZIP())
+ " ";
}
if (party.getStreet() != null) {
xml += "" + XMLTools.encodeXML(party.getStreet())
+ " ";
}
if (party.getAdditionalAddress() != null) {
xml += "" + XMLTools.encodeXML(party.getAdditionalAddress())
+ " ";
}
if (party.getAdditionalAddressExtension() != null) {
xml += "" + XMLTools.encodeXML(party.getAdditionalAddressExtension())
+ " ";
}
if (party.getLocation() != null) {
xml += "" + XMLTools.encodeXML(party.getLocation())
+ " ";
}
//country IS mandatory
xml += "" + XMLTools.encodeXML(party.getCountry())
+ " "
+ " ";
if (party.getUriUniversalCommunicationID() != null && party.getUriUniversalCommunicationIDScheme() != null) {
xml += "" +
"" +
XMLTools.encodeXML(party.getUriUniversalCommunicationID())
+ " ";
}
if ((party.getVATID() != null) && (!isShipToTradeParty)) {
xml += ""
+ "" + XMLTools.encodeXML(party.getVATID())
+ " "
+ " ";
}
if ((party.getTaxID() != null) && (!isShipToTradeParty)) {
xml += ""
+ "" + XMLTools.encodeXML(party.getTaxID())
+ " "
+ " ";
}
return xml;
}
protected String getTradePartyPayeeAsXML(IZUGFeRDExportableTradeParty party) {
String xml = "";
// According EN16931 either GlobalID or seller assigned ID might be present for a Payee
if (party.getID() != null) {
xml += "" + XMLTools.encodeXML(party.getID()) + " ";
}
if ((party.getGlobalIDScheme() != null) && (party.getGlobalID() != null)) {
xml += ""
+ XMLTools.encodeXML(party.getGlobalID())
+ " ";
}
xml += "" + XMLTools.encodeXML(party.getName()) + " ";
if (party.getLegalOrganisation() != null) {
xml += " ";
if (party.getLegalOrganisation().getSchemedID() != null) {
xml += "" + XMLTools.encodeXML(party.getLegalOrganisation().getSchemedID().getID()) + " ";
}
xml += " ";
}
return xml;
}
/***
* returns the XML for a charge or allowance on item level
* @param allowance the allowance or charge on this item
* @param item the item
* @return CII XML
*/
protected String getAllowanceChargeStr(IZUGFeRDAllowanceCharge allowance, IAbsoluteValueProvider item) {
String percentage = "";
String chargeIndicator = "false";
if ((allowance.getPercent() != null) && (profile == Profiles.getByName("Extended"))) {
percentage = "" + vatFormat(allowance.getPercent()) + " ";
percentage += "" + item.getValue() + " ";
}
if (allowance.isCharge()) {
chargeIndicator = "true";
}
String reason = "";
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) {
reason = "" + XMLTools.encodeXML(allowance.getReason()) + " ";
}
String reasonCode = "";
if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("XRechnung"))) {
// only in XRechnung profile
reasonCode = "" + allowance.getReasonCode() + " ";
}
final String allowanceChargeStr = "" +
chargeIndicator + " " + percentage +
"" + priceFormat(allowance.getTotalAmount(item)) + " " +
reason +
reasonCode +
" ";
return allowanceChargeStr;
}
/***
* returns the XML for a charge or allowance on item total level
* @param allowance the allowance or charge
* @param item the line
* @return CII XML
*/
protected String getItemTotalAllowanceChargeStr(IZUGFeRDAllowanceCharge allowance, IAbsoluteValueProvider item) {
String percentage = "";
String chargeIndicator = "false";
if ((allowance.getPercent() != null) && (profile == Profiles.getByName("Extended"))) {
percentage = "" + vatFormat(allowance.getPercent()) + " ";
percentage += "" + item.getValue() + " ";
}
if (allowance.isCharge()) {
chargeIndicator = "true";
}
String reason = "";
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) {
reason = "" + XMLTools.encodeXML(allowance.getReason()) + " ";
}
String reasonCode = "";
if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("XRechnung"))) {
// only in XRechnung profile
reasonCode = "" + allowance.getReasonCode() + " ";
}
final String itemTotalAllowanceChargeStr = "" +
chargeIndicator + " " + percentage +
"" + currencyFormat(allowance.getTotalAmount(item)) + " " +
reason +
reasonCode +
" ";
return itemTotalAllowanceChargeStr;
}
@Override
public void generateXML(IExportableTransaction trans) {
this.trans = trans;
this.calc = new TransactionCalculator(trans);
boolean hasDueDate = trans.getDueDate() != null;
final SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy");
String exemptionReason = "";
if (trans.getPaymentTermDescription() != null) {
paymentTermsDescription = XMLTools.encodeXML(trans.getPaymentTermDescription());
}
if ((profile == Profiles.getByName("XRechnung")) && (trans.getCashDiscounts() != null) && (trans.getCashDiscounts().length > 0)) {
for (IZUGFeRDCashDiscount discount : trans.getCashDiscounts()
) {
if (paymentTermsDescription == null) {
paymentTermsDescription = "";
}
paymentTermsDescription += discount.getAsXRechnung();
}
} else if ((paymentTermsDescription == null) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CORRECTEDINVOICE) && (trans.getDocumentCode() != DocumentCodeTypeConstants.CREDITNOTE)) {
if (trans.getDueDate() != null) {
paymentTermsDescription = "Please remit until " + germanDateFormat.format(trans.getDueDate());
}
}
String typecode = "380";
if (trans.getDocumentCode() != null) {
typecode = trans.getDocumentCode();
}
String xml = ""
+ ""
+ ""
+ "\n";
// + "
// "+testBooleanStr+" "
//
if (getProfile() == Profiles.getByName("XRechnung")) {
xml += "\n"
+ "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 \n"
+ " \n";
}
xml +=
""
+ "" + getProfile().getID() + " "
+ " "
+ " "
+ ""
+ "" + XMLTools.encodeXML(trans.getNumber()) + " "
// + "RECHNUNG "
// + "380 "
+ "" + typecode + " "
+ ""
+ DATE.udtFormat(trans.getIssueDate()) + " " // date
+ buildNotes(trans)
+ " "
+ "";
int lineID = 0;
for (final IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
lineID++;
if (currentItem.getProduct().getTaxExemptionReason() != null) {
exemptionReason = "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + " ";
}
final LineCalculator lc = new LineCalculator(currentItem);
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BasicWL"))) {
xml += "" +
""
+ "" + lineID + " "
+ buildItemNotes(currentItem)
+ " "
+ "";
if ((currentItem.getProduct().getGlobalIDScheme() != null) && (currentItem.getProduct().getGlobalID() != null)) {
xml += "" + XMLTools.encodeXML(currentItem.getProduct().getGlobalID()) + " ";
}
if (currentItem.getProduct().getSellerAssignedID() != null) {
xml += ""
+ XMLTools.encodeXML(currentItem.getProduct().getSellerAssignedID()) + " ";
}
if (currentItem.getProduct().getBuyerAssignedID() != null) {
xml += ""
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + " ";
}
String allowanceChargeStr = "";
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
}
}
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
}
}
String itemTotalAllowanceChargeStr = "";
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getItemTotalAllowances()) {
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalAllowance, currentItem);
}
}
xml += "" + XMLTools.encodeXML(currentItem.getProduct().getName()) + " ";
if (currentItem.getProduct().getDescription().length() > 0) {
xml += "" +
XMLTools.encodeXML(currentItem.getProduct().getDescription()) +
" ";
}
if (currentItem.getProduct().getClassifications() != null && currentItem.getProduct().getClassifications().length > 0) {
for (IDesignatedProductClassification classification : currentItem.getProduct().getClassifications()) {
xml += ""
+ "" + classification.getClassCode().getCode() + " ";
if (classification.getClassName() != null) {
xml += "" + XMLTools.encodeXML(classification.getClassName()) + " ";
}
xml += " ";
}
}
if (currentItem.getProduct().getAttributes() != null) {
for (Entry entry : currentItem.getProduct().getAttributes().entrySet()) {
xml += "" +
"" + XMLTools.encodeXML(entry.getKey()) + " " +
"" + XMLTools.encodeXML(entry.getValue()) + " " +
" ";
}
}
if (currentItem.getProduct().getCountryOfOrigin() != null) {
xml += "" +
XMLTools.encodeXML(currentItem.getProduct().getCountryOfOrigin()) +
" ";
}
xml += " "
+ "";
if (currentItem.getReferencedDocuments() != null) {
for (final IReferencedDocument currentReferencedDocument : currentItem.getReferencedDocuments()) {
xml += "" +
"" + XMLTools.encodeXML(currentReferencedDocument.getIssuerAssignedID()) + " " +
"" + XMLTools.encodeXML(currentReferencedDocument.getTypeCode()) + " " +
"" + XMLTools.encodeXML(currentReferencedDocument.getReferenceTypeCode()) + " " +
" ";
}
}
if (currentItem.getBuyerOrderReferencedDocumentLineID() != null) {
xml += " "
+ "" + XMLTools.encodeXML(currentItem.getBuyerOrderReferencedDocumentLineID()) + " "
+ " ";
}
if (!allowanceChargeStr.isEmpty()) {
xml += ""
+ "" + priceFormat(lc.getPriceGross())
+ " " //currencyID=\"EUR\"
+ "" + quantityFormat(currentItem.getBasisQuantity()) + " "
+ allowanceChargeStr
// + ""
// + "false "
// + "0.6667 "
// + "Rabatt "
// + " "
+ " ";
}
xml += ""
+ "" + priceFormat(lc.getPrice())
+ " " // currencyID=\"EUR\"
+ "" + quantityFormat(currentItem.getBasisQuantity()) + " "
+ " "
+ " "
+ ""
+ ""
+ quantityFormat(currentItem.getQuantity()) + " "
+ " "
+ ""
+ ""
+ "VAT "
+ exemptionReason
+ "" + currentItem.getProduct().getTaxCategoryCode() + " "
+ ""
+ vatFormat(currentItem.getProduct().getVATPercent()) + " "
+ " ";
if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) {
xml += "";
if (currentItem.getDetailedDeliveryPeriodFrom() != null) {
xml += "" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodFrom()) + " ";
}
if (currentItem.getDetailedDeliveryPeriodTo() != null) {
xml += "" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodTo()) + " ";
}
xml += " ";
}
xml += itemTotalAllowanceChargeStr;
xml += ""
+ "" + currencyFormat(lc.getItemTotalNetAmount())
+ " " // currencyID=\"EUR\"
+ " ";
if (currentItem.getAdditionalReferences() != null) {
for (final IReferencedDocument currentReference : currentItem.getAdditionalReferences()) {
xml += "" +
"" + XMLTools.encodeXML(currentReference.getIssuerAssignedID()) + " " +
"130 " +
"" + XMLTools.encodeXML(currentReference.getReferenceTypeCode()) + " " +
" ";
}
} else if (currentItem.getAdditionalReferencedDocumentID() != null) {
xml += "" + currentItem.getAdditionalReferencedDocumentID() + " 130 ";
}
xml += " "
+ " ";
}
}
xml += "";
if (trans.getReferenceNumber() != null) {
xml += "" + XMLTools.encodeXML(trans.getReferenceNumber()) + " ";
}
xml += ""
+ getTradePartyAsXML(trans.getSender(), true, false)
+ " "
+ "";
// + "GE2020211 "
// + "4000001987658 "
xml += getTradePartyAsXML(trans.getRecipient(), false, false);
xml += " ";
if (trans.getSellerOrderReferencedDocumentID() != null) {
xml += ""
+ ""
+ XMLTools.encodeXML(trans.getSellerOrderReferencedDocumentID()) + " "
+ " ";
}
if (trans.getBuyerOrderReferencedDocumentID() != null) {
xml += ""
+ ""
+ XMLTools.encodeXML(trans.getBuyerOrderReferencedDocumentID()) + " "
+ " ";
}
if (trans.getContractReferencedDocument() != null) {
xml += ""
+ ""
+ XMLTools.encodeXML(trans.getContractReferencedDocument()) + " "
+ " ";
}
// Additional Documents of XRechnung (Rechnungsbegruendende Unterlagen - BG-24 XRechnung)
if (trans.getAdditionalReferencedDocuments() != null) {
for (final FileAttachment f : trans.getAdditionalReferencedDocuments()) {
final String documentContent = new String(Base64.getEncoder().encodeToString(f.getData()));
xml += ""
+ "" + f.getFilename() + " "
+ "916 "
+ "" + f.getDescription() + " "
+ "" + documentContent + " "
+ " ";
}
}
if (trans.getSpecifiedProcuringProjectID() != null) {
xml += ""
+ ""
+ XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + " ";
if (trans.getSpecifiedProcuringProjectName() != null) {
xml += "" + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectName()) + " ";
}
xml += " ";
}
xml += " ";
xml += "";
if (this.trans.getDeliveryAddress() != null) {
xml += "" +
getTradePartyAsXML(this.trans.getDeliveryAddress(), false, true) +
" ";
}
if (trans.getDeliveryDate() != null) {
xml += ""
+ "";
xml += DATE.udtFormat(trans.getDeliveryDate());
xml += " ";
xml += " ";
}
/*
* + "" +
* "20130603 " +
* "2013-51112 " +
* " "
*/
if (trans.getDespatchAdviceReferencedDocumentID() != null) {
xml += "";
xml += "" + XMLTools.encodeXML(trans.getDespatchAdviceReferencedDocumentID()) + " ";
xml += " ";
}
xml += " ";
xml += "";
if ((trans.getCreditorReferenceID() != null) && (getProfile() != Profiles.getByName("Minimum"))) {
xml += "" + XMLTools.encodeXML(trans.getCreditorReferenceID()) + " ";
}
if ((trans.getNumber() != null) && (getProfile() != Profiles.getByName("Minimum"))) {
xml += "" + XMLTools.encodeXML(trans.getNumber()) + " ";
}
xml += "" + trans.getCurrency() + " ";
if (this.trans.getPayee() != null) {
xml += "" +
getTradePartyPayeeAsXML(this.trans.getPayee()) +
" ";
}
if (trans.getTradeSettlementPayment() != null) {
for (final IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) {
if (payment != null) {
hasDueDate = true;
if (getProfile() != Profiles.getByName("Minimum")) {
xml += payment.getSettlementXML();
}
}
}
}
if (trans.getTradeSettlement() != null) {
for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) {
if (payment != null) {
if (payment instanceof IZUGFeRDTradeSettlementPayment) {
hasDueDate = true;
}
if (getProfile() != Profiles.getByName("Minimum")) {
xml += payment.getSettlementXML();
}
}
}
}
if ((trans.getDocumentCode() == DocumentCodeTypeConstants.CORRECTEDINVOICE) || (trans.getDocumentCode() == DocumentCodeTypeConstants.CREDITNOTE)) {
hasDueDate = false;
}
final Map VATPercentAmountMap = calc.getVATPercentAmountMap();
for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) {
final VATAmount amount = VATPercentAmountMap.get(currentTaxPercent);
if (amount != null) {
final String amountCategoryCode = amount.getCategoryCode();
final String amountDueDateTypeCode = amount.getDueDateTypeCode();
final boolean displayExemptionReason = CATEGORY_CODES_WITH_EXEMPTION_REASON.contains(amountCategoryCode);
if (getProfile() != Profiles.getByName("Minimum")) {
String exemptionReasonTextXML = "";
if ((displayExemptionReason) && (amount.getVatExemptionReasonText() != null)) {
exemptionReasonTextXML = "" + XMLTools.encodeXML(amount.getVatExemptionReasonText()) + " ";
}
xml += ""
+ "" + currencyFormat(amount.getCalculated())
+ " " //currencyID=\"EUR\"
+ "VAT "
+ exemptionReasonTextXML
+ "" + currencyFormat(amount.getBasis()) + " " // currencyID=\"EUR\"
+ "" + amountCategoryCode + " "
+ (amountDueDateTypeCode != null ? "" + amountDueDateTypeCode + " " : "")
+ ""
+ vatFormat(currentTaxPercent) + " ";
}
}
}
if ((trans.getDetailedDeliveryPeriodFrom() != null) || (trans.getDetailedDeliveryPeriodTo() != null)) {
xml += "";
if (trans.getDetailedDeliveryPeriodFrom() != null) {
xml += "" + DATE.udtFormat(trans.getDetailedDeliveryPeriodFrom()) + " ";
}
if (trans.getDetailedDeliveryPeriodTo() != null) {
xml += "" + DATE.udtFormat(trans.getDetailedDeliveryPeriodTo()) + " ";
}
xml += " ";
}
if ((trans.getZFCharges() != null) && (trans.getZFCharges().length > 0)) {
if (profile == Profiles.getByName("XRechnung")) {
for (IZUGFeRDAllowanceCharge charge : trans.getZFCharges()) {
xml += "" +
"" +
"true " +
" " +
"" + currencyFormat(charge.getTotalAmount(calc)) + " ";
if (charge.getReason() != null) {
xml += "" + XMLTools.encodeXML(charge.getReason()) + " ";
}
if (charge.getReasonCode() != null) {
xml += "" + charge.getReasonCode() + " ";
}
xml += "" +
"VAT " +
"" + charge.getCategoryCode() + " ";
if (charge.getTaxPercent() != null) {
xml += "" + vatFormat(charge.getTaxPercent()) + " ";
}
xml += " " +
" ";
}
} else {
for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) {
if (calc.getChargesForPercent(currentTaxPercent).compareTo(BigDecimal.ZERO) != 0) {
xml += "" +
"" +
"true " +
" " +
"" + currencyFormat(calc.getChargesForPercent(currentTaxPercent)) + " " +
"" + XMLTools.encodeXML(calc.getChargeReasonForPercent(currentTaxPercent)) + " " +
"" +
"VAT " +
"" + VATPercentAmountMap.get(currentTaxPercent).getCategoryCode() + " " +
"" + vatFormat(currentTaxPercent) + " " +
" " +
" ";
}
}
}
}
if ((trans.getZFAllowances() != null) && (trans.getZFAllowances().length > 0)) {
if (profile == Profiles.getByName("XRechnung")) {
for (IZUGFeRDAllowanceCharge allowance : trans.getZFAllowances()) {
xml += "" +
"" +
"false " +
" " +
"" + currencyFormat(allowance.getTotalAmount(calc)) + " ";
if (allowance.getReason() != null) {
xml += "" + XMLTools.encodeXML(allowance.getReason()) + " ";
}
if (allowance.getReasonCode() != null) {
xml += "" + allowance.getReasonCode() + " ";
}
xml += "" +
"VAT " +
"" + allowance.getCategoryCode() + " ";
if (allowance.getTaxPercent() != null) {
xml += "" + vatFormat(allowance.getTaxPercent()) + " ";
}
xml += " " +
" ";
}
} else {
for (final BigDecimal currentTaxPercent : VATPercentAmountMap.keySet()) {
if (calc.getAllowancesForPercent(currentTaxPercent).compareTo(BigDecimal.ZERO) != 0) {
xml += "" +
"" +
"false " +
" " +
"" + currencyFormat(calc.getAllowancesForPercent(currentTaxPercent)) + " " +
"" + XMLTools.encodeXML(calc.getAllowanceReasonForPercent(currentTaxPercent)) + " " +
"" +
"VAT " +
"" + VATPercentAmountMap.get(currentTaxPercent).getCategoryCode() + " " +
"" + vatFormat(currentTaxPercent) + " " +
" " +
" ";
}
}
}
}
if ((trans.getPaymentTerms() == null) && (getProfile() != Profiles.getByName("Minimum")) && ((paymentTermsDescription != null) || (trans.getTradeSettlement() != null) || (hasDueDate))) {
xml += "";
if (paymentTermsDescription != null) {
xml += "" + paymentTermsDescription + " ";
}
if (trans.getTradeSettlement() != null) {
for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) {
if ((payment != null) && (payment instanceof IZUGFeRDTradeSettlementDebit)) {
xml += payment.getPaymentXML();
}
}
}
if (trans.getDueDate() != null) {
xml += "" // $NON-NLS-2$
+ DATE.udtFormat(trans.getDueDate())
+ " ";// 20130704
}
xml += " ";
} else {
xml += buildPaymentTermsXml();
}
if ((profile == Profiles.getByName("Extended")) && (trans.getCashDiscounts() != null) && (trans.getCashDiscounts().length > 0)) {
for (IZUGFeRDCashDiscount discount : trans.getCashDiscounts()
) {
xml += discount.getAsCII();
}
}
final String allowanceTotalLine = "" + currencyFormat(calc.getAllowancesForPercent(null)) + " ";
final String chargesTotalLine = "" + currencyFormat(calc.getChargesForPercent(null)) + " ";
xml += "";
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BASICWL"))) {
xml += "" + currencyFormat(calc.getTotal()) + " ";
xml += chargesTotalLine
+ allowanceTotalLine;
}
xml += "" + currencyFormat(calc.getTaxBasis()) + " "
// //
// currencyID=\"EUR\"
+ ""
+ currencyFormat(calc.getGrandTotal().subtract(calc.getTaxBasis())) + " ";
if (trans.getRoundingAmount() != null) {
xml += "" + currencyFormat(trans.getRoundingAmount()) + " ";
}
xml += "" + currencyFormat(calc.getGrandTotal()) + " ";
// //
// currencyID=\"EUR\"
if (getProfile() != Profiles.getByName("Minimum")) {
xml += "" + currencyFormat(calc.getTotalPrepaid()) + " ";
}
xml += "" + currencyFormat(calc.getDuePayable()) + " "
+ " ";
if (trans.getInvoiceReferencedDocumentID() != null) {
xml += ""
+ ""
+ XMLTools.encodeXML(trans.getInvoiceReferencedDocumentID()) + " ";
if (trans.getInvoiceReferencedIssueDate() != null) {
xml += ""
+ DATE.qdtFormat(trans.getInvoiceReferencedIssueDate())
+ " ";
}
xml += " ";
}
xml += " ";
// + "\n"
// + "\n"
// + "\n"
// + "Wir erlauben uns Ihnen folgende Positionen aus der Lieferung Nr.
// 2013-51112 in Rechnung zu stellen: \n"
// + " \n"
// + " \n"
// + " \n";
xml += " "
+ " ";
final byte[] zugferdRaw;
zugferdRaw = xml.getBytes(StandardCharsets.UTF_8);
zugferdData = XMLTools.removeBOM(zugferdRaw);
}
protected String buildItemNotes(IZUGFeRDExportableItem currentItem) {
if (currentItem.getNotes() == null) {
return "";
}
return Arrays.stream(currentItem.getNotes())
.map(IncludedNote::unspecifiedNote)
.map(IncludedNote::toCiiXml)
.collect(Collectors.joining());
}
protected String buildNotes(IExportableTransaction exportableTransaction) {
final List includedNotes = new ArrayList<>();
Optional.ofNullable(exportableTransaction.getNotesWithSubjectCode()).ifPresent(includedNotes::addAll);
if (exportableTransaction.getNotes() != null) {
for (final String currentNote : exportableTransaction.getNotes()) {
includedNotes.add(IncludedNote.unspecifiedNote(currentNote));
}
}
if (exportableTransaction.rebateAgreementExists()) {
includedNotes.add(IncludedNote.discountBonusNote("Es bestehen Rabatt- und Bonusvereinbarungen."));
}
Optional.ofNullable(exportableTransaction.getOwnOrganisationFullPlaintextInfo())
.ifPresent(info -> includedNotes.add(IncludedNote.regulatoryNote(info)));
Optional.ofNullable(exportableTransaction.getSubjectNote())
.ifPresent(note -> includedNotes.add(IncludedNote.unspecifiedNote(note)));
return includedNotes.stream().map(IncludedNote::toCiiXml).collect(Collectors.joining(""));
}
@Override
public void setProfile(Profile p) {
profile = p;
}
private String buildPaymentTermsXml() {
final IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms();
if (paymentTerms == null) {
return "";
}
String paymentTermsXml = "";
final IZUGFeRDPaymentDiscountTerms discountTerms = paymentTerms.getDiscountTerms();
final Date dueDate = paymentTerms.getDueDate();
if (dueDate != null && discountTerms != null && discountTerms.getBaseDate() != null) {
throw new IllegalStateException(
"if paymentTerms.dueDate is specified, paymentTerms.discountTerms.baseDate has not to be specified");
}
paymentTermsXml += "" + paymentTerms.getDescription() + " ";
if (dueDate != null) {
paymentTermsXml += "";
paymentTermsXml += DATE.udtFormat(dueDate);
paymentTermsXml += " ";
}
if (trans.getTradeSettlement() != null) {
for (final IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) {
if ((payment != null) && (payment instanceof IZUGFeRDTradeSettlementDebit)) {
paymentTermsXml += payment.getPaymentXML();
}
}
}
if (discountTerms != null) {
paymentTermsXml += "";
final String currency = trans.getCurrency();
final String basisAmount = currencyFormat(calc.getGrandTotal());
paymentTermsXml += "" + basisAmount + " ";
paymentTermsXml += "" + discountTerms.getCalculationPercentage().toString()
+ " ";
if (discountTerms.getBaseDate() != null) {
final Date baseDate = discountTerms.getBaseDate();
paymentTermsXml += "";
paymentTermsXml += DATE.udtFormat(baseDate);
paymentTermsXml += " ";
paymentTermsXml += ""
+ discountTerms.getBasePeriodMeasure() + " ";
}
paymentTermsXml += " ";
}
paymentTermsXml += " ";
return paymentTermsXml;
}
}