Skip to content

Commit

Permalink
misc corrections, added fluent interface for line items
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanstapel committed Jan 30, 2025
1 parent 47c0465 commit 5354e3d
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 35 deletions.
27 changes: 13 additions & 14 deletions ZUGFeRD.Test/ZUGFeRD22Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ public void TestLineStatusCode()

desc.TradeLineItems.Clear();

TradeLineItem tradeLineItem1 = desc.AddTradeLineItem(
desc.AddTradeLineItem(
name: "Trennblätter A4",
billedQuantity: 20m,
unitCode: QuantityCodes.H87,
netUnitPrice: 9.9m,
grossUnitPrice: 9.9m,
categoryCode: TaxCategoryCodes.S,
taxPercent: 19.0m,
taxType: TaxTypes.VAT);
tradeLineItem1.SetLineStatus(LineStatusCodes.New, LineStatusReasonCodes.DETAIL);
taxType: TaxTypes.VAT)
.SetLineStatus(LineStatusCodes.New, LineStatusReasonCodes.DETAIL);

desc.AddTradeLineItem(
name: "Joghurt Banane",
Expand All @@ -72,15 +72,15 @@ public void TestLineStatusCode()
taxPercent: 7.0m,
taxType: TaxTypes.VAT);

TradeLineItem tradeLineItem3 = desc.AddTradeLineItem(
desc.AddTradeLineItem(
name: "Abschlagsrechnung vom 01.01.2024",
billedQuantity: -1m,
unitCode: QuantityCodes.C62,
netUnitPrice: 500,
categoryCode: TaxCategoryCodes.S,
taxPercent: 19.0m,
taxType: TaxTypes.VAT);
tradeLineItem3.SetLineStatus(LineStatusCodes.DocumentationClaim, LineStatusReasonCodes.INFORMATION);
taxType: TaxTypes.VAT)
.SetLineStatus(LineStatusCodes.DocumentationClaim, LineStatusReasonCodes.INFORMATION);

MemoryStream ms = new MemoryStream();

Expand Down Expand Up @@ -109,7 +109,7 @@ public void TestExtendedInvoiceWithIncludedItems()

desc.TradeLineItems.Clear();

TradeLineItem tradeLineItem = desc.AddTradeLineItem(
desc.AddTradeLineItem(
lineID: "1",
name: "Trennblätter A4",
billedQuantity: 20m,
Expand All @@ -118,10 +118,9 @@ public void TestExtendedInvoiceWithIncludedItems()
grossUnitPrice: 9.9m,
categoryCode: TaxCategoryCodes.S,
taxPercent: 19.0m,
taxType: TaxTypes.VAT);

tradeLineItem.AddIncludedReferencedProduct("Test", 1, QuantityCodes.C62);
tradeLineItem.AddIncludedReferencedProduct("Test2");
taxType: TaxTypes.VAT)
.AddIncludedReferencedProduct("Test", 1, QuantityCodes.C62)
.AddIncludedReferencedProduct("Test2");

MemoryStream ms = new MemoryStream();

Expand Down Expand Up @@ -912,9 +911,9 @@ public void TestWriteTradeLineChargeFreePackage()
fileStream.Close();

// Modifiy trade line settlement data
TradeLineItem tradelineItem = originalInvoiceDescriptor.AddTradeLineItem(name: String.Empty);
tradelineItem.SetChargeFreeQuantity(10, QuantityCodes.C62);
tradelineItem.SetPackageQuantity(20, QuantityCodes.C62);
originalInvoiceDescriptor.AddTradeLineItem(name: String.Empty)
.SetChargeFreeQuantity(10, QuantityCodes.C62)
.SetPackageQuantity(20, QuantityCodes.C62);

originalInvoiceDescriptor.IsTest = false;

Expand Down
12 changes: 12 additions & 0 deletions ZUGFeRD/InvoiceDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,26 @@ public class InvoiceDescriptor

/// <summary>
/// This party is optional and is written in most profiles except Minimum profile
///
/// BG-13
/// </summary>
public Party ShipTo { get; set; }

/// <summary>
/// Detailed contact information of the recipient
/// BG-X-26
/// </summary>
public Contact ShipToContact { get; set; }

/// <summary>
/// This party is optional and only relevant for Extended profile
/// </summary>
public Party UltimateShipTo { get; set; }

/// <summary>
/// Detailed contact information of the final goods recipient
/// BG-X-11
/// </summary>
public Contact UltimateShipToContact { get; set; }

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions ZUGFeRD/InvoiceDescriptor23CIIReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,9 @@ public override InvoiceDescriptor Load(Stream stream)
}

