Skip to content

Commit

Permalink
Merge branch 'master' into 23ciiwriter-notes
Browse files Browse the repository at this point in the history
  • Loading branch information
tobitege committed Jan 11, 2025
2 parents 823044a + f769f7d commit ad7f083
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 65 deletions.
12 changes: 7 additions & 5 deletions ZUGFeRD.Test/XRechnungUBLTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
Expand Down Expand Up @@ -261,13 +261,14 @@ public void TestAllowanceChargeOnDocumentLevel()
CurrencyCodes currency = CurrencyCodes.EUR;
decimal actualAmount = 12.34m;
string reason = "Gutschrift";
AllowanceReasonCodes reasonCode = AllowanceReasonCodes.Packaging;
TaxTypes taxTypeCode = TaxTypes.VAT;
TaxCategoryCodes taxCategoryCode = TaxCategoryCodes.AA;
decimal taxPercent = 19.0m;

desc.AddTradeAllowanceCharge(isDiscount, basisAmount, currency, actualAmount, reason, taxTypeCode, taxCategoryCode, taxPercent);
desc.AddTradeAllowanceCharge(isDiscount, basisAmount, currency, actualAmount, reason, taxTypeCode, taxCategoryCode, taxPercent, reasonCode);

desc.TradeLineItems[0].AddTradeAllowanceCharge(true, CurrencyCodes.EUR, 100, 10, "test");
desc.TradeLineItems[0].AddTradeAllowanceCharge(true, CurrencyCodes.EUR, 100, 10, "test", reasonCode);

TradeAllowanceCharge? testAllowanceCharge = desc.GetTradeAllowanceCharges().FirstOrDefault();

Expand All @@ -286,6 +287,7 @@ public void TestAllowanceChargeOnDocumentLevel()
Assert.AreEqual(loadedAllowanceCharge.Currency, currency, message: "currency");
Assert.AreEqual(loadedAllowanceCharge.Amount, actualAmount, message: "actualAmount");
Assert.AreEqual(loadedAllowanceCharge.Reason, reason, message: "reason");
Assert.AreEqual(loadedAllowanceCharge.ReasonCode, reasonCode, message: "reasonCode");
Assert.AreEqual(loadedAllowanceCharge.Tax.TypeCode, taxTypeCode, message: "taxTypeCode");
Assert.AreEqual(loadedAllowanceCharge.Tax.CategoryCode, taxCategoryCode, message: "taxCategoryCode");
Assert.AreEqual(loadedAllowanceCharge.Tax.Percent, taxPercent, message: "taxPercent");
Expand Down Expand Up @@ -1202,7 +1204,7 @@ public void TestDecimals()

Assert.IsTrue(invoiceAsString.Contains($">{Math.Round(duePayableAmount, 2, MidpointRounding.AwayFromZero).ToString("F2", CultureInfo.InvariantCulture)}<"));
Assert.IsFalse(invoiceAsString.Contains($">{Math.Round(duePayableAmount, 4, MidpointRounding.AwayFromZero).ToString("F4", CultureInfo.InvariantCulture)}<"));
Assert.AreEqual(desc.DuePayableAmount, Math.Round(duePayableAmount, 2, MidpointRounding.AwayFromZero));
Assert.AreEqual(desc.DuePayableAmount, Math.Round(duePayableAmount, 2, MidpointRounding.AwayFromZero));
} // !TestDecimals()
}
}
4 changes: 2 additions & 2 deletions ZUGFeRD.Test/ZUGFeRD20Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ public void TestWriteAndReadExtended()
desc.BillingPeriodStart = timestamp;
desc.BillingPeriodEnd = timestamp.AddDays(14);

desc.AddTradeAllowanceCharge(false, 5m, CurrencyCodes.EUR, 15m, "Reason for charge", TaxTypes.AAB, TaxCategoryCodes.AB, 19m);
desc.AddTradeAllowanceCharge(false, 5m, CurrencyCodes.EUR, 15m, "Reason for charge", TaxTypes.AAB, TaxCategoryCodes.AB, 19m, AllowanceReasonCodes.Packaging);
desc.AddLogisticsServiceCharge(10m, "Logistics service charge", TaxTypes.AAC, TaxCategoryCodes.AC, 7m);

