diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java index 33a35e8c..920ab7d2 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java @@ -262,6 +262,16 @@ public interface IZUGFeRDExportableTransaction { return null; } + /** + * get payment terms. if set, getPaymentTermDescription() and getDueDate() are + * ignored + * + * @return + */ + default IZUGFeRDPaymentTerms getPaymentTerms() { + return null; + } + /** * get reference document number typically used for Invoice Corrections Will be added as IncludedNote in comfort profile diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDPaymentDiscountTerms.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDPaymentDiscountTerms.java new file mode 100644 index 00000000..ebb6bee0 --- /dev/null +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDPaymentDiscountTerms.java @@ -0,0 +1,15 @@ +package org.mustangproject.ZUGFeRD; + +import java.math.BigDecimal; + +public interface IZUGFeRDPaymentDiscountTerms { + + BigDecimal getCalculationPercentage(); + + IZUGFeRDDate getBaseDate(); + + int getBasePeriodMeasure(); + + String getBasePeriodUnitCode(); + +} diff --git a/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDPaymentTerms.java b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDPaymentTerms.java new file mode 100644 index 00000000..f49215bc --- /dev/null +++ b/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDPaymentTerms.java @@ -0,0 +1,10 @@ +package org.mustangproject.ZUGFeRD; + +public interface IZUGFeRDPaymentTerms { + + String getDescription(); + + IZUGFeRDDate getDueDate(); + + IZUGFeRDPaymentDiscountTerms getDiscountTerms(); +} diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 5181ab58..8724edf8 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -246,18 +246,18 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { public void generateXML(IZUGFeRDExportableTransaction trans) { this.trans = trans; - boolean hasDueDate = false; - String taxCategoryCode = ""; + boolean hasDueDate=false; + String taxCategoryCode=""; SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy"); //$NON-NLS-1$ SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); //$NON-NLS-1$ - String exemptionReason = ""; - - if (paymentTermsDescription == null) { - paymentTermsDescription = "Zahlbar ohne Abzug bis " + germanDateFormat.format(trans.getDueDate()); + String exemptionReason=""; + if (paymentTermsDescription==null) { + paymentTermsDescription= "Zahlbar ohne Abzug bis " + germanDateFormat.format(trans.getDueDate()); + } - if (trans.getPaymentTermDescription() != null) { - paymentTermsDescription = trans.getPaymentTermDescription(); + if (trans.getPaymentTermDescription()!=null) { + paymentTermsDescription=trans.getPaymentTermDescription(); } String senderReg = ""; @@ -311,11 +311,11 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { int lineID = 0; for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { lineID++; - taxCategoryCode = currentItem.getProduct().getTaxCategoryCode(); - if (currentItem.getProduct().isIntraCommunitySupply()) { - exemptionReason = "Intra-community supply"; + taxCategoryCode=currentItem.getProduct().getTaxCategoryCode(); + if (currentItem.getProduct().isIntraCommunitySupply()) { + exemptionReason="Intra-community supply"; } - + LineCalc lc = new LineCalc(currentItem); xml = xml + " \n" + //$NON-NLS-1$ " \n" //$NON-NLS-1$ @@ -325,8 +325,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { // + " 4012345001235\n" // + " KR3M\n" // + " 55T01\n" - + " " + XMLTools.encodeXML(currentItem.getProduct().getName()) //$NON-NLS-1$ - + "\n" //$NON-NLS-1$ + + " " + XMLTools.encodeXML(currentItem.getProduct().getName()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " " + XMLTools.encodeXML(currentItem.getProduct().getDescription()) //$NON-NLS-1$ + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ @@ -335,8 +334,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " \n" //$NON-NLS-1$ + " " + priceFormat(lc.getPriceGross()) //$NON-NLS-1$ + "\n" //$NON-NLS-1$ //currencyID=\"EUR\" - + " 1.0000\n" //$NON-NLS-1$ + + " 1.0000\n" //$NON-NLS-1$ // + " \n" // + " false\n" // + " 0.6667\n" @@ -346,22 +345,21 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " \n" //$NON-NLS-1$ + " " + priceFormat(currentItem.getPrice()) //$NON-NLS-1$ + "\n" //$NON-NLS-1$ // currencyID=\"EUR\" - + " 1.0000\n" //$NON-NLS-1$ + + " 1.0000\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ - + " " //$NON-NLS-1$ + + " " //$NON-NLS-1$ //$NON-NLS-2$ + quantityFormat(currentItem.getQuantity()) + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " VAT\n" //$NON-NLS-1$ - + exemptionReason - + " " + currentItem.getProduct().getTaxCategoryCode() //$NON-NLS-1$ - + "\n" + " " //$NON-NLS-2$ + + " "+currentItem.getProduct().getTaxCategoryCode()+"\n" //$NON-NLS-1$ + + exemptionReason + + " " //$NON-NLS-1$ + vatFormat(currentItem.getProduct().getVATPercent()) + "\n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ + " \n" //$NON-NLS-1$ @@ -375,25 +373,24 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { xml = xml + " \n"; //$NON-NLS-1$ if (trans.getReferenceNumber() != null) { - xml = xml + " " + XMLTools.encodeXML(trans.getReferenceNumber()) - + "\n"; + xml = xml + " " + XMLTools.encodeXML(trans.getReferenceNumber()) + "\n"; } xml = xml + " \n" //$NON-NLS-1$ // + " 4000001123452\n" + " " + XMLTools.encodeXML(trans.getOwnOrganisationName()) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ - if ((trans.getOwnVATID() != null) && (trans.getOwnOrganisationName() != null)) { - + if ((trans.getOwnVATID()!=null)&&(trans.getOwnOrganisationName()!=null)) { + xml = xml + " \n" + " " - + XMLTools.encodeXML(trans.getOwnVATID()) + "\n" - + " " + XMLTools.encodeXML(trans.getOwnOrganisationName()) - + "\n" + " "; + + XMLTools.encodeXML(trans.getOwnVATID()) + "\n" + " " + + XMLTools.encodeXML(trans.getOwnOrganisationName()) + "\n" + + " "; } if (trans.getOwnContact() != null) { - xml = xml + "\n" + " " - + XMLTools.encodeXML(trans.getOwnContact().getName()) + "\n"; + xml = xml + "\n" + " " + XMLTools.encodeXML(trans.getOwnContact().getName()) + + "\n"; if (trans.getOwnContact().getPhone() != null) { xml = xml + " \n" + " " @@ -412,41 +409,36 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { xml = xml + " \n" + " " + XMLTools.encodeXML(trans.getOwnZIP()) + "\n" + " " - + XMLTools.encodeXML(trans.getOwnStreet()) + "\n" + " " - + XMLTools.encodeXML(trans.getOwnLocation()) + "\n" + " " - + XMLTools.encodeXML(trans.getOwnCountry()) + "\n" - + " \n"; - if (trans.getOwnTaxID() != null) { - xml = xml + " \n" //$NON-NLS-1$ - + " " + XMLTools.encodeXML(trans.getOwnTaxID()) //$NON-NLS-1$ - + "\n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ - } - if (trans.getOwnTaxID() != null) { - xml = xml + " \n" //$NON-NLS-1$ - + " " + XMLTools.encodeXML(trans.getOwnVATID()) //$NON-NLS-1$ - + "\n" //$NON-NLS-1$ - + " \n"; //$NON-NLS-1$ - } - xml = xml + " \n" //$NON-NLS-1$ + + XMLTools.encodeXML(trans.getOwnStreet()) + "\n" + " " + XMLTools.encodeXML(trans.getOwnLocation()) + + "\n" + " " + XMLTools.encodeXML(trans.getOwnCountry()) + + "\n" + " \n" + + " \n" //$NON-NLS-1$ + + " " + XMLTools.encodeXML(trans.getOwnTaxID()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " \n" //$NON-NLS-1$ + + " \n" //$NON-NLS-1$ + + " " + XMLTools.encodeXML(trans.getOwnVATID()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + + " \n" //$NON-NLS-1$ + + " \n" //$NON-NLS-1$ + " \n"; //$NON-NLS-1$ - // + " GE2020211\n" - // + " 4000001987658\n" - - xml += getContactAsXML(trans.getRecipient()); - xml += " \n" //$NON-NLS-1$ + // + " GE2020211\n" + // + " 4000001987658\n" + + xml+=getContactAsXML(trans.getRecipient()); + xml += " \n" //$NON-NLS-1$ // + " \n" // + " 20130301\n" // + " 2013-471331\n" // + " \n" + " \n" //$NON-NLS-1$ - + " \n"; - if (this.trans.getDeliveryAddress() != null) { - xml += "" + getContactAsXML(this.trans.getDeliveryAddress()) - + ""; + + " \n" ; + if (this.trans.getDeliveryAddress()!=null) { + xml += ""+ + getContactAsXML(this.trans.getDeliveryAddress())+ + ""; } - - xml += " \n" + " "; + + xml+= " \n" + + " "; if (trans.getZFDeliveryDate() != null) { ZUGFeRDDateFormat dateFormat = trans.getZFDeliveryDate().getFormat(); @@ -468,25 +460,24 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { * " \n" */ + " \n" + " \n" //$NON-NLS-2$ - + " " + XMLTools.encodeXML(trans.getNumber()) //$NON-NLS-1$ - + "\n" //$NON-NLS-1$ + + " " + XMLTools.encodeXML(trans.getNumber()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + " " + trans.getCurrency() + "\n"; //$NON-NLS-1$ - if (trans.getTradeSettlementPayment() != null) { + if (trans.getTradeSettlementPayment()!=null) { for (IZUGFeRDTradeSettlementPayment payment : trans.getTradeSettlementPayment()) { - if (payment != null) { - hasDueDate = true; - xml += payment.getSettlementXML(); + if(payment!=null) { + hasDueDate=true; + xml+=payment.getSettlementXML(); } } } - if (trans.getTradeSettlement() != null) { + if (trans.getTradeSettlement()!=null) { for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { - if (payment != null) { + if(payment!=null) { if (payment instanceof IZUGFeRDTradeSettlementPayment) { - hasDueDate = true; + hasDueDate=true; } - xml += payment.getSettlementXML(); + xml+=payment.getSettlementXML(); } } } @@ -499,34 +490,39 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " " + currencyFormat(amount.getCalculated()) //$NON-NLS-1$ + "\n" //$NON-NLS-1$ //currencyID=\"EUR\" + " VAT\n" //$NON-NLS-1$ - + exemptionReason + " " + currencyFormat(amount.getBasis()) + "\n" // currencyID=\"EUR\" - + " " + taxCategoryCode + "\n" //$NON-NLS-1$ + + " "+taxCategoryCode+"\n" //$NON-NLS-1$ + + exemptionReason + " " + vatFormat(currentTaxPercent) //$NON-NLS-1$ + "\n" + " \n"; //$NON-NLS-2$ } } - xml = xml + " \n" //$NON-NLS-1$ - + " " + paymentTermsDescription + "\n"; + if (trans.getPaymentTerms() == null) { + xml = xml + " \n" //$NON-NLS-1$ + + " " + paymentTermsDescription + "\n"; - if (trans.getTradeSettlement() != null) { - for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { - if (payment != null) { - xml += payment.getPaymentXML(); + if (trans.getTradeSettlement() != null) { + for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { + if (payment != null) { + xml += payment.getPaymentXML(); + } } } + + if (hasDueDate) { + xml = xml + " " // $NON-NLS-2$ + + zugferdDateFormat.format(trans.getDueDate()) + + "\n";// 20130704 //$NON-NLS-1$ + + } + xml = xml + " \n"; //$NON-NLS-1$ + } else { + xml = xml + buildPaymentTermsXml(); } - if (hasDueDate) { - xml = xml + " " // $NON-NLS-2$ - + zugferdDateFormat.format(trans.getDueDate()) + "\n";// 20130704 //$NON-NLS-1$ - - } - - xml = xml + " \n" //$NON-NLS-1$ - + " \n" //$NON-NLS-1$ + xml = xml + " \n" //$NON-NLS-1$ + " " + currencyFormat(getTotal()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // currencyID=\"EUR\" + " 0.00\n" //$NON-NLS-1$ currencyID=\"EUR\" @@ -542,11 +538,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { + " " + currencyFormat(getTotalGross()) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ // // // currencyID=\"EUR\" - + " " + currencyFormat(getTotalPrepaid()) - + "\n" + " " //$NON-NLS-2$ - + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "\n" //$NON-NLS-1$ - // // - // currencyID=\"EUR\" + + " " + currencyFormat(getTotalPrepaid()) + "\n" + + " " + currencyFormat(getTotalGross().subtract(getTotalPrepaid())) + "\n" //$NON-NLS-1$ //$NON-NLS-2$ + // // + // currencyID=\"EUR\" + " \n" //$NON-NLS-1$ + " \n"; //$NON-NLS-1$ // + " \n" @@ -577,4 +572,48 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { } // $NON-NLS-1$ } + private String buildPaymentTermsXml() { + String paymentTermsXml = ""; + + IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms(); + IZUGFeRDPaymentDiscountTerms discountTerms = paymentTerms.getDiscountTerms(); + IZUGFeRDDate 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 += "" + + dueDate.getFormat().getFormatter().format(dueDate.getDate()) + ""; + paymentTermsXml += ""; + } + + if (discountTerms != null) { + paymentTermsXml += ""; + String currency = trans.getCurrency(); + String basisAmount = currencyFormat(getTotalGross()); + paymentTermsXml += "" + basisAmount + ""; + paymentTermsXml += "" + discountTerms.getCalculationPercentage().toString() + + ""; + + if (discountTerms.getBaseDate() != null) { + Date baseDate = discountTerms.getBaseDate().getDate(); + ZUGFeRDDateFormat baseDateFormat = discountTerms.getBaseDate().getFormat(); + paymentTermsXml += ""; + paymentTermsXml += "" + baseDateFormat.getFormatter().format(baseDate) + ""; + paymentTermsXml += ""; + + paymentTermsXml += "" + + discountTerms.getBasePeriodMeasure() + ""; + } + + paymentTermsXml += ""; + } + + paymentTermsXml += ""; + return paymentTermsXml; + } + } diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java index e7fca721..b89f17de 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDTransactionModelConverter.java @@ -44,6 +44,7 @@ import org.mustangproject.ZUGFeRD.model.ExchangedDocumentType; import org.mustangproject.ZUGFeRD.model.IDType; import org.mustangproject.ZUGFeRD.model.IndicatorType; import org.mustangproject.ZUGFeRD.model.LogisticsServiceChargeType; +import org.mustangproject.ZUGFeRD.model.MeasureType; import org.mustangproject.ZUGFeRD.model.NoteType; import org.mustangproject.ZUGFeRD.model.NoteTypeConstants; import org.mustangproject.ZUGFeRD.model.ObjectFactory; @@ -67,6 +68,7 @@ import org.mustangproject.ZUGFeRD.model.TextType; import org.mustangproject.ZUGFeRD.model.TradeAddressType; import org.mustangproject.ZUGFeRD.model.TradeAllowanceChargeType; import org.mustangproject.ZUGFeRD.model.TradePartyType; +import org.mustangproject.ZUGFeRD.model.TradePaymentDiscountTermsType; import org.mustangproject.ZUGFeRD.model.TradePaymentTermsType; import org.mustangproject.ZUGFeRD.model.TradePriceType; import org.mustangproject.ZUGFeRD.model.TradeProductType; @@ -675,6 +677,9 @@ class ZUGFeRDTransactionModelConverter { private Collection getPaymentTerms() { + if (trans.getPaymentTerms() != null) { + return handlePaymentTermsObject(trans.getPaymentTerms()); + } List paymentTerms = new ArrayList<>(); TradePaymentTermsType paymentTerm = xmlFactory @@ -701,6 +706,69 @@ class ZUGFeRDTransactionModelConverter { return paymentTerms; } + private Collection handlePaymentTermsObject(IZUGFeRDPaymentTerms paymentTerms) { + List xmlPaymentTerms = new ArrayList<>(); + + TradePaymentTermsType paymentTerm = xmlFactory.createTradePaymentTermsType(); + + TextType paymentTermDescr = xmlFactory.createTextType(); + + String paymentTermDescription = paymentTerms.getDescription(); + if (paymentTermDescription == null) { + paymentTermDescription = ""; + } + paymentTermDescr.setValue(paymentTermDescription); + paymentTerm.getDescription().add(paymentTermDescr); + + IZUGFeRDPaymentDiscountTerms discountTerms = paymentTerms.getDiscountTerms(); + if (paymentTerms.getDueDate() != null && discountTerms != null && discountTerms.getBaseDate() != null) { + throw new IllegalStateException( + "if paymentTerms.dueDate is specified, paymentTerms.discountTerms.baseDate has not to be specified"); + } + + if (paymentTerms.getDueDate() != null) { + DateTimeType dueDate = xmlFactory.createDateTimeType(); + DateTimeType.DateTimeString dueDateString = xmlFactory.createDateTimeTypeDateTimeString(); + dueDateString.setFormat(paymentTerms.getDueDate().getFormat().getDateTimeType()); + dueDateString.setValue( + paymentTerms.getDueDate().getFormat().getFormatter().format(paymentTerms.getDueDate().getDate())); + dueDate.setDateTimeString(dueDateString); + paymentTerm.setDueDateDateTime(dueDate); + } + + if (discountTerms != null) { + TradePaymentDiscountTermsType tradePaymentDiscountTerms = xmlFactory.createTradePaymentDiscountTermsType(); + + PercentType calculationPercent = xmlFactory.createPercentType(); + calculationPercent.setValue(discountTerms.getCalculationPercentage()); + tradePaymentDiscountTerms.setCalculationPercent(calculationPercent); + + AmountType basisAmount = xmlFactory.createAmountType(); + basisAmount.setCurrencyID(currency); + basisAmount.setValue(currencyFormat(totals.totalGrossAmount)); + tradePaymentDiscountTerms.getBasisAmount().add(basisAmount); + + if (discountTerms.getBaseDate() != null) { + DateTimeType baseDate = xmlFactory.createDateTimeType(); + DateTimeType.DateTimeString baseDateString = xmlFactory.createDateTimeTypeDateTimeString(); + baseDateString.setFormat(discountTerms.getBaseDate().getFormat().getDateTimeType()); + baseDateString.setValue(discountTerms.getBaseDate().getFormat().getFormatter() + .format(discountTerms.getBaseDate().getDate())); + baseDate.setDateTimeString(baseDateString); + tradePaymentDiscountTerms.setBasisDateTime(baseDate); + + MeasureType basisPeriodMeasure = xmlFactory.createMeasureType(); + basisPeriodMeasure.setUnitCode(discountTerms.getBasePeriodUnitCode()); + basisPeriodMeasure.setValue(new BigDecimal(discountTerms.getBasePeriodMeasure())); + tradePaymentDiscountTerms.setBasisPeriodMeasure(basisPeriodMeasure); + } + paymentTerm.getApplicableTradePaymentDiscountTerms().add(tradePaymentDiscountTerms); + } + xmlPaymentTerms.add(paymentTerm); + + return xmlPaymentTerms; + } + private TradeSettlementMonetarySummationType getMonetarySummation() { TradeSettlementMonetarySummationType monetarySummation = xmlFactory