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

ExtendedQuantityCode to use Codes which are not definded in default Q… #493

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ZUGFeRD/IncludedReferencedProduct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@ public class IncludedReferencedProduct
/// BT-X-20-1
/// </summary>
public QuantityCodes? UnitCode { get; set; }

/// <summary>
/// BT-X-20-1
/// </summary>
public ExtendedQuantityCode ExtendedUnitCode { get; set; }
}
}
4 changes: 2 additions & 2 deletions ZUGFeRD/InvoiceDescriptor22UBLWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@

Writer.WriteStartElement("cac", "TaxCategory");
Writer.WriteElementString("cbc", "ID", tradeAllowanceCharge.Tax.CategoryCode.ToString());
if (tradeAllowanceCharge.Tax.Percent != null)

Check warning on line 402 in ZUGFeRD/InvoiceDescriptor22UBLWriter.cs

View workflow job for this annotation

GitHub Actions / build

The result of the expression is always 'true' since a value of type 'decimal' is never equal to 'null' of type 'decimal?'

Check warning on line 402 in ZUGFeRD/InvoiceDescriptor22UBLWriter.cs

View workflow job for this annotation

GitHub Actions / build

The result of the expression is always 'true' since a value of type 'decimal' is never equal to 'null' of type 'decimal?'
{
Writer.WriteElementString("cbc", "Percent", _formatDecimal(tradeAllowanceCharge.Tax.Percent));
}
Expand All @@ -421,8 +421,8 @@
foreach (Tax tax in this.Descriptor.Taxes)
{
Writer.WriteStartElement("cac", "TaxSubtotal");
_writeOptionalAmount(Writer, "cbc", "TaxableAmount", tax.BasisAmount, forceCurrency: true);

Check warning on line 424 in ZUGFeRD/InvoiceDescriptor22UBLWriter.cs

View workflow job for this annotation

GitHub Actions / build

'Tax.BasisAmount' is obsolete: 'Please note that TaxAmount needs to be written manually beginning with version 17.0'

Check warning on line 424 in ZUGFeRD/InvoiceDescriptor22UBLWriter.cs

View workflow job for this annotation

GitHub Actions / build

'Tax.BasisAmount' is obsolete: 'Please note that TaxAmount needs to be written manually beginning with version 17.0'
_writeOptionalAmount(Writer, "cbc", "TaxAmount", tax.TaxAmount, forceCurrency: true);

Check warning on line 425 in ZUGFeRD/InvoiceDescriptor22UBLWriter.cs

View workflow job for this annotation

GitHub Actions / build

'Tax.TaxAmount' is obsolete: 'Please note that TaxAmount needs to be set manually beginning with version 17.0, automatic calculation will be removed'

Check warning on line 425 in ZUGFeRD/InvoiceDescriptor22UBLWriter.cs

View workflow job for this annotation

GitHub Actions / build

'Tax.TaxAmount' is obsolete: 'Please note that TaxAmount needs to be set manually beginning with version 17.0, automatic calculation will be removed'

Writer.WriteStartElement("cac", "TaxCategory");
Writer.WriteElementString("cbc", "ID", tax.CategoryCode.ToString());
Expand Down Expand Up @@ -483,7 +483,7 @@

//Writer.WriteElementString("cbc", "InvoicedQuantity", tradeLineItem.BilledQuantity.ToString());
Writer.WriteStartElement("cbc", "InvoicedQuantity");
Writer.WriteAttributeString("unitCode", tradeLineItem.UnitCode.EnumToString());
Writer.WriteAttributeString("unitCode", tradeLineItem.ExtendedUnitCode != null ? tradeLineItem.ExtendedUnitCode.ToString() : tradeLineItem.UnitCode.EnumToString());
Writer.WriteValue(_formatDecimal(tradeLineItem.BilledQuantity));
Writer.WriteEndElement();

Expand Down Expand Up @@ -541,7 +541,7 @@
if (tradeLineItem.UnitQuantity.HasValue)
{
Writer.WriteStartElement("cbc", "BaseQuantity"); // BT-149
Writer.WriteAttributeString("unitCode", tradeLineItem.UnitCode.EnumToString()); // BT-150
Writer.WriteAttributeString("unitCode", tradeLineItem.ExtendedUnitCode != null ? tradeLineItem.ExtendedUnitCode.ToString() : tradeLineItem.UnitCode.EnumToString()); // BT-150
Writer.WriteValue(_formatDecimal(tradeLineItem.UnitQuantity));
Writer.WriteEndElement();
}
Expand Down Expand Up @@ -892,7 +892,7 @@
type -= 1000;
}

if (type == InvoiceType.CorrectionOld)

