Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SpecifiedTradeAllowanceCharges on TradeLineItems for UBL #712

Merged
merged 7 commits into from
Apr 7, 2025
64 changes: 56 additions & 8 deletions ZUGFeRD/InvoiceDescriptor22UBLWriter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
Expand All @@ -21,7 +21,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;

namespace s2industries.ZUGFeRD
{
Expand All @@ -38,7 +37,7 @@ public override void Save(InvoiceDescriptor descriptor, Stream stream, ZUGFeRDFo
{
throw new IllegalStreamException("Cannot write to stream");
}


long streamPosition = stream.Position;

Expand Down Expand Up @@ -66,13 +65,13 @@ public override void Save(InvoiceDescriptor descriptor, Stream stream, ZUGFeRDFo
{ "ext", "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" },
{ "xs", "http://www.w3.org/2001/XMLSchema" }
};

if (isInvoice)
{
{
namespaces.Add("ubl", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2");
}
else
{
{
namespaces.Add("ubl", "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2");
}
this.Writer.SetNamespaces(namespaces);
Expand Down Expand Up @@ -624,7 +623,7 @@ private void _WriteTradeLineItem(TradeLineItem tradeLineItem, bool isInvoice = t
Writer.WriteAttributeString("unitCode", tradeLineItem.UnitCode.EnumToString());
Writer.WriteValue(_formatDecimal(tradeLineItem.BilledQuantity));
Writer.WriteEndElement(); // !InvoicedQuantity || CreditedQuantity

Writer.WriteStartElement("cbc", "LineExtensionAmount");
Writer.WriteAttributeString("currencyID", this.Descriptor.Currency.EnumToString());
Writer.WriteValue(_formatDecimal(tradeLineItem.LineTotalAmount));
Expand Down Expand Up @@ -654,6 +653,16 @@ private void _WriteTradeLineItem(TradeLineItem tradeLineItem, bool isInvoice = t
}
}

foreach (var specifiedTradeAllowanceCharge in tradeLineItem.GetSpecifiedTradeAllowances())
{
_WriteItemLevelSpecifiedTradeAllowanceCharge(specifiedTradeAllowanceCharge);
}

foreach (var specifiedTradeAllowanceCharge in tradeLineItem.GetSpecifiedTradeCharges())
{
_WriteItemLevelSpecifiedTradeAllowanceCharge(specifiedTradeAllowanceCharge);
}

Writer.WriteStartElement("cac", "Item");

Writer.WriteOptionalElementString("cbc", "Description", tradeLineItem.Description);
Expand Down Expand Up @@ -754,6 +763,45 @@ private void _WriteTradeLineItem(TradeLineItem tradeLineItem, bool isInvoice = t
Writer.WriteEndElement(); //!InvoiceLine
}

private void _WriteItemLevelSpecifiedTradeAllowanceCharge(AbstractTradeAllowanceCharge specifiedTradeAllowanceCharge)
{
Writer.WriteStartElement("cac", "AllowanceCharge");
Writer.WriteElementString("cbc", "ChargeIndicator",
specifiedTradeAllowanceCharge.ChargeIndicator ? "true" : "false"); // BG-28-0
switch (specifiedTradeAllowanceCharge)
{
case TradeAllowance allowance when allowance.ReasonCode != null:
Writer.WriteOptionalElementString("ram", "ReasonCode", allowance.ReasonCode.EnumToString()); // BT-140
break;
case TradeCharge charge when charge.ReasonCode != null:
Writer.WriteOptionalElementString("ram", "ReasonCode", charge.ReasonCode.EnumToString()); // BT-145
break;
}

Writer.WriteOptionalElementString("cbc", "AllowanceChargeReason",
specifiedTradeAllowanceCharge.Reason); // BT-139, BT-144

if (specifiedTradeAllowanceCharge.ChargePercentage.HasValue)
{
Writer.WriteOptionalElementString("cbc", "MultiplierFactorNumeric",
_formatDecimal(specifiedTradeAllowanceCharge.ChargePercentage));
}

Writer.WriteStartElement("cbc", "Amount");
Writer.WriteAttributeString("currencyID", this.Descriptor.Currency.EnumToString());
Writer.WriteValue(_formatDecimal(specifiedTradeAllowanceCharge.ActualAmount));
Writer.WriteEndElement(); // !Amount
if (specifiedTradeAllowanceCharge.BasisAmount.HasValue)
{
Writer.WriteStartElement("cbc", "BaseAmount"); // BT-137, BT-142
Writer.WriteAttributeString("currencyID", this.Descriptor.Currency.EnumToString());
Writer.WriteValue(_formatDecimal(specifiedTradeAllowanceCharge.BasisAmount));
Writer.WriteEndElement(); // !BaseAmount
}

Writer.WriteEndElement(); // !AllowanceCharge
}


private void _WriteCommodityClassification(ProfileAwareXmlTextWriter writer, List<DesignatedProductClassification> designatedProductClassifications)
{
Expand All @@ -771,7 +819,7 @@ private void _WriteCommodityClassification(ProfileAwareXmlTextWriter writer, Lis
continue;
}

writer.WriteStartElement("cbc", "ItemClassificationCode"); // BT-158
writer.WriteStartElement("cbc", "ItemClassificationCode"); // BT-158
Writer.WriteAttributeString("listID", classification.ListID.EnumToString()); // BT-158-1

if (!String.IsNullOrWhiteSpace(classification.ListVersionID))
Expand Down
Loading