Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
tipa committed Nov 6, 2024
2 parents 9af13a5 + f36c837 commit a14cad0
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 53 deletions.
86 changes: 84 additions & 2 deletions ZUGFeRD-Test/XRechnungUBLTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,10 @@ public void TestInvoiceWithAttachment()
}
} // !TestInvoiceWithAttachment()



[TestMethod]
public void TestActualDeliveryDate()
public void TestActualDeliveryDateWithoutDeliveryAddress()
{
DateTime timestamp = new DateTime(2024,08,11);
InvoiceDescriptor desc = this.InvoiceProvider.CreateInvoice();
Expand All @@ -200,7 +202,87 @@ public void TestActualDeliveryDate()

// test the ActualDeliveryDate
Assert.AreEqual(timestamp, loadedInvoice.ActualDeliveryDate);
} // !TestActualDeliveryDate()
Assert.IsNull(loadedInvoice.ShipTo);
} // !TestActualDeliveryDateWithoutDeliveryAddress()



[TestMethod]
public void TestActualDeliveryDateWithDeliveryAddress()
{
DateTime timestamp = new DateTime(2024, 08, 11);
InvoiceDescriptor desc = this.InvoiceProvider.CreateInvoice();
MemoryStream ms = new MemoryStream();

desc.ActualDeliveryDate = timestamp;

string shipToID = "1234";
string shipToName = "Test ShipTo Name";
CountryCodes shipToCountry = CountryCodes.DE;

desc.ShipTo = new Party()
{
ID = new GlobalID()
{
ID = shipToID
},
Name = shipToName,
Country = shipToCountry
};

desc.Save(ms, ZUGFeRDVersion.Version23, Profile.XRechnung, ZUGFeRDFormats.UBL);
ms.Seek(0, SeekOrigin.Begin);

InvoiceDescriptor loadedInvoice = InvoiceDescriptor.Load(ms);

// test the ActualDeliveryDate
Assert.AreEqual(timestamp, loadedInvoice.ActualDeliveryDate);
Assert.IsNotNull(loadedInvoice.ShipTo);
Assert.IsNotNull(loadedInvoice.ShipTo.ID);
Assert.AreEqual(loadedInvoice.ShipTo.ID.ID, shipToID);
Assert.AreEqual(loadedInvoice.ShipTo.Name, shipToName);
Assert.AreEqual(loadedInvoice.ShipTo.Country, shipToCountry);
} // !TestActualDeliveryDateWithDeliveryAddress()



[TestMethod]
public void TestActualDeliveryAddressWithoutDeliveryDate()
{
InvoiceDescriptor desc = this.InvoiceProvider.CreateInvoice();
MemoryStream ms = new MemoryStream();

// ActualDeliveryDate is set by the InvoiceProvider, we are resetting it to the default value
desc.ActualDeliveryDate = null;

string shipToID = "1234";
string shipToName = "Test ShipTo Name";
CountryCodes shipToCountry = CountryCodes.DE;

desc.ShipTo = new Party()
{
ID = new GlobalID()
{
ID = shipToID
},
Name = shipToName,
Country = shipToCountry
};

desc.Save(ms, ZUGFeRDVersion.Version23, Profile.XRechnung, ZUGFeRDFormats.UBL);
ms.Seek(0, SeekOrigin.Begin);

InvoiceDescriptor loadedInvoice = InvoiceDescriptor.Load(ms);

// test the ActualDeliveryDate
Assert.IsNull(loadedInvoice.ActualDeliveryDate);
Assert.IsNotNull(loadedInvoice.ShipTo);
Assert.IsNotNull(loadedInvoice.ShipTo.ID);
Assert.AreEqual(loadedInvoice.ShipTo.ID.ID, shipToID);
Assert.AreEqual(loadedInvoice.ShipTo.Name, shipToName);
Assert.AreEqual(loadedInvoice.ShipTo.Country, shipToCountry);
} // !TestActualDeliveryAddressWithoutDeliveryDate()


[TestMethod]
public void TestTaxTypes()
Expand Down
15 changes: 15 additions & 0 deletions ZUGFeRD/InvoiceDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ public class InvoiceDescriptor

