namespace DXApp.TemplateKitProject.Services; using DXApp.TemplateKitProject.Models; using System.Xml.Linq; public class ZugferdParserService { // ZUGFeRD v2 / Factur-X Namespaces private static readonly XNamespace Ram = "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"; private static readonly XNamespace Rsm = "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"; private static readonly XNamespace Udt = "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"; public ZugferdInvoice Parse(string xml) { var doc = XDocument.Parse(xml); var root = doc.Root!; var header = root.Element(Rsm + "ExchangedDocument"); var trade = root.Element(Rsm + "SupplyChainTradeTransaction"); var agreement = trade?.Element(Ram + "ApplicableHeaderTradeAgreement"); var settlement = trade?.Element(Ram + "ApplicableHeaderTradeSettlement"); return new ZugferdInvoice { InvoiceNumber = header?.Element(Ram + "ID")?.Value ?? string.Empty, InvoiceDate = ParseDate(header?.Element(Ram + "IssueDateTime") ?.Element(Udt + "DateTimeString")?.Value), SellerName = agreement?.Element(Ram + "SellerTradeParty") ?.Element(Ram + "Name")?.Value ?? string.Empty, SellerTaxId = agreement?.Element(Ram + "SellerTradeParty") ?.Element(Ram + "SpecifiedTaxRegistration") ?.Element(Ram + "ID")?.Value ?? string.Empty, BuyerName = agreement?.Element(Ram + "BuyerTradeParty") ?.Element(Ram + "Name")?.Value ?? string.Empty, CurrencyCode = settlement?.Element(Ram + "InvoiceCurrencyCode")?.Value ?? "EUR", TotalAmount = ParseDecimal(settlement?.Element(Ram + "SpecifiedTradeSettlementHeaderMonetarySummation") ?.Element(Ram + "GrandTotalAmount")?.Value), TaxAmount = ParseDecimal(settlement?.Element(Ram + "SpecifiedTradeSettlementHeaderMonetarySummation") ?.Element(Ram + "TaxTotalAmount")?.Value), Iban = settlement?.Element(Ram + "SpecifiedTradeSettlementPaymentMeans") ?.Element(Ram + "PayeePartyCreditorFinancialAccount") ?.Element(Ram + "IBANID")?.Value ?? string.Empty, RawXml = xml, ImportedAt = DateTime.UtcNow }; } private static DateTime ParseDate(string? value) { if (string.IsNullOrWhiteSpace(value)) return DateTime.MinValue; return DateTime.TryParseExact(value, "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var dt) ? dt : DateTime.MinValue; } private static decimal ParseDecimal(string? value) => decimal.TryParse(value, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var d) ? d : 0m; }