retval.ShipTo = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty", nsmgr);
retval.ShipToContact = _nodeAsContact(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty", nsmgr);
retval.ShipToContact = _nodeAsContact(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty/ram:DefinedTradeContact", nsmgr);
retval.UltimateShipTo = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:UltimateShipToTradeParty", nsmgr);
retval.UltimateShipToContact = _nodeAsContact(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:UltimateShipToTradeParty", nsmgr);
retval.UltimateShipToContact = _nodeAsContact(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:UltimateShipToTradeParty/ram:DefinedTradeContact", nsmgr);
retval.ShipFrom = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ShipFromTradeParty", nsmgr);
retval.ActualDeliveryDate = XmlUtils.NodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString", nsmgr);

Expand Down
55 changes: 36 additions & 19 deletions ZUGFeRD/TradeLineItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public TradeLineItem(string lineId)
/// <param name="actualAmount">The actual allowance or surcharge amount</param>
/// <param name="reason">Reason for the allowance or surcharge</param>
/// <param name="reasonCode">Reason code for the allowance or surcharge</param>
public void AddTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, decimal? basisAmount, decimal actualAmount,
public TradeLineItem AddTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, decimal? basisAmount, decimal actualAmount,
string reason, AllowanceReasonCodes reasonCode = AllowanceReasonCodes.Unknown)
{
this._TradeAllowanceCharges.Add(new TradeAllowanceCharge()
Expand All @@ -318,6 +318,7 @@ public void AddTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, dec
Reason = reason,
ReasonCode = reasonCode
});
return this;
} // !AddTradeAllowanceCharge()


Expand All @@ -331,7 +332,7 @@ public void AddTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, dec
/// <param name="chargePercentage">Actual allowance or surcharge charge percentage</param>
/// <param name="reason">Reason for the allowance or surcharge</param>
/// <param name="reasonCode">Reason code for the allowance or surcharge</param>
public void AddTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, decimal? basisAmount, decimal actualAmount,
public TradeLineItem AddTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, decimal? basisAmount, decimal actualAmount,
decimal? chargePercentage, string reason, AllowanceReasonCodes reasonCode = AllowanceReasonCodes.Unknown)
{
this._TradeAllowanceCharges.Add(new TradeAllowanceCharge()
Expand All @@ -344,6 +345,7 @@ public void AddTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, dec
Reason = reason,
ReasonCode = reasonCode
});
return this;
} // !AddTradeAllowanceCharge()


Expand All @@ -365,7 +367,7 @@ public IList<TradeAllowanceCharge> GetTradeAllowanceCharges()
/// <param name="basisAmount">Basis aount for the allowance or surcharge, typicalls the net amount of the item</param>
/// <param name="actualAmount">The actual allowance or surcharge amount</param>
/// <param name="reason">Reason for the allowance or surcharge</param>
public void AddSpecifiedTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, decimal? basisAmount, decimal actualAmount,
public TradeLineItem AddSpecifiedTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, decimal? basisAmount, decimal actualAmount,
string reason,
AllowanceReasonCodes reasonCode = AllowanceReasonCodes.Unknown)
{
Expand All @@ -378,6 +380,7 @@ public void AddSpecifiedTradeAllowanceCharge(bool isDiscount, CurrencyCodes curr
Reason = reason,
ReasonCode = reasonCode
});
return this;
} // !AddSpecifiedTradeAllowanceCharge()


Expand All @@ -390,7 +393,7 @@ public void AddSpecifiedTradeAllowanceCharge(bool isDiscount, CurrencyCodes curr
/// <param name="actualAmount">The actual allowance or surcharge amount</param>
/// <param name="chargePercentage">Actual allowance or surcharge charge percentage</param>
/// <param name="reason">Reason for the allowance or surcharge</param>
public void AddSpecifiedTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, decimal? basisAmount, decimal actualAmount,
public TradeLineItem AddSpecifiedTradeAllowanceCharge(bool isDiscount, CurrencyCodes currency, decimal? basisAmount, decimal actualAmount,
decimal? chargePercentage, string reason,
AllowanceReasonCodes reasonCode = AllowanceReasonCodes.Unknown)
{
Expand All @@ -404,6 +407,7 @@ public void AddSpecifiedTradeAllowanceCharge(bool isDiscount, CurrencyCodes curr
Reason = reason,
ReasonCode = reasonCode
});
return this;
} // !AddSpecifiedTradeAllowanceCharge()