Check warning on line 895 in ZUGFeRD/InvoiceDescriptor22UBLWriter.cs

View workflow job for this annotation

GitHub Actions / build

'InvoiceType.CorrectionOld' is obsolete: 'Use 'Correction' instead'
{
return (int)InvoiceType.Correction;
}
Expand Down
2 changes: 2 additions & 0 deletions ZUGFeRD/InvoiceDescriptor22UblReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ private static List<TradeLineItem> _parseTradeLineItem(XmlNode tradeLineItem, Xm
NetUnitPrice = XmlUtils.NodeAsDecimal(tradeLineItem, ".//cac:Price/cbc:PriceAmount", nsmgr, 0).Value,
GrossUnitPrice = 0, // TODO: Find value //GrossUnitPrice = XmlUtils.NodeAsDecimal(tradeLineItem, ".//ram:GrossPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value,
UnitCode = default(QuantityCodes).FromString(XmlUtils.NodeAsString(tradeLineItem, ".//cbc:InvoicedQuantity/@unitCode", nsmgr)),
ExtendedUnitCode = ExtendedQuantityCodeManager.GetCode(XmlUtils.NodeAsString(tradeLineItem, ".//cbc:InvoicedQuantity/@unitCode", nsmgr)),
BillingPeriodStart = XmlUtils.NodeAsDateTime(tradeLineItem, ".//cac:InvoicePeriod/cbc:StartDate", nsmgr),
BillingPeriodEnd = XmlUtils.NodeAsDateTime(tradeLineItem, ".//cac:InvoicePeriod/cbc:EndDate", nsmgr),
};
Expand Down Expand Up @@ -595,6 +596,7 @@ private static List<TradeLineItem> _parseTradeLineItem(XmlNode tradeLineItem, Xm
{
// UnitCode alternativ aus BilledQuantity extrahieren
item.UnitCode = default(QuantityCodes).FromString(XmlUtils.NodeAsString(tradeLineItem, ".//cbc:InvoicedQuantity/@unitCode", nsmgr));
item.ExtendedUnitCode = ExtendedQuantityCodeManager.GetCode(XmlUtils.NodeAsString(tradeLineItem, ".//cbc:InvoicedQuantity/@unitCode", nsmgr));
}

// TODO: Find value //if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID", nsmgr) != null)
Expand Down
12 changes: 8 additions & 4 deletions ZUGFeRD/InvoiceDescriptor23CIIReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,10 @@ private static TradeLineItem _parseTradeLineItem(XmlNode tradeLineItem, XmlNames
NetUnitPrice = XmlUtils.NodeAsDecimal(tradeLineItem, ".//ram:NetPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value,
GrossUnitPrice = XmlUtils.NodeAsDecimal(tradeLineItem, ".//ram:GrossPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value,
UnitCode = default(QuantityCodes).FromString(XmlUtils.NodeAsString(tradeLineItem, ".//ram:BilledQuantity/@unitCode", nsmgr)),
ExtendedUnitCode = ExtendedQuantityCodeManager.GetCode(XmlUtils.NodeAsString(tradeLineItem, ".//ram:BilledQuantity/@unitCode", nsmgr)),
BillingPeriodStart = XmlUtils.NodeAsDateTime(tradeLineItem, ".//ram:BillingSpecifiedPeriod/ram:StartDateTime/udt:DateTimeString", nsmgr),
BillingPeriodEnd = XmlUtils.NodeAsDateTime(tradeLineItem, ".//ram:BillingSpecifiedPeriod/ram:EndDateTime/udt:DateTimeString", nsmgr),
};

};

if (!String.IsNullOrWhiteSpace(_parentLineId))
{
Expand All @@ -512,14 +512,17 @@ private static TradeLineItem _parseTradeLineItem(XmlNode tradeLineItem, XmlNames

foreach (XmlNode includedItem in tradeLineItem.SelectNodes(".//ram:SpecifiedTradeProduct/ram:IncludedReferencedProduct", nsmgr))
{
var unitCode = XmlUtils.NodeAsString(includedItem, ".//ram:UnitQuantity/@unitCode", nsmgr, null);
var unitCode = XmlUtils.NodeAsString(includedItem, ".//ram:UnitQuantity/@unitCode", nsmgr, null);

item.IncludedReferencedProducts.Add(new IncludedReferencedProduct()
{
Name = XmlUtils.NodeAsString(includedItem, ".//ram:Name", nsmgr),
UnitQuantity = XmlUtils.NodeAsDecimal(includedItem, ".//ram:UnitQuantity", nsmgr, null),
UnitCode = unitCode != null ? (QuantityCodes?)default(QuantityCodes).FromString(unitCode) : null
UnitCode = unitCode != null ? (QuantityCodes?)default(QuantityCodes).FromString(unitCode) : null,
ExtendedUnitCode = unitCode != null ? ExtendedQuantityCodeManager.GetCode(unitCode) : null,
});


}

if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument", nsmgr) != null)
Expand Down Expand Up @@ -623,6 +626,7 @@ private static TradeLineItem _parseTradeLineItem(XmlNode tradeLineItem, XmlNames
{
// UnitCode alternativ aus BilledQuantity extrahieren
item.UnitCode = default(QuantityCodes).FromString(XmlUtils.NodeAsString(tradeLineItem, ".//ram:BilledQuantity/@unitCode", nsmgr));
item.ExtendedUnitCode = ExtendedQuantityCodeManager.GetCode(XmlUtils.NodeAsString(tradeLineItem, ".//ram:BilledQuantity/@unitCode", nsmgr));
}

if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID", nsmgr) != null)
Expand Down
10 changes: 5 additions & 5 deletions ZUGFeRD/InvoiceDescriptor23CIIWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,9 @@
Writer.WriteStartElement("ram", "IncludedReferencedProduct");
Writer.WriteOptionalElementString("ram", "Name", includedItem.Name);

if(includedItem.UnitQuantity.HasValue)
if (includedItem.UnitQuantity.HasValue)
{
_writeElementWithAttributeWithPrefix(Writer, "ram", "UnitQuantity", "unitCode", includedItem.UnitCode.Value.EnumToString(), _formatDecimal(includedItem.UnitQuantity, 4));
_writeElementWithAttributeWithPrefix(Writer, "ram", "UnitQuantity", "unitCode", includedItem.ExtendedUnitCode != null ? includedItem.ExtendedUnitCode.ToString() : includedItem.UnitCode.Value.EnumToString(), _formatDecimal(includedItem.UnitQuantity, 4));
}
Writer.WriteEndElement(); // !ram:IncludedReferencedProduct
}
Expand Down Expand Up @@ -311,7 +311,7 @@
_writeOptionalAmount(Writer, "ram", "ChargeAmount", tradeLineItem.GrossUnitPrice, 2); // BT-148
if (tradeLineItem.UnitQuantity.HasValue)
{
_writeElementWithAttributeWithPrefix(Writer, "ram", "BasisQuantity", "unitCode", tradeLineItem.UnitCode.EnumToString(), _formatDecimal(tradeLineItem.UnitQuantity.Value, 4));
_writeElementWithAttributeWithPrefix(Writer, "ram", "BasisQuantity", "unitCode", tradeLineItem.ExtendedUnitCode != null ? tradeLineItem.ExtendedUnitCode.ToString() : tradeLineItem.UnitCode.EnumToString(), _formatDecimal(tradeLineItem.UnitQuantity.Value, 4));
}

foreach (TradeAllowanceCharge tradeAllowanceCharge in tradeLineItem.GetTradeAllowanceCharges()) // BT-147
Expand Down Expand Up @@ -364,7 +364,7 @@

if (tradeLineItem.UnitQuantity.HasValue)
{
_writeElementWithAttributeWithPrefix(Writer, "ram", "BasisQuantity", "unitCode", tradeLineItem.UnitCode.EnumToString(), _formatDecimal(tradeLineItem.UnitQuantity.Value, 4));
_writeElementWithAttributeWithPrefix(Writer, "ram", "BasisQuantity", "unitCode", tradeLineItem.ExtendedUnitCode != null ? tradeLineItem.ExtendedUnitCode.ToString() : tradeLineItem.UnitCode.EnumToString(), _formatDecimal(tradeLineItem.UnitQuantity.Value, 4));
}
Writer.WriteEndElement(); // ram:NetPriceProductTradePrice(Basic|Comfort|Extended|XRechnung)
#endregion // !NetPriceProductTradePrice(Basic|Comfort|Extended|XRechnung)
Expand All @@ -378,7 +378,7 @@

#region SpecifiedLineTradeDelivery (Basic, Comfort, Extended)
Writer.WriteStartElement("ram", "SpecifiedLineTradeDelivery", Profile.Basic | Profile.Comfort | Profile.Extended | Profile.XRechnung1 | Profile.XRechnung);
_writeElementWithAttributeWithPrefix(Writer, "ram", "BilledQuantity", "unitCode", tradeLineItem.UnitCode.EnumToString(), _formatDecimal(tradeLineItem.BilledQuantity, 4));
_writeElementWithAttributeWithPrefix(Writer, "ram", "BilledQuantity", "unitCode", tradeLineItem.ExtendedUnitCode != null ? tradeLineItem.ExtendedUnitCode.ToString() : tradeLineItem.UnitCode.EnumToString(), _formatDecimal(tradeLineItem.BilledQuantity, 4));

if (tradeLineItem.ShipTo != null)
{
Expand Down Expand Up @@ -1317,13 +1317,13 @@
writer.WriteStartElement("ram", "ApplicableTradeTax");

writer.WriteStartElement("ram", "CalculatedAmount");
writer.WriteValue(_formatDecimal(tax.TaxAmount));

Check warning on line 1320 in ZUGFeRD/InvoiceDescriptor23CIIWriter.cs

View workflow job for this annotation

GitHub Actions / build

'Tax.TaxAmount' is obsolete: 'Please note that TaxAmount needs to be set manually beginning with version 17.0, automatic calculation will be removed'
writer.WriteEndElement(); // !CalculatedAmount

writer.WriteElementString("ram", "TypeCode", tax.TypeCode.EnumToString());
writer.WriteOptionalElementString("ram", "ExemptionReason", tax.ExemptionReason);
writer.WriteStartElement("ram", "BasisAmount");
writer.WriteValue(_formatDecimal(tax.BasisAmount));

Check warning on line 1326 in ZUGFeRD/InvoiceDescriptor23CIIWriter.cs

View workflow job for this annotation

GitHub Actions / build

'Tax.BasisAmount' is obsolete: 'Please note that TaxAmount needs to be written manually beginning with version 17.0'
writer.WriteEndElement(); // !BasisAmount

if (tax.AllowanceChargeBasisAmount.HasValue && (tax.AllowanceChargeBasisAmount.Value != 0 && (Descriptor.Profile != Profile.XRechnung1 && Descriptor.Profile != Profile.XRechnung)))
Expand Down
99 changes: 99 additions & 0 deletions ZUGFeRD/QuantityCodes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

namespace s2industries.ZUGFeRD
{

/// <summary>
/// ISO Quantity Codes
///
Expand Down Expand Up @@ -457,4 +458,102 @@ public static string EnumToString(this QuantityCodes c)
return c.ToString("g");
} // !ToString()
}

#region Custom

/// <summary>
/// Extended Quantity Code
/// </summary>
public class ExtendedQuantityCode
{
/// <summary>
/// Code from the standard list
/// </summary>
public QuantityCodes? Code { get; }

/// <summary>
/// Custom Code
/// </summary>
public string CustomCode { get; }

/// <summary>
/// Constructor for standard codes
/// </summary>
/// <param name="code"></param>
public ExtendedQuantityCode(QuantityCodes code)
{
Code = code;
CustomCode = null;
}

/// <summary>
/// Constructor for custom codes
/// </summary>
/// <param name="customCode"></param>
public ExtendedQuantityCode(string customCode)
{
Code = null;
CustomCode = customCode;
}

/// <summary>
/// Get the string representation of the code
/// </summary>
/// <returns></returns>
public override string ToString()
{
return Code?.ToString() ?? CustomCode;
}
}

/// <summary>
/// Manager for custom quantity codes
/// </summary>
public static class ExtendedQuantityCodeManager
{
private static readonly Dictionary<string, ExtendedQuantityCode> _codes = new Dictionary<string, ExtendedQuantityCode>();

static ExtendedQuantityCodeManager()
{
foreach (QuantityCodes code in Enum.GetValues(typeof(QuantityCodes)))
{
_codes[code.ToString()] = new ExtendedQuantityCode(code);
}
}

/// <summary>
/// Add a custom code
/// </summary>
/// <param name="customCode"></param>
public static void AddCustomCode(string customCode)
{
_codes[customCode] = new ExtendedQuantityCode(customCode);
}

/// <summary>
/// Get the code for a given string
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public static ExtendedQuantityCode GetCode(string code)
{
if (_codes.TryGetValue(code, out var result))
{
return result;
}

return new ExtendedQuantityCode(QuantityCodes.Unknown);
}

/// <summary>
/// Get all codes
/// </summary>
/// <returns></returns>
public static IEnumerable<ExtendedQuantityCode> GetAllCodes()
{
return _codes.Values;
}
}

#endregion Custom
}
5 changes: 5 additions & 0 deletions ZUGFeRD/TradeLineItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ public class TradeLineItem
/// </summary>
public QuantityCodes UnitCode { get; set; }

/// <summary>
/// BT-130
/// </summary>
public ExtendedQuantityCode ExtendedUnitCode { get; set; }

/// <summary>
/// Identifier of the invoice line item
///
Expand Down
Loading