Merge pull request #161 from heisej/bugfixes_and_new_export_props

Bugfixes and new export props
This commit is contained in:
Jochen Staerk
2020-06-03 20:20:44 +02:00
committed by GitHub
5 changed files with 109 additions and 37 deletions

View File

@@ -47,12 +47,21 @@ public interface IZUGFeRDExportableItem {
BigDecimal getPrice(); BigDecimal getPrice();
/** /**
* how many * how many get billed
* *
* @return the quantity of the item * @return the quantity of the item
*/ */
BigDecimal getQuantity(); BigDecimal getQuantity();
/**
* how many items units per price
*
* @return item units per price
*/
default BigDecimal getBasisQuantity() {
return BigDecimal.ONE.setScale(4);
}
default String getCategoryCode() { default String getCategoryCode() {
return TaxCategoryCodeTypeConstants.STANDARDRATE; return TaxCategoryCodeTypeConstants.STANDARDRATE;
} }

View File

@@ -75,6 +75,25 @@ public interface IZUGFeRDExportableProduct {
*/ */
String getDescription(); String getDescription();
/**
* Get the ID that had been assigned by the seller to
* identify the product
*
* @return seller assigned product ID
*/
default String getSellerAssignedID() {
return null;
}
/**
* Get the ID that had been assigned by the buyer to
* identify the product
*
* @return buyer assigned product ID
*/
default String getBuyerAssignedID() {
return null;
}
/** /**
* VAT percent of the product (e.g. 19, or 5.1 if you like) * VAT percent of the product (e.g. 19, or 5.1 if you like)
* *
@@ -95,5 +114,9 @@ public interface IZUGFeRDExportableProduct {
} }
} }
default String getTaxExemptionReason() {
if (isIntraCommunitySupply())
return "Intra-community supply";
return null;
}
} }

View File

@@ -106,6 +106,16 @@ public interface IZUGFeRDExportableTransaction {
} }
/**
* subject of the document e.g. invoice and order
* number as human readable text
*
* @return string with document subject
*/
default String getSubjectNote() {
return null;
}
IZUGFeRDAllowanceCharge[] getZFAllowances(); IZUGFeRDAllowanceCharge[] getZFAllowances();
@@ -272,6 +282,14 @@ public interface IZUGFeRDExportableTransaction {
return null; return null;
} }
/**
* returns if a rebate agreements exists
*
* @return
*/
default boolean rebateAgreementExists() {
return false;
}
/** /**
* get reference document number typically used for Invoice Corrections Will be added as IncludedNote in comfort profile * get reference document number typically used for Invoice Corrections Will be added as IncludedNote in comfort profile

View File

@@ -48,9 +48,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
BigDecimal multiplicator = currentItem.getProduct().getVATPercent().divide(new BigDecimal(100)) BigDecimal multiplicator = currentItem.getProduct().getVATPercent().divide(new BigDecimal(100))
.add(new BigDecimal(1)); .add(new BigDecimal(1));
priceGross = currentItem.getPrice().multiply(multiplicator); priceGross = currentItem.getPrice().multiply(multiplicator);
totalGross = currentItem.getPrice().multiply(multiplicator).multiply(currentItem.getQuantity()); totalGross = currentItem.getQuantity().multiply(currentItem.getPrice()).divide(currentItem.getBasisQuantity())
itemTotalNetAmount = currentItem.getQuantity().multiply(currentItem.getPrice()).setScale(2, .multiply(multiplicator);
BigDecimal.ROUND_HALF_UP); itemTotalNetAmount = currentItem.getQuantity().multiply(currentItem.getPrice()).divide(currentItem.getBasisQuantity())
.setScale(2, BigDecimal.ROUND_HALF_UP);
itemTotalVATAmount = totalGross.subtract(itemTotalNetAmount); itemTotalVATAmount = totalGross.subtract(itemTotalNetAmount);
} }
@@ -268,6 +269,20 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
} }
String rebateAgreement = "";
if (trans.rebateAgreementExists()) {
rebateAgreement = "<ram:IncludedNote>\n" + " <ram:Content>"
+ "Es bestehen Rabatt- und Bonusvereinbarungen.</ram:Content>\n"
+ "<ram:SubjectCode>AAK</ram:SubjectCode>\n" + "</ram:IncludedNote>\n";
}
String subjectNote = "";
if (trans.getSubjectNote()!=null) {
subjectNote = "<ram:IncludedNote>\n" + " <ram:Content>"
+ XMLTools.encodeXML(trans.getSubjectNote())+ "</ram:Content>\n"
+ "</ram:IncludedNote>\n";
}
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" //$NON-NLS-1$ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" //$NON-NLS-1$
+ "<rsm:CrossIndustryInvoice xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\"" + "<rsm:CrossIndustryInvoice xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:rsm=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100\""
@@ -293,27 +308,18 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
// format // format
// was // was
// 20130605 // 20130605
+ subjectNote
+ rebateAgreement
+ senderReg + senderReg
// + " <IncludedNote>\n"
// + " <Content>\n"
// + "Rechnung gemäß Bestellung Nr. 2013-471331 vom 01.03.2013.\n"
// + "\n"
// + " </Content>\n"
// + " </IncludedNote>\n"
// + " <IncludedNote>\n"
// + " <Content>\n"
// + "Es bestehen Rabatt- und Bonusvereinbarungen.\n"
// + " </Content>\n"
// + " <SubjectCode>AAK</SubjectCode>\n"
// + " </IncludedNote>\n"
+ " </rsm:ExchangedDocument>\n" //$NON-NLS-1$ + " </rsm:ExchangedDocument>\n" //$NON-NLS-1$
+ " <rsm:SupplyChainTradeTransaction>\n"; //$NON-NLS-1$ + " <rsm:SupplyChainTradeTransaction>\n"; //$NON-NLS-1$
int lineID = 0; int lineID = 0;
for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) { for (IZUGFeRDExportableItem currentItem : trans.getZFItems()) {
lineID++; lineID++;
taxCategoryCode=currentItem.getProduct().getTaxCategoryCode(); taxCategoryCode=currentItem.getProduct().getTaxCategoryCode();
if (currentItem.getProduct().isIntraCommunitySupply()) { if (currentItem.getProduct().getTaxExemptionReason() != null) {
exemptionReason="<ram:ExemptionReason>Intra-community supply</ram:ExemptionReason>"; exemptionReason="<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
} }
LineCalc lc = new LineCalc(currentItem); LineCalc lc = new LineCalc(currentItem);
@@ -321,11 +327,17 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
" <ram:AssociatedDocumentLineDocument>\n" //$NON-NLS-1$ " <ram:AssociatedDocumentLineDocument>\n" //$NON-NLS-1$
+ " <ram:LineID>" + lineID + "</ram:LineID>\n" //$NON-NLS-1$ //$NON-NLS-2$ + " <ram:LineID>" + lineID + "</ram:LineID>\n" //$NON-NLS-1$ //$NON-NLS-2$
+ " </ram:AssociatedDocumentLineDocument>\n" //$NON-NLS-1$ + " </ram:AssociatedDocumentLineDocument>\n" //$NON-NLS-1$
+ " <ram:SpecifiedTradeProduct>\n" //$NON-NLS-1$ + " <ram:SpecifiedTradeProduct>\n"; //$NON-NLS-1$
// + " <GlobalID schemeID=\"0160\">4012345001235</GlobalID>\n" // + " <GlobalID schemeID=\"0160\">4012345001235</GlobalID>\n"
// + " <SellerAssignedID>KR3M</SellerAssignedID>\n" if (currentItem.getProduct().getSellerAssignedID() != null) {
// + " <BuyerAssignedID>55T01</BuyerAssignedID>\n" xml = xml + " <ram:SellerAssignedID>"
+ " <ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>\n" //$NON-NLS-1$ //$NON-NLS-2$ + XMLTools.encodeXML(currentItem.getProduct().getSellerAssignedID()) + "</ram:SellerAssignedID>\n";
}
if (currentItem.getProduct().getBuyerAssignedID() != null) {
xml = xml + " <ram:BuyerAssignedID>"
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>\n";
}
xml = xml + " <ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>\n" //$NON-NLS-1$ //$NON-NLS-2$
+ " <ram:Description>" + XMLTools.encodeXML(currentItem.getProduct().getDescription()) //$NON-NLS-1$ + " <ram:Description>" + XMLTools.encodeXML(currentItem.getProduct().getDescription()) //$NON-NLS-1$
+ "</ram:Description>\n" //$NON-NLS-1$ + "</ram:Description>\n" //$NON-NLS-1$
+ " </ram:SpecifiedTradeProduct>\n" //$NON-NLS-1$ + " </ram:SpecifiedTradeProduct>\n" //$NON-NLS-1$
@@ -335,7 +347,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
+ " <ram:ChargeAmount>" + priceFormat(lc.getPriceGross()) //$NON-NLS-1$ + " <ram:ChargeAmount>" + priceFormat(lc.getPriceGross()) //$NON-NLS-1$
+ "</ram:ChargeAmount>\n" //$NON-NLS-1$ //currencyID=\"EUR\" + "</ram:ChargeAmount>\n" //$NON-NLS-1$ //currencyID=\"EUR\"
+ " <ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit()) //$NON-NLS-1$ + " <ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit()) //$NON-NLS-1$
+ "\">1.0000</ram:BasisQuantity>\n" //$NON-NLS-1$ + "\">" + quantityFormat(currentItem.getBasisQuantity()) +"</ram:BasisQuantity>\n" //$NON-NLS-1$
// + " <AppliedTradeAllowanceCharge>\n" // + " <AppliedTradeAllowanceCharge>\n"
// + " <ChargeIndicator>false</ChargeIndicator>\n" // + " <ChargeIndicator>false</ChargeIndicator>\n"
// + " <ActualAmount currencyID=\"EUR\">0.6667</ActualAmount>\n" // + " <ActualAmount currencyID=\"EUR\">0.6667</ActualAmount>\n"
@@ -346,7 +358,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
+ " <ram:ChargeAmount>" + priceFormat(currentItem.getPrice()) //$NON-NLS-1$ + " <ram:ChargeAmount>" + priceFormat(currentItem.getPrice()) //$NON-NLS-1$
+ "</ram:ChargeAmount>\n" //$NON-NLS-1$ // currencyID=\"EUR\" + "</ram:ChargeAmount>\n" //$NON-NLS-1$ // currencyID=\"EUR\"
+ " <ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit()) //$NON-NLS-1$ + " <ram:BasisQuantity unitCode=\"" + XMLTools.encodeXML(currentItem.getProduct().getUnit()) //$NON-NLS-1$
+ "\">1.0000</ram:BasisQuantity>\n" //$NON-NLS-1$ + "\">" + quantityFormat(currentItem.getBasisQuantity()) +"</ram:BasisQuantity>\n" //$NON-NLS-1$
+ " </ram:NetPriceProductTradePrice>\n" //$NON-NLS-1$ + " </ram:NetPriceProductTradePrice>\n" //$NON-NLS-1$
+ " </ram:SpecifiedLineTradeAgreement>\n" //$NON-NLS-1$ + " </ram:SpecifiedLineTradeAgreement>\n" //$NON-NLS-1$
@@ -381,9 +393,16 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
xml = xml + " <ram:BuyerReference>" + XMLTools.encodeXML(trans.getReferenceNumber()) + "</ram:BuyerReference>\n"; xml = xml + " <ram:BuyerReference>" + XMLTools.encodeXML(trans.getReferenceNumber()) + "</ram:BuyerReference>\n";
} }
xml = xml + " <ram:SellerTradeParty>\n" //$NON-NLS-1$ xml = xml + " <ram:SellerTradeParty>\n"; //$NON-NLS-1$
// + " <GlobalID schemeID=\"0088\">4000001123452</GlobalID>\n" if (trans.getOwnForeignOrganisationID()!=null) {
+ " <ram:Name>" + XMLTools.encodeXML(trans.getOwnOrganisationName()) + "</ram:Name>\n"; //$NON-NLS-1$ //$NON-NLS-2$ xml = xml + " <ram:ID>" + XMLTools.encodeXML(trans.getOwnForeignOrganisationID()) + "</ram:ID>\n";
}
if ((trans.getOwnContact()!=null)&&(trans.getOwnContact().getGlobalID()!=null)&&(trans.getOwnContact().getGlobalIDScheme()!=null)) {
xml = xml + " <ram:GlobalID schemeID=\"" + XMLTools.encodeXML(trans.getOwnContact().getGlobalIDScheme()) + "\">"
+ XMLTools.encodeXML(trans.getOwnContact().getGlobalID()) + "</ram:GlobalID>\n";
}
xml = xml + " <ram:Name>" + XMLTools.encodeXML(trans.getOwnOrganisationName()) + "</ram:Name>\n"; //$NON-NLS-1$ //$NON-NLS-2$
if ((trans.getOwnVATID()!=null)&&(trans.getOwnOrganisationName()!=null)) { if ((trans.getOwnVATID()!=null)&&(trans.getOwnOrganisationName()!=null)) {
@@ -429,12 +448,15 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
// + " <GlobalID schemeID=\"0088\">4000001987658</GlobalID>\n" // + " <GlobalID schemeID=\"0088\">4000001987658</GlobalID>\n"
xml+=getContactAsXML(trans.getRecipient()); xml+=getContactAsXML(trans.getRecipient());
xml += " </ram:BuyerTradeParty>\n" //$NON-NLS-1$ xml += " </ram:BuyerTradeParty>\n"; //$NON-NLS-1$
// + " <BuyerOrderReferencedDocument>\n"
// + " <IssueDateTime format=\"102\">20130301</IssueDateTime>\n" if (trans.getBuyerOrderReferencedDocumentID()!=null) {
// + " <ID>2013-471331</ID>\n" xml = xml + " <ram:BuyerOrderReferencedDocument>\n" //$NON-NLS-1$
// + " </BuyerOrderReferencedDocument>\n" + " <ram:IssuerAssignedID>" //$NON-NLS-1$
+ " </ram:ApplicableHeaderTradeAgreement>\n" //$NON-NLS-1$ + XMLTools.encodeXML(trans.getBuyerOrderReferencedDocumentID()) + "</ram:IssuerAssignedID>\n" //$NON-NLS-1$
+ " </ram:BuyerOrderReferencedDocument>\n";
}
xml = xml + " </ram:ApplicableHeaderTradeAgreement>\n" //$NON-NLS-1$
+ " <ram:ApplicableHeaderTradeDelivery>\n" ; + " <ram:ApplicableHeaderTradeDelivery>\n" ;
if (this.trans.getDeliveryAddress()!=null) { if (this.trans.getDeliveryAddress()!=null) {
xml += "<ram:ShipToTradeParty>"+ xml += "<ram:ShipToTradeParty>"+
@@ -510,13 +532,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider {
if (trans.getTradeSettlement() != null) { if (trans.getTradeSettlement() != null) {
for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) { for (IZUGFeRDTradeSettlement payment : trans.getTradeSettlement()) {
if (payment != null) { if ((payment != null) && (payment instanceof IZUGFeRDTradeSettlementDebit)) {
xml += payment.getPaymentXML(); xml += payment.getPaymentXML();
} }
} }
} }
if (hasDueDate) { if (hasDueDate && (trans.getDueDate()!=null)) {
xml = xml + " <ram:DueDateDateTime><udt:DateTimeString format=\"102\">" // $NON-NLS-2$ xml = xml + " <ram:DueDateDateTime><udt:DateTimeString format=\"102\">" // $NON-NLS-2$
+ zugferdDateFormat.format(trans.getDueDate()) + zugferdDateFormat.format(trans.getDueDate())
+ "</udt:DateTimeString></ram:DueDateDateTime>\n";// 20130704 //$NON-NLS-1$ + "</udt:DateTimeString></ram:DueDateDateTime>\n";// 20130704 //$NON-NLS-1$

View File

@@ -41,7 +41,7 @@ import junit.framework.TestSuite;
* used for this import, testout-ZF2New.pdf * used for this import, testout-ZF2New.pdf
*/ */
public class ZF2ZInvoiceImporterTest extends TestCase { public class ZF2ZInvoiceImporterTest extends TestCase {
final String TARGET_PDF = "./target/testout-ZF2New.pdf"; final String TARGET_PDF = "./target/testout-ZF2new.pdf";
public void testInvoiceImport() { public void testInvoiceImport() {