added item delivery periods

This commit is contained in:
jstaerk
2020-11-21 12:50:55 +01:00
parent 81dc18d731
commit 39d98d1e9d
5 changed files with 115 additions and 29 deletions

View File

@@ -1,13 +1,8 @@
### 2.0.1 todo 2.0.1
- 2.1 support kleinunternehmer, reverse charge? =====
- dont show empty tax number field 2020-11-12
- fail when no bankverbindung?
- fail when xr attrs missing?
- build xr skonto???
- *validator not to XR error on ZF files (only notices)
- xmp errors may not show correctly in log
### 2.0.1 done
- corrected VAT calculation on prices with >2 decimals (PR#195 thanks to weclapp-dev) - corrected VAT calculation on prices with >2 decimals (PR#195 thanks to weclapp-dev)
- have fax numbers only in appropriate profiles, i.e., extended - have fax numbers only in appropriate profiles, i.e., extended
- do not list tax numbers for shiptotradeparties - do not list tax numbers for shiptotradeparties
@@ -16,6 +11,9 @@
- BigDecimal specific refactoring PR #192 Thanks to weclapp-dev - BigDecimal specific refactoring PR #192 Thanks to weclapp-dev
- Preserving metadata PR #193 Thanks to mr-stephan - Preserving metadata PR #193 Thanks to mr-stephan
- support zero-rated goods: confirm that VAT category code switches from S to Z on 0%VAT - support zero-rated goods: confirm that VAT category code switches from S to Z on 0%VAT
- new sample invoice
- delivery period also on item level
- corrected more than 100 javadoc entries
2.0.0 2.0.0
===== =====

View File

@@ -5,12 +5,14 @@ import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
/*** /***
* describes any invoice line * describes any invoice line
*/ */
public class Item implements IZUGFeRDExportableItem { public class Item implements IZUGFeRDExportableItem {
protected BigDecimal price, quantity, tax, grossPrice, lineTotalAmount; protected BigDecimal price, quantity, tax, grossPrice, lineTotalAmount;
protected Date detailedDeliveryPeriodFrom=null, detailedDeliveryPeriodTo=null;
protected String id; protected String id;
protected Product product; protected Product product;
protected ArrayList<String> notes = null; protected ArrayList<String> notes = null;
@@ -58,6 +60,7 @@ public class Item implements IZUGFeRDExportableItem {
return this; return this;
} }
public BigDecimal getTax() { public BigDecimal getTax() {
return tax; return tax;
} }
@@ -135,11 +138,23 @@ public class Item implements IZUGFeRDExportableItem {
} }
/***
* Adds a item level addition to the price (will be multiplied by quantity)
* @see org.mustangproject.Charge
* @param izac a relative or absolute charge
* @return fluent setter
*/
public Item addCharge(IZUGFeRDAllowanceCharge izac) { public Item addCharge(IZUGFeRDAllowanceCharge izac) {
Charges.add(izac); Charges.add(izac);
return this; return this;
} }
/***
* Adds a item level reduction the price (will be multiplied by quantity)
* @see org.mustangproject.Allowance
* @param izac a relative or absolute allowance
* @return fluent setter
*/
public Item addAllowance(IZUGFeRDAllowanceCharge izac) { public Item addAllowance(IZUGFeRDAllowanceCharge izac) {
Allowances.add(izac); Allowances.add(izac);
return this; return this;
@@ -158,5 +173,37 @@ public class Item implements IZUGFeRDExportableItem {
return this; return this;
} }
/***
* specify a item level delivery period
* (apart from the document level delivery period, and the document level
* delivery day, which is probably anyway required)
*
* @param from start date
* @param to end date
* @return fluent setter
*/
public Item setDetailedDeliveryPeriod(Date from, Date to) {
detailedDeliveryPeriodFrom=from;
detailedDeliveryPeriodTo=to;
return this;
}
/***
* specifies the item level delivery period (there is also one on document level),
* this will be included in a BillingSpecifiedPeriod element
* @return the beginning of the delivery period
*/
public Date getDetailedDeliveryPeriodFrom() {
return detailedDeliveryPeriodFrom;
}
/***
* specifies the item level delivery period (there is also one on document level),
* this will be included in a BillingSpecifiedPeriod element
* @return the end of the delivery period
*/
public Date getDetailedDeliveryPeriodTo() {
return detailedDeliveryPeriodTo;
}
} }

View File

@@ -27,6 +27,7 @@ package org.mustangproject.ZUGFeRD;
* */ * */
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date;
public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
@@ -88,4 +89,24 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
return null; return null;
} }
/***
* specifies the item level delivery period (there is also one on document level),
* this will be included in a BillingSpecifiedPeriod element
* @return the beginning of the delivery period
*/
default Date getDetailedDeliveryPeriodFrom() {
return null;
}
/***
* specifies the item level delivery period (there is also one on document level),
* this will be included in a BillingSpecifiedPeriod element
* @return the end of the delivery period
*/
default Date getDetailedDeliveryPeriodTo() {
return null;
}
} }

View File