Expand All @@ -420,37 +424,41 @@ public IList<TradeAllowanceCharge> GetSpecifiedTradeAllowanceCharges()
/// <summary>
/// The value given here refers to the superior line. In this way, a hierarchy tree of invoice items can be mapped.
/// </summary>
public void SetParentLineId(string parentLineId)
public TradeLineItem SetParentLineId(string parentLineId)
{
this.AssociatedDocument.ParentLineID = parentLineId;
return this;
}

/// <summary>
/// Sets the status code and reason code for this trade line item
/// </summary>
/// <param name="lineStatusCode">The status code for this line</param>
/// <param name="lineStatusReasonCode">The reason code explaining the status</param>
public void SetLineStatus(LineStatusCodes lineStatusCode, LineStatusReasonCodes lineStatusReasonCode)
public TradeLineItem SetLineStatus(LineStatusCodes lineStatusCode, LineStatusReasonCodes lineStatusReasonCode)
{
this.AssociatedDocument.LineStatusCode = lineStatusCode;
this.AssociatedDocument.LineStatusReasonCode = lineStatusReasonCode;
return this;
}


/// <summary>
/// Sets the delivery note reference information for this trade line item. BG-X-83
/// Only available in Extended profile.
/// </summary>
/// <param name="deliveryNoteId">The identifier of the delivery note. BT-X-92</param>
/// <param name="deliveryNoteDate">The date of the delivery note. BT-X-94</param>
/// <param name="deliveryNoteReferencedLineId">The identifier of the delivery note item. BT-X-93</param>
public void SetDeliveryNoteReferencedDocument(string deliveryNoteId, DateTime? deliveryNoteDate, string deliveryNoteReferencedLineId = null)
public TradeLineItem SetDeliveryNoteReferencedDocument(string deliveryNoteId, DateTime? deliveryNoteDate, string deliveryNoteReferencedLineId = null)
{
this.DeliveryNoteReferencedDocument = new DeliveryNoteReferencedDocument()
{
ID = deliveryNoteId,
IssueDateTime = deliveryNoteDate,
LineID = deliveryNoteReferencedLineId
};
return this;
} // !SetDeliveryNoteReferencedDocument()