/// <summary>
/// Information about the buyer
/// BG-7
/// </summary>
public Party Buyer { get; set; }

Expand All @@ -128,10 +129,24 @@ public class InvoiceDescriptor
/// </summary>
public Contact BuyerContact { get; set; }
public List<TaxRegistration> BuyerTaxRegistration { get; set; } = new List<TaxRegistration>();

/// <summary>
/// Buyer electronic address
/// BT-49
/// </summary>
public ElectronicAddress BuyerElectronicAddress { get; set; }

/// <summary>
/// BG-4
/// </summary>
public Party Seller { get; set; }
public Contact SellerContact { get; set; }
public List<TaxRegistration> SellerTaxRegistration { get; set; } = new List<TaxRegistration>();

/// <summary>
/// Seller electronic address
/// BT-34
/// </summary>
public ElectronicAddress SellerElectronicAddress { get; set; }

/// <summary>
Expand Down
103 changes: 57 additions & 46 deletions ZUGFeRD/InvoiceDescriptor22UBLWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,66 @@ public override void Save(InvoiceDescriptor descriptor, Stream stream, ZUGFeRDFo


#region SellerTradeParty
//AccountingSupplierParty

// AccountingSupplierParty = PartyTypes.SellerTradeParty
_writeOptionalParty(Writer, PartyTypes.SellerTradeParty, this.Descriptor.Seller, this.Descriptor.SellerContact, this.Descriptor.SellerElectronicAddress, this.Descriptor.SellerTaxRegistration);
#endregion

#region BuyerTradeParty
//AccountingCustomerParty
//AccountingCustomerParty = PartyTypes.BuyerTradeParty
_writeOptionalParty(Writer, PartyTypes.BuyerTradeParty, this.Descriptor.Buyer, this.Descriptor.BuyerContact, this.Descriptor.BuyerElectronicAddress, this.Descriptor.BuyerTaxRegistration);
#endregion



// Deliery = ShipToTradeParty
if ((this.Descriptor.ShipTo != null) || (this.Descriptor.ActualDeliveryDate.HasValue))
{
Writer.WriteStartElement("cac", "Delivery");

if (this.Descriptor.ActualDeliveryDate.HasValue)
{
Writer.WriteStartElement("cbc", "ActualDeliveryDate");
Writer.WriteValue(_formatDate(this.Descriptor.ActualDeliveryDate.Value, false, true));
Writer.WriteEndElement(); // !ActualDeliveryDate
}

if (this.Descriptor.ShipTo != null)
{
Writer.WriteStartElement("cac", "DeliveryLocation");

if (this.Descriptor.ShipTo.ID != null) // despite this is a mandatory field, the component should not throw an exception if this is not the case
{
Writer.WriteOptionalElementString("cbc", "ID", this.Descriptor.ShipTo.ID.ID);
}
Writer.WriteStartElement("cac", "Address");
Writer.WriteOptionalElementString("cbc", "StreetName", this.Descriptor.ShipTo.Street);
Writer.WriteOptionalElementString("cbc", "AdditionalStreetName", this.Descriptor.ShipTo.AddressLine3);
Writer.WriteOptionalElementString("cbc", "CityName", this.Descriptor.ShipTo.City);
Writer.WriteOptionalElementString("cbc", "PostalZone", this.Descriptor.ShipTo.Postcode);
Writer.WriteOptionalElementString("cbc", "CountrySubentity", this.Descriptor.ShipTo.CountrySubdivisionName);
Writer.WriteStartElement("cac", "Country");
if (this.Descriptor.ShipTo.Country != CountryCodes.Unknown)
{
Writer.WriteElementString("cbc", "IdentificationCode", this.Descriptor.ShipTo.Country.ToString());
}
Writer.WriteEndElement(); //!Country
Writer.WriteEndElement(); // !Address
Writer.WriteEndElement(); // !DeliveryLocation

if (!string.IsNullOrWhiteSpace(this.Descriptor.ShipTo.Name))
{
Writer.WriteStartElement("cac", "DeliveryParty");
Writer.WriteStartElement("cac", "PartyName");
Writer.WriteStartElement("cbc", "Name");
Writer.WriteValue(this.Descriptor.ShipTo.Name);
Writer.WriteEndElement(); // !Name
Writer.WriteEndElement(); // !PartyName
Writer.WriteEndElement(); // !DeliveryParty
}
}
}


#region AllowanceCharge
foreach (TradeAllowanceCharge tradeAllowanceCharge in descriptor.GetTradeAllowanceCharges())
{
Expand Down Expand Up @@ -243,16 +294,7 @@ public override void Save(InvoiceDescriptor descriptor, Stream stream, ZUGFeRDFo

Writer.WriteEndElement(); // !AllowanceCharge()
}
#endregion

if (this.Descriptor.ActualDeliveryDate.HasValue)
{
Writer.WriteStartElement("cac", "Delivery");
Writer.WriteStartElement("cbc", "ActualDeliveryDate");
Writer.WriteValue(_formatDate(this.Descriptor.ActualDeliveryDate.Value, false, true));
Writer.WriteEndElement(); // !ActualDeliveryDate
Writer.WriteEndElement(); // !Delivery
}
#endregion

// PaymentMeans
if (this.Descriptor.PaymentMeans != null)
Expand Down Expand Up @@ -546,39 +588,8 @@ private void _writeOptionalParty(ProfileAwareXmlTextWriter writer, PartyTypes pa
break;
case PartyTypes.ShipFromTradeParty:
return;
//case PartyTypes.ShipToTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.UltimateShipToTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.ShipFromTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.InvoiceeTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.PayeeTradeParty:
// if (this.Descriptor.Profile == Profile.Minimum) { return; } // party is written for all profiles but minimum
// break;
//case PartyTypes.SalesAgentTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.BuyerTaxRepresentativeTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.ProductEndUserTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.BuyerAgentTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.InvoicerTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
//case PartyTypes.PayerTradeParty:
// if ((this.Descriptor.Profile != Profile.Extended) && (this.Descriptor.Profile != Profile.XRechnung1) && (this.Descriptor.Profile != Profile.XRechnung)) { return; } // extended, XRechnung1, XRechnung profile only
// break;
case PartyTypes.ShipToTradeParty: // ship to trade party/ cac:Delivery has very minimized information, thus generic _writeOptionalParty() cannot be used
return;
default:
return;
}
Expand Down
10 changes: 5 additions & 5 deletions ZUGFeRD/InvoiceDescriptor23CIIWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1414,7 +1414,7 @@ private void _writeOptionalLegalOrganization(ProfileAwareXmlTextWriter writer, s
} // !_writeOptionalLegalOrganization()


private void _writeOptionalParty(ProfileAwareXmlTextWriter writer, PartyTypes partyType, Party party, Profile profile, Contact contact = null, ElectronicAddress ElectronicAddress = null, List<TaxRegistration> taxRegistrations = null)
private void _writeOptionalParty(ProfileAwareXmlTextWriter writer, PartyTypes partyType, Party party, Profile profile, Contact contact = null, ElectronicAddress electronicAddress = null, List<TaxRegistration> taxRegistrations = null)
{
if (party == null)
{
Expand Down Expand Up @@ -1512,14 +1512,14 @@ private void _writeOptionalParty(ProfileAwareXmlTextWriter writer, PartyTypes pa
writer.WriteEndElement(); // !PostalTradeAddress
}

if (ElectronicAddress != null)
if (electronicAddress != null)
{
if (!String.IsNullOrWhiteSpace(ElectronicAddress.Address))
if (!String.IsNullOrWhiteSpace(electronicAddress.Address))
{
writer.WriteStartElement("ram", "URIUniversalCommunication");
writer.WriteStartElement("ram", "URIID");
writer.WriteAttributeString("schemeID", ElectronicAddress.ElectronicAddressSchemeID.EnumToString());
writer.WriteValue(ElectronicAddress.Address);
writer.WriteAttributeString("schemeID", electronicAddress.ElectronicAddressSchemeID.EnumToString());
writer.WriteValue(electronicAddress.Address);
writer.WriteEndElement();
writer.WriteEndElement();
}
Expand Down

0 comments on commit a14cad0

Please sign in to comment.