desc.GetTradePaymentTerms().FirstOrDefault().DueDate = timestamp.AddDays(14);
Expand Down Expand Up @@ -596,7 +596,7 @@ public void TestWriteAndReadExtended()
lineItem.BillingPeriodEnd = timestamp.AddDays(10);

lineItem.AddReceivableSpecifiedTradeAccountingAccount("987654");
lineItem.AddTradeAllowanceCharge(false, CurrencyCodes.EUR, 10m, 50m, "Reason: UnitTest");
lineItem.AddTradeAllowanceCharge(false, CurrencyCodes.EUR, 10m, 50m, "Reason: UnitTest", AllowanceReasonCodes.Packaging);


MemoryStream ms = new MemoryStream();
Expand Down
8 changes: 4 additions & 4 deletions ZUGFeRD.Test/ZUGFeRD22Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1834,7 +1834,7 @@ public void TestWriteAndReadExtended()
desc.BillingPeriodStart = timestamp;
desc.BillingPeriodEnd = timestamp.AddDays(14);

desc.AddTradeAllowanceCharge(false, 5m, CurrencyCodes.EUR, 15m, "Reason for charge", TaxTypes.AAB, TaxCategoryCodes.AB, 19m);
desc.AddTradeAllowanceCharge(false, 5m, CurrencyCodes.EUR, 15m, "Reason for charge", TaxTypes.AAB, TaxCategoryCodes.AB, 19m, AllowanceReasonCodes.Packaging);
desc.AddLogisticsServiceCharge(10m, "Logistics service charge", TaxTypes.AAC, TaxCategoryCodes.AC, 7m);

desc.GetTradePaymentTerms().FirstOrDefault().DueDate = timestamp.AddDays(14);
Expand Down Expand Up @@ -1866,7 +1866,7 @@ public void TestWriteAndReadExtended()
lineItem.BillingPeriodEnd = timestamp.AddDays(10);

lineItem.AddReceivableSpecifiedTradeAccountingAccount("987654");
lineItem.AddTradeAllowanceCharge(false, CurrencyCodes.EUR, 10m, 50m, "Reason: UnitTest");
lineItem.AddTradeAllowanceCharge(false, CurrencyCodes.EUR, 10m, 50m, "Reason: UnitTest", AllowanceReasonCodes.Packaging);


MemoryStream ms = new MemoryStream();
Expand Down Expand Up @@ -2273,7 +2273,7 @@ public void TestTradeAllowanceChargeWithoutExplicitPercentage()
InvoiceDescriptor invoice = _InvoiceProvider.CreateInvoice();

// fake values, does not matter for our test case
invoice.AddTradeAllowanceCharge(true, 100, CurrencyCodes.EUR, 10, String.Empty, TaxTypes.VAT, TaxCategoryCodes.S, 19);
invoice.AddTradeAllowanceCharge(true, 100, CurrencyCodes.EUR, 10, String.Empty, TaxTypes.VAT, TaxCategoryCodes.S, 19, AllowanceReasonCodes.Packaging);

MemoryStream ms = new MemoryStream();
invoice.Save(ms, ZUGFeRDVersion.Version23, Profile.Extended);
Expand All @@ -2295,7 +2295,7 @@ public void TestTradeAllowanceChargeWithExplicitPercentage()
InvoiceDescriptor invoice = _InvoiceProvider.CreateInvoice();

// fake values, does not matter for our test case
invoice.AddTradeAllowanceCharge(true, 100, CurrencyCodes.EUR, 10, 12, String.Empty, TaxTypes.VAT, TaxCategoryCodes.S, 19);
invoice.AddTradeAllowanceCharge(true, 100, CurrencyCodes.EUR, 10, 12, String.Empty, TaxTypes.VAT, TaxCategoryCodes.S, 19, AllowanceReasonCodes.Packaging);

MemoryStream ms = new MemoryStream();
invoice.Save(ms, ZUGFeRDVersion.Version23, Profile.Extended);
Expand Down
125 changes: 125 additions & 0 deletions ZUGFeRD/AllowanceReasonCodes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* 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
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

using System.ComponentModel;