@@ -107,6 +107,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
} }
// @todo check if the two boolean args can be refactored // @todo check if the two boolean args can be refactored
/*** /***
* returns the UN/CEFACT CII XML for companies(tradeparties), which is actually * returns the UN/CEFACT CII XML for companies(tradeparties), which is actually
* the same for ZF1 (v 2013b) and ZF2 (v 2016b) * the same for ZF1 (v 2013b) and ZF2 (v 2016b)
@@ -378,8 +379,20 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ " <ram:RateApplicablePercent>" + " <ram:RateApplicablePercent>"
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>\n" + vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>\n"
+ " </ram:ApplicableTradeTax>\n" + " </ram:ApplicableTradeTax>\n";
+ " <ram:SpecifiedTradeSettlementLineMonetarySummation>\n" if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) {
xml = xml + "<ram:BillingSpecifiedPeriod>";
if (currentItem.getDetailedDeliveryPeriodFrom() != null) {
xml = xml + "<ram:StartDateTime><udt:DateTimeString format='102'>" + zugferdDateFormat.format(currentItem.getDetailedDeliveryPeriodFrom()) + "</udt:DateTimeString></ram:StartDateTime>";
}
if (currentItem.getDetailedDeliveryPeriodTo() != null) {
xml = xml + "<ram:EndDateTime><udt:DateTimeString format='102'>" + zugferdDateFormat.format(currentItem.getDetailedDeliveryPeriodTo()) + "</udt:DateTimeString></ram:EndDateTime>";
}
xml = xml + "</ram:BillingSpecifiedPeriod>";
}
xml = xml + " <ram:SpecifiedTradeSettlementLineMonetarySummation>\n"
+ " <ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount()) + " <ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount())
+ "</ram:LineTotalAmount>\n" // currencyID=\"EUR\" + "</ram:LineTotalAmount>\n" // currencyID=\"EUR\"
+ " </ram:SpecifiedTradeSettlementLineMonetarySummation>\n"; + " </ram:SpecifiedTradeSettlementLineMonetarySummation>\n";

View File

@@ -242,6 +242,9 @@ public class ZF2PushTest extends TestCase {
} }
/***
* test the edge cases of the invoice class
*/
public void testPushEdge() { public void testPushEdge() {
String orgname = "Test company"; String orgname = "Test company";
@@ -262,7 +265,7 @@ public class ZF2PushTest extends TestCase {
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID).setID("0009845")) .setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID).setID("0009845"))
.setDeliveryAddress(new TradeParty("just the other side of the street", "teststr.12a", "55232", "Entenhausen", "DE").addVATID("DE47110")) .setDeliveryAddress(new TradeParty("just the other side of the street", "teststr.12a", "55232", "Entenhausen", "DE").addVATID("DE47110"))
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setID("0008734").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE").setFax("++49555123456"))) .setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setID("0008734").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "franz@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE").setFax("++49555123456")))
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(16)), price, new BigDecimal(1.0)).addNote("item level 1/1").addAllowance(new Allowance(new BigDecimal(0.02)).setReason("item discount").setTaxPercent(new BigDecimal(16)))) .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(16)), price, new BigDecimal(1.0)).addNote("item level 1/1").addAllowance(new Allowance(new BigDecimal(0.02)).setReason("item discount").setTaxPercent(new BigDecimal(16))).setDetailedDeliveryPeriod(sdf.parse("2020-01-13"),sdf.parse("2020-01-15")))
.addCharge(new Charge(new BigDecimal(0.5)).setReason("quick delivery charge").setTaxPercent(new BigDecimal(16))) .addCharge(new Charge(new BigDecimal(0.5)).setReason("quick delivery charge").setTaxPercent(new BigDecimal(16)))
.addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16))) .addAllowance(new Allowance(new BigDecimal(0.2)).setReason("discount").setTaxPercent(new BigDecimal(16)))
.setDetailedDeliveryPeriod(sdf.parse("2020-01-01"),sdf.parse("2020-01-31")) .setDetailedDeliveryPeriod(sdf.parse("2020-01-01"),sdf.parse("2020-01-31"))
@@ -284,6 +287,10 @@ public class ZF2PushTest extends TestCase {
assertTrue(zi.getUTF8().contains("0009845")); assertTrue(zi.getUTF8().contains("0009845"));
assertTrue(zi.getUTF8().contains("0008734")); assertTrue(zi.getUTF8().contains("0008734"));
assertTrue(zi.getUTF8().contains("20200113")); // to contain item delivery periods
assertTrue(zi.getUTF8().contains("20200115")); // to contain item delivery periods
assertTrue(zi.getUTF8().contains("item level 1/1")); assertTrue(zi.getUTF8().contains("item level 1/1"));
assertTrue(zi.getUTF8().contains("DE4711")); // the VAT ID should be there... assertTrue(zi.getUTF8().contains("DE4711")); // the VAT ID should be there...
assertFalse(zi.getUTF8().contains("DE47110")); // but not the VAT ID of the shiptotradeparty assertFalse(zi.getUTF8().contains("DE47110")); // but not the VAT ID of the shiptotradeparty