Expand All @@ -461,7 +469,7 @@ public void SetDeliveryNoteReferencedDocument(string deliveryNoteId, DateTime? d
/// <param name="typeCode">Type of the document</param>
/// <param name="code">Reference type code</param>
/// <param name="issueDateTime">Issue date and time of the document</param>
public void AddAdditionalReferencedDocument(string id, AdditionalReferencedDocumentTypeCode typeCode, ReferenceTypeCodes code = ReferenceTypeCodes.Unknown, DateTime? issueDateTime = null)
public TradeLineItem AddAdditionalReferencedDocument(string id, AdditionalReferencedDocumentTypeCode typeCode, ReferenceTypeCodes code = ReferenceTypeCodes.Unknown, DateTime? issueDateTime = null)
{
this._AdditionalReferencedDocuments.Add(new AdditionalReferencedDocument()
{
Expand All @@ -470,23 +478,27 @@ public void AddAdditionalReferencedDocument(string id, AdditionalReferencedDocum
TypeCode = typeCode,
ReferenceTypeCode = code
});
return this;
} // !AddAdditionalReferencedDocument()


/// <summary>
/// Adds a referenced product that is included in this trade line item
/// </summary>
/// <param name="name">Name of the included product</param>
/// <param name="unitQuantity">Quantity of the included product</param>
/// <param name="quantityCodes">Unit code for the quantity</param>
public void AddIncludedReferencedProduct(string name, decimal? unitQuantity = null, QuantityCodes? quantityCodes = null)
public TradeLineItem AddIncludedReferencedProduct(string name, decimal? unitQuantity = null, QuantityCodes? quantityCodes = null)
{
this.IncludedReferencedProducts.Add(new IncludedReferencedProduct()
{
Name = name,
UnitQuantity = unitQuantity,
UnitCode = quantityCodes
});
}
return this;
} // !AddIncludedReferencedProduct()


/// <summary>
/// Add an additional reference document
Expand All @@ -500,7 +512,7 @@ public void AddIncludedReferencedProduct(string name, decimal? unitQuantity = nu
/// <param name="filename"></param>
/// <param name="uriID"></param>
/// <param name="lineID"></param>
public void AddAdditionalReferencedDocument(string id, AdditionalReferencedDocumentTypeCode typeCode, DateTime? issueDateTime = null,
public TradeLineItem AddAdditionalReferencedDocument(string id, AdditionalReferencedDocumentTypeCode typeCode, DateTime? issueDateTime = null,
string name = null, ReferenceTypeCodes referenceTypeCode = ReferenceTypeCodes.Unknown, byte[] attachmentBinaryObject = null,
string filename = null, string uriID = null, string lineID = null)
{
Expand All @@ -516,6 +528,7 @@ public void AddAdditionalReferencedDocument(string id, AdditionalReferencedDocum
URIID = uriID,
LineID = lineID
});
return this;
} // !AddAdditionalReferencedDocument()


Expand All @@ -534,14 +547,15 @@ public IList<AdditionalReferencedDocument> GetAdditionalReferencedDocuments()
/// Please note that XRechnung/ FacturX allows a maximum of one such reference and will only output the referenced order line id
/// but not issuer assigned id and date
/// </summary>
public void SetOrderReferencedDocument(string orderReferencedId, DateTime? orderReferencedDate, string orderReferencedLineId)
public TradeLineItem SetOrderReferencedDocument(string orderReferencedId, DateTime? orderReferencedDate, string orderReferencedLineId)
{
this.BuyerOrderReferencedDocument = new BuyerOrderReferencedDocument()
{
ID = orderReferencedId,
IssueDateTime = orderReferencedDate,
LineID = orderReferencedLineId
};
return this;
} // !SetOrderReferencedDocument()


Expand All @@ -552,38 +566,41 @@ public void SetOrderReferencedDocument(string orderReferencedId, DateTime? order
/// <param name="contractReferencedId">The identifier of the contract. BT-X-24</param>
/// <param name="contractReferencedDate">The date of the contract. BT-X-26</param>
/// <param name="contractReferencedLineId">The identifier of the contract position. BT-X-25</param>
public void SetContractReferencedDocument(string contractReferencedId, DateTime? contractReferencedDate, string contractReferencedLineId = null)
public TradeLineItem SetContractReferencedDocument(string contractReferencedId, DateTime? contractReferencedDate, string contractReferencedLineId = null)
{
this.ContractReferencedDocument = new ContractReferencedDocument()
{
ID = contractReferencedId,
IssueDateTime = contractReferencedDate,
LineID = contractReferencedLineId
};
return this;
} // !SetContractReferencedDocument()


/// <summary>
/// Adds an invoice line Buyer accounting reference with default Unknown account type
/// </summary>
/// <param name="AccountID">The accounting reference identifier</param>
public void AddReceivableSpecifiedTradeAccountingAccount(string AccountID)
public TradeLineItem AddReceivableSpecifiedTradeAccountingAccount(string AccountID)
{
AddReceivableSpecifiedTradeAccountingAccount(AccountID, AccountingAccountTypeCodes.Unknown);
return this;
}


/// <summary>
/// Adds an invoice line Buyer accounting reference. BT-133
/// Please note that XRechnung/ FacturX allows a maximum of one such reference
/// </summary>
public void AddReceivableSpecifiedTradeAccountingAccount(string AccountID, AccountingAccountTypeCodes AccountTypeCode)
public TradeLineItem AddReceivableSpecifiedTradeAccountingAccount(string AccountID, AccountingAccountTypeCodes AccountTypeCode)
{
this.ReceivableSpecifiedTradeAccountingAccounts.Add(new ReceivableSpecifiedTradeAccountingAccount()
{
TradeAccountID = AccountID,
TradeAccountTypeCode = AccountTypeCode
});
return this;
}


Expand Down Expand Up @@ -631,11 +648,11 @@ public List<DesignatedProductClassification> GetDesignatedProductClassifications
/// <param name="chargeFreeUnitCode">Unit code for the quantity</param>
/// </summary>
/// <returns></returns>
public void SetChargeFreeQuantity(decimal chargeFreeQuantity, QuantityCodes chargeFreeUnitCode)
public TradeLineItem SetChargeFreeQuantity(decimal chargeFreeQuantity, QuantityCodes chargeFreeUnitCode)
{
ChargeFreeQuantity = chargeFreeQuantity;
ChargeFreeUnitCode = chargeFreeUnitCode;

return this;
} // !SetChargeFreeQuantity()

/// sets the number of packages, at line level, in this trade delivery.
Expand All @@ -644,11 +661,11 @@ public void SetChargeFreeQuantity(decimal chargeFreeQuantity, QuantityCodes char
/// <param name="packageUnitCode">Unit code for the quantity</param>
/// </summary>
/// <returns></returns>
public void SetPackageQuantity(decimal packageQuantity, QuantityCodes packageUnitCode)
public TradeLineItem SetPackageQuantity(decimal packageQuantity, QuantityCodes packageUnitCode)
{
PackageQuantity = packageQuantity;
PackageUnitCode = packageUnitCode;

return this;
} // !SetPackageQuantity()

}
Expand Down

0 comments on commit 5354e3d

Please sign in to comment.