namespace s2industries.ZUGFeRD
{
/// <summary>
/// Reason codes according to UN/EDIFACT UNTDID 7161 code list
/// </summary>
public enum AllowanceReasonCodes
{
/// <summary>
/// Unknown
/// </summary>
Unknown = 0,

/// <summary>
/// Advertising
/// </summary>
[Description("AA")]
Advertising = 1,

/// <summary>
/// Off-premises discount
/// </summary>
[Description("ABL")]
OffPremisesDiscount = 2,

/// <summary>
/// Customer discount
/// </summary>
[Description("ADR")]
CustomerDiscount = 3,

/// <summary>
/// Damaged goods
/// </summary>
[Description("ADT")]
DamagedGoods = 4,

/// <summary>
/// Early payment allowance
/// </summary>
[Description("FC")]
EarlyPaymentAllowance = 66,

/// <summary>
/// Discount
/// </summary>
[Description("95")]
Discount = 95,

/// <summary>
/// Volume discount
/// </summary>
[Description("100")]
VolumeDiscount = 100,

/// <summary>
/// Special agreement
/// </summary>
[Description("102")]
SpecialAgreement = 102,

/// <summary>
/// Freight charge
/// </summary>
[Description("FC")]
FreightCharge = 30, // FC

/// <summary>
/// Insurance
/// </summary>
[Description("FI")]
Insurance = 31, // INS

/// <summary>
/// Packaging
/// </summary>
[Description("PAC")]
Packaging = 32, // PAC

/// <summary>
/// Pallet charge
/// </summary>
[Description("PC")]
PalletCharge = 33, // PC

/// <summary>
/// Handling service
/// </summary>
[Description("SH")]
HandlingService = 34, // SH

/// <summary>
/// Transport costs
/// </summary>
[Description("TC")]
TransportCosts = 35, // TC

/// <summary>
/// Miscellaneous service
/// </summary>
[Description("ZZZ")]
MiscellaneousService = 99 // ZZZ
}
}
32 changes: 30 additions & 2 deletions ZUGFeRD/EnumExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
Expand All @@ -18,6 +18,9 @@
*/

using System;
using System.ComponentModel;
using System.Reflection;


namespace s2industries.ZUGFeRD
{
Expand Down Expand Up @@ -59,5 +62,30 @@ internal static int EnumToInt<T>(this T value) where T : Enum
{
return (int)(object)value;
} // !EnumToInt()


internal static string GetDescriptionAttribute<T>(this T value) where T : Enum
{
FieldInfo field = value.GetType().GetField(value.ToString());
DescriptionAttribute attribute = field.GetCustomAttribute<DescriptionAttribute>();
return attribute?.Description ?? value.ToString();
} // !GetDescriptionAttribute()


internal static T FromDescription<T>(string code) where T : Enum
{
if (string.IsNullOrEmpty(code))
{
return default(T);
}
foreach (T value in Enum.GetValues(typeof(T)))
{
if (value.GetDescriptionAttribute().Equals(code, StringComparison.OrdinalIgnoreCase))
{
return value;
}
}
return default(T);
} // !FromDescription()
}
}
12 changes: 9 additions & 3 deletions ZUGFeRD/InvoiceDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -818,15 +818,19 @@ public void AddLogisticsServiceCharge(decimal amount, string description, TaxTyp
/// <param name="currency">Curency of the allowance</param>
/// <param name="actualAmount">Actual allowance charge amount</param>
/// <param name="reason">Reason for the allowance</param>
/// <param name="reasonCode">Reason code for the allowance</param>
/// <param name="taxTypeCode">VAT type code for document level allowance/ charge</param>
/// <param name="taxCategoryCode">VAT type code for document level allowance/ charge</param>
/// <param name="taxPercent">VAT rate for the allowance</param>
public void AddTradeAllowanceCharge(bool isDiscount, decimal? basisAmount, CurrencyCodes currency, decimal actualAmount, string reason, TaxTypes taxTypeCode, TaxCategoryCodes taxCategoryCode, decimal taxPercent)
public void AddTradeAllowanceCharge(bool isDiscount, decimal? basisAmount, CurrencyCodes currency, decimal actualAmount,
string reason, TaxTypes taxTypeCode, TaxCategoryCodes taxCategoryCode, decimal taxPercent,
AllowanceReasonCodes reasonCode = AllowanceReasonCodes.Unknown)
{
this._TradeAllowanceCharges.Add(new TradeAllowanceCharge()
{
ChargeIndicator = !isDiscount,
Reason = reason,
ReasonCode = reasonCode,
BasisAmount = basisAmount,
ActualAmount = actualAmount,
Currency = currency,
Expand Down Expand Up @@ -856,12 +860,14 @@ public void AddTradeAllowanceCharge(bool isDiscount, decimal? basisAmount, Curre
/// <param name="taxTypeCode">VAT type code for document level allowance/ charge</param>
/// <param name="taxCategoryCode">VAT type code for document level allowance/ charge</param>
/// <param name="taxPercent">VAT rate for the allowance</param>
public void AddTradeAllowanceCharge(bool isDiscount, decimal? basisAmount, CurrencyCodes currency, decimal actualAmount, decimal? chargePercentage, string reason, TaxTypes taxTypeCode, TaxCategoryCodes taxCategoryCode, decimal taxPercent)
/// <param name="reasonCode">Reason code for the allowance</param>
public void AddTradeAllowanceCharge(bool isDiscount, decimal? basisAmount, CurrencyCodes currency, decimal actualAmount, decimal? chargePercentage, string reason, TaxTypes taxTypeCode, TaxCategoryCodes taxCategoryCode, decimal taxPercent, AllowanceReasonCodes reasonCode = AllowanceReasonCodes.Unknown)
{
this._TradeAllowanceCharges.Add(new TradeAllowanceCharge()
{
ChargeIndicator = !isDiscount,
Reason = reason,
ReasonCode = reasonCode,
BasisAmount = basisAmount,
ActualAmount = actualAmount,
Currency = currency,
Expand Down Expand Up @@ -1215,7 +1221,7 @@ public TradeLineItem AddTradeLineItem(string name,
buyerAssignedID: buyerAssignedID,
deliveryNoteID: deliveryNoteID,
deliveryNoteDate: deliveryNoteDate,
buyerOrderLineID: buyerOrderLineID,
buyerOrderLineID: buyerOrderLineID,
buyerOrderID: buyerOrderID, // Extended!
buyerOrderDate: buyerOrderDate,
billingPeriodStart: billingPeriodStart,
Expand Down
11 changes: 6 additions & 5 deletions ZUGFeRD/InvoiceDescriptor1Reader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
Expand All @@ -27,7 +27,7 @@ internal class InvoiceDescriptor1Reader : IInvoiceDescriptorReader
{
/// <summary>
/// Parses the ZUGFeRD invoice from the given stream.
///
///
/// Make sure that the stream is open, otherwise an IllegalStreamException exception is thrown.
/// Important: the stream will not be closed by this function.
/// </summary>
Expand Down Expand Up @@ -210,7 +210,8 @@ public override InvoiceDescriptor Load(Stream stream)
XmlUtils.NodeAsString(node, ".//ram:Reason", nsmgr),
default(TaxTypes).FromString(XmlUtils.NodeAsString(node, ".//ram:CategoryTradeTax/ram:TypeCode", nsmgr)),
default(TaxCategoryCodes).FromString(XmlUtils.NodeAsString(node, ".//ram:CategoryTradeTax/ram:CategoryCode", nsmgr)),
XmlUtils.NodeAsDecimal(node, ".//ram:CategoryTradeTax/ram:ApplicablePercent", nsmgr, 0).Value);
XmlUtils.NodeAsDecimal(node, ".//ram:CategoryTradeTax/ram:ApplicablePercent", nsmgr, 0).Value,
EnumExtensions.FromDescription<AllowanceReasonCodes>(XmlUtils.NodeAsString(node, "./ram:ReasonCode", nsmgr)));
}

foreach (XmlNode node in doc.SelectNodes("//ram:SpecifiedLogisticsServiceCharge", nsmgr))
Expand Down Expand Up @@ -392,7 +393,7 @@ private static TradeLineItem _parseTradeLineItem(XmlNode tradeLineItem, XmlNames
foreach (XmlNode referenceNode in referenceNodes)
{
string typeCodeAsString = XmlUtils.NodeAsString(referenceNode, "ram:TypeCode", nsmgr);
string codeAsString = XmlUtils.NodeAsString(referenceNode, "ram:ReferenceTypeCode", nsmgr);
string codeAsString = XmlUtils.NodeAsString(referenceNode, "ram:ReferenceTypeCode", nsmgr);

item.AddAdditionalReferencedDocument(
id: XmlUtils.NodeAsString(referenceNode, "ram:ID", nsmgr),
Expand Down
Loading

0 comments on commit ad7f083

Please sign in to comment.