From bd15684b5eea2e0767244207bc6381ea2a590f02 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 4 Jul 2024 21:29:59 +0200 Subject: [PATCH] simplified handling of xml namespaces for reading documents makes code more robust --- ZUGFeRD/IInvoiceDescriptorReader.cs | 19 + ZUGFeRD/InvoiceDescriptor1Reader.cs | 5 +- ZUGFeRD/InvoiceDescriptor20Reader.cs | 7 +- ZUGFeRD/InvoiceDescriptor22Reader.cs | 1217 +++++++++++++------------- 4 files changed, 627 insertions(+), 621 deletions(-) diff --git a/ZUGFeRD/IInvoiceDescriptorReader.cs b/ZUGFeRD/IInvoiceDescriptorReader.cs index 3a075b9..63cbd73 100644 --- a/ZUGFeRD/IInvoiceDescriptorReader.cs +++ b/ZUGFeRD/IInvoiceDescriptorReader.cs @@ -59,6 +59,25 @@ public bool IsReadableByThisReaderVersion(string filename) } // !IsReadableByThisReaderVersion() + protected XmlNamespaceManager _GenerateNamespaceManagerFromNode(XmlNode node) + { + XmlNamespaceManager nsmgr = new XmlNamespaceManager(node.OwnerDocument.NameTable); + foreach (XmlAttribute attr in node.Attributes) + { + if (attr.Prefix == "xmlns") + { + nsmgr.AddNamespace(attr.LocalName, attr.Value); + } + else if (attr.Name == "xmlns") + { + nsmgr.AddNamespace(string.Empty, attr.Value); + } + } + + return nsmgr; + } // !_GenerateNamespaceManagerFromNode() + + protected static bool _nodeAsBool(XmlNode node, string xpath, XmlNamespaceManager nsmgr = null, bool defaultValue = true) { if (node == null) diff --git a/ZUGFeRD/InvoiceDescriptor1Reader.cs b/ZUGFeRD/InvoiceDescriptor1Reader.cs index 2a81139..8a9f315 100644 --- a/ZUGFeRD/InvoiceDescriptor1Reader.cs +++ b/ZUGFeRD/InvoiceDescriptor1Reader.cs @@ -45,10 +45,7 @@ public override InvoiceDescriptor Load(Stream stream) XmlDocument doc = new XmlDocument(); doc.Load(stream); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.DocumentElement.OwnerDocument.NameTable); - nsmgr.AddNamespace("rsm", "urn:ferd:CrossIndustryDocument:invoice:1p0"); - nsmgr.AddNamespace("ram", "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12"); - nsmgr.AddNamespace("udt", "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15"); + XmlNamespaceManager nsmgr = _GenerateNamespaceManagerFromNode(doc.DocumentElement); InvoiceDescriptor retval = new InvoiceDescriptor { diff --git a/ZUGFeRD/InvoiceDescriptor20Reader.cs b/ZUGFeRD/InvoiceDescriptor20Reader.cs index db15428..71f50c9 100644 --- a/ZUGFeRD/InvoiceDescriptor20Reader.cs +++ b/ZUGFeRD/InvoiceDescriptor20Reader.cs @@ -46,12 +46,7 @@ public override InvoiceDescriptor Load(Stream stream) XmlDocument doc = new XmlDocument(); doc.Load(stream); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.DocumentElement.OwnerDocument.NameTable); - nsmgr.AddNamespace("qdt", "urn:un:unece:uncefact:data:standard:QualifiedDataType:100"); - nsmgr.AddNamespace("a", "urn:un:unece:uncefact:data:standard:QualifiedDataType:100"); - nsmgr.AddNamespace("rsm", "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"); - nsmgr.AddNamespace("ram", "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"); - nsmgr.AddNamespace("udt", "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"); + XmlNamespaceManager nsmgr = _GenerateNamespaceManagerFromNode(doc.DocumentElement); InvoiceDescriptor retval = new InvoiceDescriptor { diff --git a/ZUGFeRD/InvoiceDescriptor22Reader.cs b/ZUGFeRD/InvoiceDescriptor22Reader.cs index 9c46b02..cc1d8f1 100644 --- a/ZUGFeRD/InvoiceDescriptor22Reader.cs +++ b/ZUGFeRD/InvoiceDescriptor22Reader.cs @@ -28,389 +28,384 @@ namespace s2industries.ZUGFeRD { - internal class InvoiceDescriptor22Reader : IInvoiceDescriptorReader - { - /// - /// 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. - /// - /// - /// The parsed ZUGFeRD invoice - public override InvoiceDescriptor Load(Stream stream) + internal class InvoiceDescriptor22Reader : IInvoiceDescriptorReader { - if (!stream.CanRead) - { - throw new IllegalStreamException("Cannot read from stream"); - } - - XmlDocument doc = new XmlDocument(); - doc.Load(stream); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.DocumentElement.OwnerDocument.NameTable); - nsmgr.AddNamespace("qdt", "urn:un:unece:uncefact:data:standard:QualifiedDataType:100"); - nsmgr.AddNamespace("a", "urn:un:unece:uncefact:data:standard:QualifiedDataType:100"); - nsmgr.AddNamespace("rsm", "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"); - nsmgr.AddNamespace("ram", "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"); - nsmgr.AddNamespace("udt", "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"); - - InvoiceDescriptor retval = new InvoiceDescriptor - { - IsTest = _nodeAsBool(doc.DocumentElement, "//rsm:ExchangedDocumentContext/ram:TestIndicator/udt:Indicator", nsmgr), - BusinessProcess = _nodeAsString(doc.DocumentElement, "//ram:BusinessProcessSpecifiedDocumentContextParameter/ram:ID", nsmgr), - Profile = default(Profile).FromString(_nodeAsString(doc.DocumentElement, "//ram:GuidelineSpecifiedDocumentContextParameter/ram:ID", nsmgr)), - Type = default(InvoiceType).FromString(_nodeAsString(doc.DocumentElement, "//rsm:ExchangedDocument/ram:TypeCode", nsmgr)), - InvoiceNo = _nodeAsString(doc.DocumentElement, "//rsm:ExchangedDocument/ram:ID", nsmgr), - InvoiceDate = _nodeAsDateTime(doc.DocumentElement, "//rsm:ExchangedDocument/ram:IssueDateTime/udt:DateTimeString", nsmgr) - }; - - foreach (XmlNode node in doc.SelectNodes("//rsm:ExchangedDocument/ram:IncludedNote", nsmgr)) - { - string content = _nodeAsString(node, ".//ram:Content", nsmgr); - string _subjectCode = _nodeAsString(node, ".//ram:SubjectCode", nsmgr); - SubjectCodes subjectCode = default(SubjectCodes).FromString(_subjectCode); - string _contentCode = _nodeAsString(node, ".//ram:ContentCode", nsmgr); - ContentCodes contentCode = default(ContentCodes).FromString(_contentCode); - retval.AddNote(content, subjectCode, contentCode); - } - - retval.ReferenceOrderNo = _nodeAsString(doc, "//ram:ApplicableHeaderTradeAgreement/ram:BuyerReference", nsmgr); - - retval.Seller = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty", nsmgr); - - if (doc.SelectSingleNode("//ram:SellerTradeParty/ram:URIUniversalCommunication", nsmgr) != null) - { - string id = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:URIUniversalCommunication/ram:URIID", nsmgr); - string schemeID = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:URIUniversalCommunication/ram:URIID/@schemeID", nsmgr); - - var eas = default(ElectronicAddressSchemeIdentifiers).FromString(schemeID); - - if (eas.HasValue) - retval.SetSellerElectronicAddress(id, eas.Value); - } - - foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration", nsmgr)) - { - string id = _nodeAsString(node, ".//ram:ID", nsmgr); - string schemeID = _nodeAsString(node, ".//ram:ID/@schemeID", nsmgr); - - retval.AddSellerTaxRegistration(id, default(TaxRegistrationSchemeID).FromString(schemeID)); - } - - if (doc.SelectSingleNode("//ram:SellerTradeParty/ram:DefinedTradeContact", nsmgr) != null) - { - retval.SellerContact = new Contact() + /// + /// 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. + /// + /// + /// The parsed ZUGFeRD invoice + public override InvoiceDescriptor Load(Stream stream) { - Name = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:PersonName", nsmgr), - OrgUnit = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:DepartmentName", nsmgr), - PhoneNo = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber", nsmgr), - FaxNo = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:FaxUniversalCommunication/ram:CompleteNumber", nsmgr), - EmailAddress = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID", nsmgr) - }; - } - - retval.Buyer = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty", nsmgr); - - if (doc.SelectSingleNode("//ram:BuyerTradeParty/ram:URIUniversalCommunication", nsmgr) != null) - { - string id = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:URIUniversalCommunication/ram:URIID", nsmgr); - string schemeID = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:URIUniversalCommunication/ram:URIID/@schemeID", nsmgr); - - var eas = default(ElectronicAddressSchemeIdentifiers).FromString(schemeID); - - if (eas.HasValue) - retval.SetBuyerElectronicAddress(id, eas.Value); - } - - foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:SpecifiedTaxRegistration", nsmgr)) - { - string id = _nodeAsString(node, ".//ram:ID", nsmgr); - string schemeID = _nodeAsString(node, ".//ram:ID/@schemeID", nsmgr); - - retval.AddBuyerTaxRegistration(id, default(TaxRegistrationSchemeID).FromString(schemeID)); - } - - if (doc.SelectSingleNode("//ram:BuyerTradeParty/ram:DefinedTradeContact", nsmgr) != null) - { - retval.BuyerContact = new Contact() - { - Name = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:PersonName", nsmgr), - OrgUnit = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:DepartmentName", nsmgr), - PhoneNo = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber", nsmgr), - FaxNo = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:FaxUniversalCommunication/ram:CompleteNumber", nsmgr), - EmailAddress = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID", nsmgr) - }; - } - - - //Get all referenced and embedded documents (BG-24) - XmlNodeList referencedDocNodes = doc.SelectNodes(".//ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument", nsmgr); - foreach (XmlNode referenceNode in referencedDocNodes) - { - retval.AdditionalReferencedDocuments.Add(_getAdditionalReferencedDocument(referenceNode, nsmgr)); - } - - //------------------------------------------------- - // hzi: With old implementation only the first document has been read instead of all documents - //------------------------------------------------- - //if (doc.SelectSingleNode("//ram:AdditionalReferencedDocument", nsmgr) != null) - //{ - // string _issuerAssignedID = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:IssuerAssignedID", nsmgr); - // string _typeCode = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:TypeCode", nsmgr); - // string _referenceTypeCode = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:ReferenceTypeCode", nsmgr); - // string _name = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:Name", nsmgr); - // DateTime? _date = _nodeAsDateTime(doc.DocumentElement, "//ram:AdditionalReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr); - - // if (doc.SelectSingleNode("//ram:AdditionalReferencedDocument/ram:AttachmentBinaryObject", nsmgr) != null) - // { - // string _filename = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:AttachmentBinaryObject/@filename", nsmgr); - // byte[] data = Convert.FromBase64String(_nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:AttachmentBinaryObject", nsmgr)); - - // retval.AddAdditionalReferencedDocument(id: _issuerAssignedID, - // typeCode: default(AdditionalReferencedDocumentTypeCode).FromString(_typeCode), - // issueDateTime: _date, - // referenceTypeCode: default(ReferenceTypeCodes).FromString(_referenceTypeCode), - // name: _name, - // attachmentBinaryObject: data, - // filename: _filename); - // } - // else - // { - // retval.AddAdditionalReferencedDocument(id: _issuerAssignedID, - // typeCode: default(AdditionalReferencedDocumentTypeCode).FromString(_typeCode), - // issueDateTime: _date, - // referenceTypeCode: default(ReferenceTypeCodes).FromString(_referenceTypeCode), - // name: _name); - // } - //} - //------------------------------------------------- - - - retval.ShipTo = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty", nsmgr); - retval.ShipFrom = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ShipFromTradeParty", nsmgr); - retval.ActualDeliveryDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString", nsmgr); - - string _despatchAdviceNo = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:IssuerAssignedID", nsmgr); - DateTime? _despatchAdviceDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:FormattedIssueDateTime/udt:DateTimeString", nsmgr); - - if (!_despatchAdviceDate.HasValue) - { - _despatchAdviceDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:FormattedIssueDateTime", nsmgr); - } - - if (_despatchAdviceDate.HasValue || !String.IsNullOrWhiteSpace(_despatchAdviceNo)) - { - retval.DespatchAdviceReferencedDocument = new DespatchAdviceReferencedDocument() - { - ID = _despatchAdviceNo, - IssueDateTime = _despatchAdviceDate - }; - } - - string _deliveryNoteNo = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID", nsmgr); - DateTime? _deliveryNoteDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssueDateTime/udt:DateTimeString", nsmgr); - - if (!_deliveryNoteDate.HasValue) - { - _deliveryNoteDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssueDateTime", nsmgr); - } - - if (_deliveryNoteDate.HasValue || !String.IsNullOrWhiteSpace(_deliveryNoteNo)) - { - retval.DeliveryNoteReferencedDocument = new DeliveryNoteReferencedDocument() - { - ID = _deliveryNoteNo, - IssueDateTime = _deliveryNoteDate - }; - } - - retval.Invoicee = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:InvoiceeTradeParty", nsmgr); - retval.Payee = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty", nsmgr); - - retval.PaymentReference = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:PaymentReference", nsmgr); - retval.Currency = default(CurrencyCodes).FromString(_nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:InvoiceCurrencyCode", nsmgr)); - - // TODO: Multiple SpecifiedTradeSettlementPaymentMeans can exist for each account/institution (with different SEPA?) - PaymentMeans _tempPaymentMeans = new PaymentMeans() - { - TypeCode = default(PaymentMeansTypeCodes).FromString(_nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode", nsmgr)), - Information = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:Information", nsmgr), - SEPACreditorIdentifier = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID", nsmgr), - SEPAMandateReference = _nodeAsString(doc.DocumentElement, "//ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID", nsmgr) - }; - - var financialCardId = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:ApplicableTradeSettlementFinancialCard/ram:ID", nsmgr); - var financialCardCardholderName = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:ApplicableTradeSettlementFinancialCard/ram:CardholderName", nsmgr); - - if (!string.IsNullOrWhiteSpace(financialCardId) || !string.IsNullOrWhiteSpace(financialCardCardholderName)) - { - _tempPaymentMeans.FinancialCard = new FinancialCard() - { - Id = financialCardId, - CardholderName = financialCardCardholderName - }; - } - - retval.PaymentMeans = _tempPaymentMeans; - - retval.BillingPeriodStart = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod/ram:StartDateTime", nsmgr); - retval.BillingPeriodEnd = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod/ram:EndDateTime", nsmgr); - - XmlNodeList creditorFinancialAccountNodes = doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount", nsmgr); - XmlNodeList creditorFinancialInstitutions = doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution", nsmgr); - - int numberOfAccounts = creditorFinancialAccountNodes.Count > creditorFinancialInstitutions.Count ? creditorFinancialAccountNodes.Count : creditorFinancialInstitutions.Count; - for (int i = 0; i < numberOfAccounts; i++) - { - BankAccount _account = new BankAccount(); - retval.CreditorBankAccounts.Add(_account); - } - - for (int i = 0; i < creditorFinancialAccountNodes.Count; i++) - { - retval.CreditorBankAccounts[i].ID = _nodeAsString(creditorFinancialAccountNodes[i], ".//ram:ProprietaryID", nsmgr); - retval.CreditorBankAccounts[i].IBAN = _nodeAsString(creditorFinancialAccountNodes[i], ".//ram:IBANID", nsmgr); - retval.CreditorBankAccounts[i].Name = _nodeAsString(creditorFinancialAccountNodes[i], ".//ram:AccountName", nsmgr); - } - - for (int i = 0; i < creditorFinancialInstitutions.Count; i++) - { - retval.CreditorBankAccounts[i].BIC = _nodeAsString(creditorFinancialInstitutions[i], ".//ram:BICID", nsmgr); - retval.CreditorBankAccounts[i].Bankleitzahl = _nodeAsString(creditorFinancialInstitutions[i], ".//ram:GermanBankleitzahlID", nsmgr); - retval.CreditorBankAccounts[i].BankName = _nodeAsString(creditorFinancialInstitutions[i], ".//ram:Name", nsmgr); - } - - var specifiedTradeSettlementPaymentMeansNodes = doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans", nsmgr); - - foreach (var specifiedTradeSettlementPaymentMeansNode in specifiedTradeSettlementPaymentMeansNodes.OfType()) - { - var payerPartyDebtorFinancialAccountNode = specifiedTradeSettlementPaymentMeansNode.SelectSingleNode("ram:PayerPartyDebtorFinancialAccount", nsmgr); - - if (payerPartyDebtorFinancialAccountNode == null) - { - continue; - } + if (!stream.CanRead) + { + throw new IllegalStreamException("Cannot read from stream"); + } + + XmlDocument doc = new XmlDocument(); + doc.Load(stream); + XmlNamespaceManager nsmgr = _GenerateNamespaceManagerFromNode(doc.DocumentElement); + + InvoiceDescriptor retval = new InvoiceDescriptor + { + IsTest = _nodeAsBool(doc.DocumentElement, "//rsm:ExchangedDocumentContext/ram:TestIndicator/udt:Indicator", nsmgr), + BusinessProcess = _nodeAsString(doc.DocumentElement, "//ram:BusinessProcessSpecifiedDocumentContextParameter/ram:ID", nsmgr), + Profile = default(Profile).FromString(_nodeAsString(doc.DocumentElement, "//ram:GuidelineSpecifiedDocumentContextParameter/ram:ID", nsmgr)), + Type = default(InvoiceType).FromString(_nodeAsString(doc.DocumentElement, "//rsm:ExchangedDocument/ram:TypeCode", nsmgr)), + InvoiceNo = _nodeAsString(doc.DocumentElement, "//rsm:ExchangedDocument/ram:ID", nsmgr), + InvoiceDate = _nodeAsDateTime(doc.DocumentElement, "//rsm:ExchangedDocument/ram:IssueDateTime/udt:DateTimeString", nsmgr) + }; + + foreach (XmlNode node in doc.SelectNodes("//rsm:ExchangedDocument/ram:IncludedNote", nsmgr)) + { + string content = _nodeAsString(node, ".//ram:Content", nsmgr); + string _subjectCode = _nodeAsString(node, ".//ram:SubjectCode", nsmgr); + SubjectCodes subjectCode = default(SubjectCodes).FromString(_subjectCode); + string _contentCode = _nodeAsString(node, ".//ram:ContentCode", nsmgr); + ContentCodes contentCode = default(ContentCodes).FromString(_contentCode); + retval.AddNote(content, subjectCode, contentCode); + } + + retval.ReferenceOrderNo = _nodeAsString(doc, "//ram:ApplicableHeaderTradeAgreement/ram:BuyerReference", nsmgr); + + retval.Seller = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty", nsmgr); + + if (doc.SelectSingleNode("//ram:SellerTradeParty/ram:URIUniversalCommunication", nsmgr) != null) + { + string id = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:URIUniversalCommunication/ram:URIID", nsmgr); + string schemeID = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:URIUniversalCommunication/ram:URIID/@schemeID", nsmgr); + + var eas = default(ElectronicAddressSchemeIdentifiers).FromString(schemeID); + + if (eas.HasValue) + retval.SetSellerElectronicAddress(id, eas.Value); + } + + foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:SpecifiedTaxRegistration", nsmgr)) + { + string id = _nodeAsString(node, ".//ram:ID", nsmgr); + string schemeID = _nodeAsString(node, ".//ram:ID/@schemeID", nsmgr); + + retval.AddSellerTaxRegistration(id, default(TaxRegistrationSchemeID).FromString(schemeID)); + } + + if (doc.SelectSingleNode("//ram:SellerTradeParty/ram:DefinedTradeContact", nsmgr) != null) + { + retval.SellerContact = new Contact() + { + Name = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:PersonName", nsmgr), + OrgUnit = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:DepartmentName", nsmgr), + PhoneNo = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber", nsmgr), + FaxNo = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:FaxUniversalCommunication/ram:CompleteNumber", nsmgr), + EmailAddress = _nodeAsString(doc.DocumentElement, "//ram:SellerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID", nsmgr) + }; + } - var _account = new BankAccount() - { - ID = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:ProprietaryID", nsmgr), - IBAN = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:IBANID", nsmgr), - Bankleitzahl = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:GermanBankleitzahlID", nsmgr), - BankName = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:Name", nsmgr), - }; - - var payerSpecifiedDebtorFinancialInstitutionNode = specifiedTradeSettlementPaymentMeansNode.SelectSingleNode("ram:PayerSpecifiedDebtorFinancialInstitution", nsmgr); - if (payerSpecifiedDebtorFinancialInstitutionNode != null) - _account.BIC = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:BICID", nsmgr); - - retval.DebitorBankAccounts.Add(_account); - } - - foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax", nsmgr)) - { - retval.AddApplicableTradeTax(_nodeAsDecimal(node, ".//ram:BasisAmount", nsmgr, 0).Value, - _nodeAsDecimal(node, ".//ram:RateApplicablePercent", nsmgr, 0).Value, - default(TaxTypes).FromString(_nodeAsString(node, ".//ram:TypeCode", nsmgr)), - default(TaxCategoryCodes).FromString(_nodeAsString(node, ".//ram:CategoryCode", nsmgr)), - 0, - default(TaxExemptionReasonCodes).FromString(_nodeAsString(node, ".//ram:ExemptionReasonCode", nsmgr)), - _nodeAsString(node, ".//ram:ExemptionReason", nsmgr)); - } - - foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge", nsmgr)) - { - retval.AddTradeAllowanceCharge(!_nodeAsBool(node, ".//ram:ChargeIndicator", nsmgr), // wichtig: das not (!) beachten - _nodeAsDecimal(node, ".//ram:BasisAmount", nsmgr), - retval.Currency, - _nodeAsDecimal(node, ".//ram:ActualAmount", nsmgr, 0).Value, - _nodeAsDecimal(node, ".//ram:CalculationPercent", nsmgr), - _nodeAsString(node, ".//ram:Reason", nsmgr), - default(TaxTypes).FromString(_nodeAsString(node, ".//ram:CategoryTradeTax/ram:TypeCode", nsmgr)), - default(TaxCategoryCodes).FromString(_nodeAsString(node, ".//ram:CategoryTradeTax/ram:CategoryCode", nsmgr)), - _nodeAsDecimal(node, ".//ram:CategoryTradeTax/ram:RateApplicablePercent", nsmgr, 0).Value); - } - - foreach (XmlNode node in doc.SelectNodes("//ram:SpecifiedLogisticsServiceCharge", nsmgr)) - { - retval.AddLogisticsServiceCharge(_nodeAsDecimal(node, ".//ram:AppliedAmount", nsmgr, 0).Value, - _nodeAsString(node, ".//ram:Description", nsmgr), - default(TaxTypes).FromString(_nodeAsString(node, ".//ram:AppliedTradeTax/ram:TypeCode", nsmgr)), - default(TaxCategoryCodes).FromString(_nodeAsString(node, ".//ram:AppliedTradeTax/ram:CategoryCode", nsmgr)), - _nodeAsDecimal(node, ".//ram:AppliedTradeTax/ram:RateApplicablePercent", nsmgr, 0).Value); - } - - retval.InvoiceReferencedDocument = new InvoiceReferencedDocument() - { - ID = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument/ram:IssuerAssignedID", nsmgr), - IssueDateTime = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument/ram:FormattedIssueDateTime", nsmgr) - }; - - retval.PaymentTerms = new PaymentTerms() - { - Description = _nodeAsString(doc.DocumentElement, "//ram:SpecifiedTradePaymentTerms/ram:Description", nsmgr), - DueDate = _nodeAsDateTime(doc.DocumentElement, "//ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime", nsmgr) - }; - - retval.LineTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:LineTotalAmount", nsmgr, 0).Value; - retval.ChargeTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:ChargeTotalAmount", nsmgr, null); - retval.AllowanceTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:AllowanceTotalAmount", nsmgr, null); - retval.TaxBasisAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxBasisTotalAmount", nsmgr, null); - retval.TaxTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxTotalAmount", nsmgr, 0).Value; - retval.GrandTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:GrandTotalAmount", nsmgr, 0).Value; - retval.RoundingAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:RoundingAmount", nsmgr, 0).Value; - retval.TotalPrepaidAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TotalPrepaidAmount", nsmgr, null); - retval.DuePayableAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:DuePayableAmount", nsmgr, 0).Value; - - foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:ReceivableSpecifiedTradeAccountingAccount", nsmgr)) - { - retval.ReceivableSpecifiedTradeAccountingAccounts.Add(new ReceivableSpecifiedTradeAccountingAccount() - { - TradeAccountID = _nodeAsString(node, ".//ram:ID", nsmgr), - TradeAccountTypeCode = (AccountingAccountTypeCodes)_nodeAsInt(node, ".//ram:TypeCode", nsmgr), - }); - } - - retval.OrderDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:BuyerOrderReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr); - retval.OrderNo = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:BuyerOrderReferencedDocument/ram:IssuerAssignedID", nsmgr); - - // Read SellerOrderReferencedDocument - if (doc.SelectSingleNode("//ram:ApplicableHeaderTradeAgreement/ram:SellerOrderReferencedDocument", nsmgr) != null) - { - retval.SellerOrderReferencedDocument = new SellerOrderReferencedDocument() - { - ID = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SellerOrderReferencedDocument/ram:IssuerAssignedID", nsmgr), - IssueDateTime = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SellerOrderReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr) - }; - } - - // Read ContractReferencedDocument - if (doc.SelectSingleNode("//ram:ApplicableHeaderTradeAgreement/ram:ContractReferencedDocument", nsmgr) != null) - { - retval.ContractReferencedDocument = new ContractReferencedDocument - { - ID = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID", nsmgr), - IssueDateTime = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:ContractReferencedDocument/ram:FormattedIssueDateTime", nsmgr) - }; - } + retval.Buyer = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty", nsmgr); - retval.SpecifiedProcuringProject = new SpecifiedProcuringProject - { - ID = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SpecifiedProcuringProject/ram:ID", nsmgr), - Name = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SpecifiedProcuringProject/ram:Name", nsmgr) - }; + if (doc.SelectSingleNode("//ram:BuyerTradeParty/ram:URIUniversalCommunication", nsmgr) != null) + { + string id = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:URIUniversalCommunication/ram:URIID", nsmgr); + string schemeID = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:URIUniversalCommunication/ram:URIID/@schemeID", nsmgr); - foreach (XmlNode node in doc.SelectNodes("//ram:IncludedSupplyChainTradeLineItem", nsmgr)) - { - retval.TradeLineItems.Add(_parseTradeLineItem(node, nsmgr)); - } + var eas = default(ElectronicAddressSchemeIdentifiers).FromString(schemeID); - return retval; - } // !Load() + if (eas.HasValue) + retval.SetBuyerElectronicAddress(id, eas.Value); + } + foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:SpecifiedTaxRegistration", nsmgr)) + { + string id = _nodeAsString(node, ".//ram:ID", nsmgr); + string schemeID = _nodeAsString(node, ".//ram:ID/@schemeID", nsmgr); - public override bool IsReadableByThisReaderVersion(Stream stream) - { - List validURIs = new List() + retval.AddBuyerTaxRegistration(id, default(TaxRegistrationSchemeID).FromString(schemeID)); + } + + if (doc.SelectSingleNode("//ram:BuyerTradeParty/ram:DefinedTradeContact", nsmgr) != null) + { + retval.BuyerContact = new Contact() + { + Name = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:PersonName", nsmgr), + OrgUnit = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:DepartmentName", nsmgr), + PhoneNo = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:TelephoneUniversalCommunication/ram:CompleteNumber", nsmgr), + FaxNo = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:FaxUniversalCommunication/ram:CompleteNumber", nsmgr), + EmailAddress = _nodeAsString(doc.DocumentElement, "//ram:BuyerTradeParty/ram:DefinedTradeContact/ram:EmailURIUniversalCommunication/ram:URIID", nsmgr) + }; + } + + + //Get all referenced and embedded documents (BG-24) + XmlNodeList referencedDocNodes = doc.SelectNodes(".//ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument", nsmgr); + foreach (XmlNode referenceNode in referencedDocNodes) + { + retval.AdditionalReferencedDocuments.Add(_getAdditionalReferencedDocument(referenceNode, nsmgr)); + } + + //------------------------------------------------- + // hzi: With old implementation only the first document has been read instead of all documents + //------------------------------------------------- + //if (doc.SelectSingleNode("//ram:AdditionalReferencedDocument", nsmgr) != null) + //{ + // string _issuerAssignedID = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:IssuerAssignedID", nsmgr); + // string _typeCode = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:TypeCode", nsmgr); + // string _referenceTypeCode = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:ReferenceTypeCode", nsmgr); + // string _name = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:Name", nsmgr); + // DateTime? _date = _nodeAsDateTime(doc.DocumentElement, "//ram:AdditionalReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr); + + // if (doc.SelectSingleNode("//ram:AdditionalReferencedDocument/ram:AttachmentBinaryObject", nsmgr) != null) + // { + // string _filename = _nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:AttachmentBinaryObject/@filename", nsmgr); + // byte[] data = Convert.FromBase64String(_nodeAsString(doc, "//ram:AdditionalReferencedDocument/ram:AttachmentBinaryObject", nsmgr)); + + // retval.AddAdditionalReferencedDocument(id: _issuerAssignedID, + // typeCode: default(AdditionalReferencedDocumentTypeCode).FromString(_typeCode), + // issueDateTime: _date, + // referenceTypeCode: default(ReferenceTypeCodes).FromString(_referenceTypeCode), + // name: _name, + // attachmentBinaryObject: data, + // filename: _filename); + // } + // else + // { + // retval.AddAdditionalReferencedDocument(id: _issuerAssignedID, + // typeCode: default(AdditionalReferencedDocumentTypeCode).FromString(_typeCode), + // issueDateTime: _date, + // referenceTypeCode: default(ReferenceTypeCodes).FromString(_referenceTypeCode), + // name: _name); + // } + //} + //------------------------------------------------- + + + retval.ShipTo = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ShipToTradeParty", nsmgr); + retval.ShipFrom = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ShipFromTradeParty", nsmgr); + retval.ActualDeliveryDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString", nsmgr); + + string _despatchAdviceNo = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:IssuerAssignedID", nsmgr); + DateTime? _despatchAdviceDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:FormattedIssueDateTime/udt:DateTimeString", nsmgr); + + if (!_despatchAdviceDate.HasValue) + { + _despatchAdviceDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DespatchAdviceReferencedDocument/ram:FormattedIssueDateTime", nsmgr); + } + + if (_despatchAdviceDate.HasValue || !String.IsNullOrWhiteSpace(_despatchAdviceNo)) + { + retval.DespatchAdviceReferencedDocument = new DespatchAdviceReferencedDocument() + { + ID = _despatchAdviceNo, + IssueDateTime = _despatchAdviceDate + }; + } + + string _deliveryNoteNo = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID", nsmgr); + DateTime? _deliveryNoteDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssueDateTime/udt:DateTimeString", nsmgr); + + if (!_deliveryNoteDate.HasValue) + { + _deliveryNoteDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssueDateTime", nsmgr); + } + + if (_deliveryNoteDate.HasValue || !String.IsNullOrWhiteSpace(_deliveryNoteNo)) + { + retval.DeliveryNoteReferencedDocument = new DeliveryNoteReferencedDocument() + { + ID = _deliveryNoteNo, + IssueDateTime = _deliveryNoteDate + }; + } + + retval.Invoicee = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:InvoiceeTradeParty", nsmgr); + retval.Payee = _nodeAsParty(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:PayeeTradeParty", nsmgr); + + retval.PaymentReference = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:PaymentReference", nsmgr); + retval.Currency = default(CurrencyCodes).FromString(_nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:InvoiceCurrencyCode", nsmgr)); + + // TODO: Multiple SpecifiedTradeSettlementPaymentMeans can exist for each account/institution (with different SEPA?) + PaymentMeans _tempPaymentMeans = new PaymentMeans() + { + TypeCode = default(PaymentMeansTypeCodes).FromString(_nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:TypeCode", nsmgr)), + Information = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:Information", nsmgr), + SEPACreditorIdentifier = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:CreditorReferenceID", nsmgr), + SEPAMandateReference = _nodeAsString(doc.DocumentElement, "//ram:SpecifiedTradePaymentTerms/ram:DirectDebitMandateID", nsmgr) + }; + + var financialCardId = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:ApplicableTradeSettlementFinancialCard/ram:ID", nsmgr); + var financialCardCardholderName = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:ApplicableTradeSettlementFinancialCard/ram:CardholderName", nsmgr); + + if (!string.IsNullOrWhiteSpace(financialCardId) || !string.IsNullOrWhiteSpace(financialCardCardholderName)) + { + _tempPaymentMeans.FinancialCard = new FinancialCard() + { + Id = financialCardId, + CardholderName = financialCardCardholderName + }; + } + + retval.PaymentMeans = _tempPaymentMeans; + + retval.BillingPeriodStart = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod/ram:StartDateTime", nsmgr); + retval.BillingPeriodEnd = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:BillingSpecifiedPeriod/ram:EndDateTime", nsmgr); + + XmlNodeList creditorFinancialAccountNodes = doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeePartyCreditorFinancialAccount", nsmgr); + XmlNodeList creditorFinancialInstitutions = doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans/ram:PayeeSpecifiedCreditorFinancialInstitution", nsmgr); + + int numberOfAccounts = creditorFinancialAccountNodes.Count > creditorFinancialInstitutions.Count ? creditorFinancialAccountNodes.Count : creditorFinancialInstitutions.Count; + for (int i = 0; i < numberOfAccounts; i++) + { + BankAccount _account = new BankAccount(); + retval.CreditorBankAccounts.Add(_account); + } + + for (int i = 0; i < creditorFinancialAccountNodes.Count; i++) + { + retval.CreditorBankAccounts[i].ID = _nodeAsString(creditorFinancialAccountNodes[i], ".//ram:ProprietaryID", nsmgr); + retval.CreditorBankAccounts[i].IBAN = _nodeAsString(creditorFinancialAccountNodes[i], ".//ram:IBANID", nsmgr); + retval.CreditorBankAccounts[i].Name = _nodeAsString(creditorFinancialAccountNodes[i], ".//ram:AccountName", nsmgr); + } + + for (int i = 0; i < creditorFinancialInstitutions.Count; i++) + { + retval.CreditorBankAccounts[i].BIC = _nodeAsString(creditorFinancialInstitutions[i], ".//ram:BICID", nsmgr); + retval.CreditorBankAccounts[i].Bankleitzahl = _nodeAsString(creditorFinancialInstitutions[i], ".//ram:GermanBankleitzahlID", nsmgr); + retval.CreditorBankAccounts[i].BankName = _nodeAsString(creditorFinancialInstitutions[i], ".//ram:Name", nsmgr); + } + + var specifiedTradeSettlementPaymentMeansNodes = doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeSettlementPaymentMeans", nsmgr); + + foreach (var specifiedTradeSettlementPaymentMeansNode in specifiedTradeSettlementPaymentMeansNodes.OfType()) + { + var payerPartyDebtorFinancialAccountNode = specifiedTradeSettlementPaymentMeansNode.SelectSingleNode("ram:PayerPartyDebtorFinancialAccount", nsmgr); + + if (payerPartyDebtorFinancialAccountNode == null) + { + continue; + } + + var _account = new BankAccount() + { + ID = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:ProprietaryID", nsmgr), + IBAN = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:IBANID", nsmgr), + Bankleitzahl = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:GermanBankleitzahlID", nsmgr), + BankName = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:Name", nsmgr), + }; + + var payerSpecifiedDebtorFinancialInstitutionNode = specifiedTradeSettlementPaymentMeansNode.SelectSingleNode("ram:PayerSpecifiedDebtorFinancialInstitution", nsmgr); + if (payerSpecifiedDebtorFinancialInstitutionNode != null) + _account.BIC = _nodeAsString(payerPartyDebtorFinancialAccountNode, ".//ram:BICID", nsmgr); + + retval.DebitorBankAccounts.Add(_account); + } + + foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:ApplicableTradeTax", nsmgr)) + { + retval.AddApplicableTradeTax(_nodeAsDecimal(node, ".//ram:BasisAmount", nsmgr, 0).Value, + _nodeAsDecimal(node, ".//ram:RateApplicablePercent", nsmgr, 0).Value, + default(TaxTypes).FromString(_nodeAsString(node, ".//ram:TypeCode", nsmgr)), + default(TaxCategoryCodes).FromString(_nodeAsString(node, ".//ram:CategoryCode", nsmgr)), + 0, + default(TaxExemptionReasonCodes).FromString(_nodeAsString(node, ".//ram:ExemptionReasonCode", nsmgr)), + _nodeAsString(node, ".//ram:ExemptionReason", nsmgr)); + } + + foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:SpecifiedTradeAllowanceCharge", nsmgr)) + { + retval.AddTradeAllowanceCharge(!_nodeAsBool(node, ".//ram:ChargeIndicator", nsmgr), // wichtig: das not (!) beachten + _nodeAsDecimal(node, ".//ram:BasisAmount", nsmgr), + retval.Currency, + _nodeAsDecimal(node, ".//ram:ActualAmount", nsmgr, 0).Value, + _nodeAsDecimal(node, ".//ram:CalculationPercent", nsmgr), + _nodeAsString(node, ".//ram:Reason", nsmgr), + default(TaxTypes).FromString(_nodeAsString(node, ".//ram:CategoryTradeTax/ram:TypeCode", nsmgr)), + default(TaxCategoryCodes).FromString(_nodeAsString(node, ".//ram:CategoryTradeTax/ram:CategoryCode", nsmgr)), + _nodeAsDecimal(node, ".//ram:CategoryTradeTax/ram:RateApplicablePercent", nsmgr, 0).Value); + } + + foreach (XmlNode node in doc.SelectNodes("//ram:SpecifiedLogisticsServiceCharge", nsmgr)) + { + retval.AddLogisticsServiceCharge(_nodeAsDecimal(node, ".//ram:AppliedAmount", nsmgr, 0).Value, + _nodeAsString(node, ".//ram:Description", nsmgr), + default(TaxTypes).FromString(_nodeAsString(node, ".//ram:AppliedTradeTax/ram:TypeCode", nsmgr)), + default(TaxCategoryCodes).FromString(_nodeAsString(node, ".//ram:AppliedTradeTax/ram:CategoryCode", nsmgr)), + _nodeAsDecimal(node, ".//ram:AppliedTradeTax/ram:RateApplicablePercent", nsmgr, 0).Value); + } + + retval.InvoiceReferencedDocument = new InvoiceReferencedDocument() + { + ID = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument/ram:IssuerAssignedID", nsmgr), + IssueDateTime = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeSettlement/ram:InvoiceReferencedDocument/ram:FormattedIssueDateTime", nsmgr) + }; + + retval.PaymentTerms = new PaymentTerms() + { + Description = _nodeAsString(doc.DocumentElement, "//ram:SpecifiedTradePaymentTerms/ram:Description", nsmgr), + DueDate = _nodeAsDateTime(doc.DocumentElement, "//ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime", nsmgr) + }; + + retval.LineTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:LineTotalAmount", nsmgr, 0).Value; + retval.ChargeTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:ChargeTotalAmount", nsmgr, null); + retval.AllowanceTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:AllowanceTotalAmount", nsmgr, null); + retval.TaxBasisAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxBasisTotalAmount", nsmgr, null); + retval.TaxTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TaxTotalAmount", nsmgr, 0).Value; + retval.GrandTotalAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:GrandTotalAmount", nsmgr, 0).Value; + retval.RoundingAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:RoundingAmount", nsmgr, 0).Value; + retval.TotalPrepaidAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:TotalPrepaidAmount", nsmgr, null); + retval.DuePayableAmount = _nodeAsDecimal(doc.DocumentElement, "//ram:SpecifiedTradeSettlementHeaderMonetarySummation/ram:DuePayableAmount", nsmgr, 0).Value; + + foreach (XmlNode node in doc.SelectNodes("//ram:ApplicableHeaderTradeSettlement/ram:ReceivableSpecifiedTradeAccountingAccount", nsmgr)) + { + retval.ReceivableSpecifiedTradeAccountingAccounts.Add(new ReceivableSpecifiedTradeAccountingAccount() + { + TradeAccountID = _nodeAsString(node, ".//ram:ID", nsmgr), + TradeAccountTypeCode = (AccountingAccountTypeCodes)_nodeAsInt(node, ".//ram:TypeCode", nsmgr), + }); + } + + retval.OrderDate = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:BuyerOrderReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr); + retval.OrderNo = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:BuyerOrderReferencedDocument/ram:IssuerAssignedID", nsmgr); + + // Read SellerOrderReferencedDocument + if (doc.SelectSingleNode("//ram:ApplicableHeaderTradeAgreement/ram:SellerOrderReferencedDocument", nsmgr) != null) + { + retval.SellerOrderReferencedDocument = new SellerOrderReferencedDocument() + { + ID = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SellerOrderReferencedDocument/ram:IssuerAssignedID", nsmgr), + IssueDateTime = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SellerOrderReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr) + }; + } + + // Read ContractReferencedDocument + if (doc.SelectSingleNode("//ram:ApplicableHeaderTradeAgreement/ram:ContractReferencedDocument", nsmgr) != null) + { + retval.ContractReferencedDocument = new ContractReferencedDocument + { + ID = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID", nsmgr), + IssueDateTime = _nodeAsDateTime(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:ContractReferencedDocument/ram:FormattedIssueDateTime", nsmgr) + }; + } + + retval.SpecifiedProcuringProject = new SpecifiedProcuringProject + { + ID = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SpecifiedProcuringProject/ram:ID", nsmgr), + Name = _nodeAsString(doc.DocumentElement, "//ram:ApplicableHeaderTradeAgreement/ram:SpecifiedProcuringProject/ram:Name", nsmgr) + }; + + foreach (XmlNode node in doc.SelectNodes("//ram:IncludedSupplyChainTradeLineItem", nsmgr)) + { + retval.TradeLineItems.Add(_parseTradeLineItem(node, nsmgr)); + } + + return retval; + } // !Load() + + + public override bool IsReadableByThisReaderVersion(Stream stream) + { + List validURIs = new List() { "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended", // Factur-X 1.03 EXTENDED "urn:cen.eu:en16931:2017", // Profil EN 16931 (COMFORT) @@ -426,250 +421,250 @@ public override bool IsReadableByThisReaderVersion(Stream stream) "urn.cpro.gouv.fr:1p0:ereporting" //Factur-X E-reporting }; - return _IsReadableByThisReaderVersion(stream, validURIs); - } // !IsReadableByThisReaderVersion() + return _IsReadableByThisReaderVersion(stream, validURIs); + } // !IsReadableByThisReaderVersion() - private static TradeLineItem _parseTradeLineItem(XmlNode tradeLineItem, XmlNamespaceManager nsmgr = null) - { - if (tradeLineItem == null) - { - return null; - } - - TradeLineItem item = new TradeLineItem() - { - GlobalID = new GlobalID(default(GlobalIDSchemeIdentifiers).FromString(_nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:GlobalID/@schemeID", nsmgr)), - _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:GlobalID", nsmgr)), - SellerAssignedID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:SellerAssignedID", nsmgr), - BuyerAssignedID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:BuyerAssignedID", nsmgr), - Name = _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:Name", nsmgr), - Description = _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:Description", nsmgr), - UnitQuantity = _nodeAsDecimal(tradeLineItem, ".//ram:BasisQuantity", nsmgr, 1), - BilledQuantity = _nodeAsDecimal(tradeLineItem, ".//ram:BilledQuantity", nsmgr, 0).Value, - LineTotalAmount = _nodeAsDecimal(tradeLineItem, ".//ram:LineTotalAmount", nsmgr, 0), - TaxCategoryCode = default(TaxCategoryCodes).FromString(_nodeAsString(tradeLineItem, ".//ram:ApplicableTradeTax/ram:CategoryCode", nsmgr)), - TaxType = default(TaxTypes).FromString(_nodeAsString(tradeLineItem, ".//ram:ApplicableTradeTax/ram:TypeCode", nsmgr)), - TaxPercent = _nodeAsDecimal(tradeLineItem, ".//ram:ApplicableTradeTax/ram:RateApplicablePercent", nsmgr, 0).Value, - NetUnitPrice = _nodeAsDecimal(tradeLineItem, ".//ram:NetPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value, - GrossUnitPrice = _nodeAsDecimal(tradeLineItem, ".//ram:GrossPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value, - UnitCode = default(QuantityCodes).FromString(_nodeAsString(tradeLineItem, ".//ram:BasisQuantity/@unitCode", nsmgr)), - BillingPeriodStart = _nodeAsDateTime(tradeLineItem, ".//ram:BillingSpecifiedPeriod/ram:StartDateTime/udt:DateTimeString", nsmgr), - BillingPeriodEnd = _nodeAsDateTime(tradeLineItem, ".//ram:BillingSpecifiedPeriod/ram:EndDateTime/udt:DateTimeString", nsmgr), - }; - - if (tradeLineItem.SelectNodes(".//ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic", nsmgr) != null) - { - foreach (XmlNode applicableProductCharacteristic in tradeLineItem.SelectNodes(".//ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic", nsmgr)) + private static TradeLineItem _parseTradeLineItem(XmlNode tradeLineItem, XmlNamespaceManager nsmgr = null) { - item.ApplicableProductCharacteristics.Add(new ApplicableProductCharacteristic() - { - Description = _nodeAsString(applicableProductCharacteristic, ".//ram:Description", nsmgr), - Value = _nodeAsString(applicableProductCharacteristic, ".//ram:Value", nsmgr), - }); - } - } + if (tradeLineItem == null) + { + return null; + } + + TradeLineItem item = new TradeLineItem() + { + GlobalID = new GlobalID(default(GlobalIDSchemeIdentifiers).FromString(_nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:GlobalID/@schemeID", nsmgr)), + _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:GlobalID", nsmgr)), + SellerAssignedID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:SellerAssignedID", nsmgr), + BuyerAssignedID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:BuyerAssignedID", nsmgr), + Name = _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:Name", nsmgr), + Description = _nodeAsString(tradeLineItem, ".//ram:SpecifiedTradeProduct/ram:Description", nsmgr), + UnitQuantity = _nodeAsDecimal(tradeLineItem, ".//ram:BasisQuantity", nsmgr, 1), + BilledQuantity = _nodeAsDecimal(tradeLineItem, ".//ram:BilledQuantity", nsmgr, 0).Value, + LineTotalAmount = _nodeAsDecimal(tradeLineItem, ".//ram:LineTotalAmount", nsmgr, 0), + TaxCategoryCode = default(TaxCategoryCodes).FromString(_nodeAsString(tradeLineItem, ".//ram:ApplicableTradeTax/ram:CategoryCode", nsmgr)), + TaxType = default(TaxTypes).FromString(_nodeAsString(tradeLineItem, ".//ram:ApplicableTradeTax/ram:TypeCode", nsmgr)), + TaxPercent = _nodeAsDecimal(tradeLineItem, ".//ram:ApplicableTradeTax/ram:RateApplicablePercent", nsmgr, 0).Value, + NetUnitPrice = _nodeAsDecimal(tradeLineItem, ".//ram:NetPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value, + GrossUnitPrice = _nodeAsDecimal(tradeLineItem, ".//ram:GrossPriceProductTradePrice/ram:ChargeAmount", nsmgr, 0).Value, + UnitCode = default(QuantityCodes).FromString(_nodeAsString(tradeLineItem, ".//ram:BasisQuantity/@unitCode", nsmgr)), + BillingPeriodStart = _nodeAsDateTime(tradeLineItem, ".//ram:BillingSpecifiedPeriod/ram:StartDateTime/udt:DateTimeString", nsmgr), + BillingPeriodEnd = _nodeAsDateTime(tradeLineItem, ".//ram:BillingSpecifiedPeriod/ram:EndDateTime/udt:DateTimeString", nsmgr), + }; + + if (tradeLineItem.SelectNodes(".//ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic", nsmgr) != null) + { + foreach (XmlNode applicableProductCharacteristic in tradeLineItem.SelectNodes(".//ram:SpecifiedTradeProduct/ram:ApplicableProductCharacteristic", nsmgr)) + { + item.ApplicableProductCharacteristics.Add(new ApplicableProductCharacteristic() + { + Description = _nodeAsString(applicableProductCharacteristic, ".//ram:Description", nsmgr), + Value = _nodeAsString(applicableProductCharacteristic, ".//ram:Value", nsmgr), + }); + } + } + + if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument", nsmgr) != null) + { + item.BuyerOrderReferencedDocument = new BuyerOrderReferencedDocument() + { + ID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument/ram:IssuerAssignedID", nsmgr), + IssueDateTime = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr) + }; + } + + if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument", nsmgr) != null) + { + item.ContractReferencedDocument = new ContractReferencedDocument() + { + ID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID", nsmgr), + IssueDateTime = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr) + }; + } - if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument", nsmgr) != null) - { - item.BuyerOrderReferencedDocument = new BuyerOrderReferencedDocument() + if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeSettlement", nsmgr) != null) + { + XmlNodeList LineTradeSettlementNodes = tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeSettlement", nsmgr).ChildNodes; + foreach (XmlNode LineTradeSettlementNode in LineTradeSettlementNodes) + { + switch (LineTradeSettlementNode.Name) + { + case "ram:ApplicableTradeTax": + //TODO + break; + case "ram:BillingSpecifiedPeriod": + //TODO + break; + case "ram:SpecifiedTradeAllowanceCharge": + //TODO + break; + case "ram:SpecifiedTradeSettlementLineMonetarySummation": + //TODO + break; + case "ram:AdditionalReferencedDocument": + //TODO + break; + case "ram:ReceivableSpecifiedTradeAccountingAccount": + item.ReceivableSpecifiedTradeAccountingAccounts.Add(new ReceivableSpecifiedTradeAccountingAccount() + { + TradeAccountID = _nodeAsString(LineTradeSettlementNode, "./ram:ID", nsmgr), + TradeAccountTypeCode = (AccountingAccountTypeCodes)_nodeAsInt(LineTradeSettlementNode, ".//ram:TypeCode", nsmgr) + }); + break; + } + } + } + + if (tradeLineItem.SelectSingleNode(".//ram:AssociatedDocumentLineDocument", nsmgr) != null) + { + item.AssociatedDocument = new AssociatedDocument(_nodeAsString(tradeLineItem, ".//ram:AssociatedDocumentLineDocument/ram:LineID", nsmgr)); + + XmlNodeList noteNodes = tradeLineItem.SelectNodes(".//ram:AssociatedDocumentLineDocument/ram:IncludedNote", nsmgr); + foreach (XmlNode noteNode in noteNodes) + { + item.AssociatedDocument.Notes.Add(new Note( + content: _nodeAsString(noteNode, ".//ram:Content", nsmgr), + subjectCode: default(SubjectCodes).FromString(_nodeAsString(noteNode, ".//ram:SubjectCode", nsmgr)), + contentCode: default(ContentCodes).FromString(_nodeAsString(noteNode, ".//ram:ContentCode", nsmgr)) + )); + } + } + + XmlNodeList appliedTradeAllowanceChargeNodes = tradeLineItem.SelectNodes(".//ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:AppliedTradeAllowanceCharge", nsmgr); + foreach (XmlNode appliedTradeAllowanceChargeNode in appliedTradeAllowanceChargeNodes) + { + bool chargeIndicator = _nodeAsBool(appliedTradeAllowanceChargeNode, "./ram:ChargeIndicator/udt:Indicator", nsmgr); + decimal? basisAmount = _nodeAsDecimal(appliedTradeAllowanceChargeNode, "./ram:BasisAmount", nsmgr, null); + string basisAmountCurrency = _nodeAsString(appliedTradeAllowanceChargeNode, "./ram:BasisAmount/@currencyID", nsmgr); + decimal actualAmount = _nodeAsDecimal(appliedTradeAllowanceChargeNode, "./ram:ActualAmount", nsmgr, 0).Value; + string actualAmountCurrency = _nodeAsString(appliedTradeAllowanceChargeNode, "./ram:ActualAmount/@currencyID", nsmgr); + string reason = _nodeAsString(appliedTradeAllowanceChargeNode, "./ram:Reason", nsmgr); + decimal? chargePercentage = _nodeAsDecimal(appliedTradeAllowanceChargeNode, "./ram:CalculationPercent", nsmgr, null); + + item.AddTradeAllowanceCharge(!chargeIndicator, // wichtig: das not (!) beachten + default(CurrencyCodes).FromString(basisAmountCurrency), + basisAmount, + actualAmount, + chargePercentage, + reason); + } + + if (item.UnitCode == QuantityCodes.Unknown) + { + // UnitCode alternativ aus BilledQuantity extrahieren + item.UnitCode = default(QuantityCodes).FromString(_nodeAsString(tradeLineItem, ".//ram:BilledQuantity/@unitCode", nsmgr)); + } + + if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID", nsmgr) != null) + { + item.DeliveryNoteReferencedDocument = new DeliveryNoteReferencedDocument() + { + ID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedLineTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID", nsmgr), + IssueDateTime = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr), + }; + } + + if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime", nsmgr) != null) + { + item.ActualDeliveryDate = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString", nsmgr); + } + + //if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID", nsmgr) != null) + //{ + // item.ContractReferencedDocument = new ContractReferencedDocument() + // { + // ID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID", nsmgr), + // IssueDateTime = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr), + // }; + //} + + //Get all referenced AND embedded documents + XmlNodeList referenceNodes = tradeLineItem.SelectNodes(".//ram:SpecifiedLineTradeAgreement/ram:AdditionalReferencedDocument", nsmgr); + foreach (XmlNode referenceNode in referenceNodes) + { + item.AdditionalReferencedDocuments.Add(_getAdditionalReferencedDocument(referenceNode, nsmgr)); + } + + return item; + } // !_parseTradeLineItem() + + + private static LegalOrganization _nodeAsLegalOrganization(XmlNode baseNode, string xpath, XmlNamespaceManager nsmgr = null) { - ID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument/ram:IssuerAssignedID", nsmgr), - IssueDateTime = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:BuyerOrderReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr) - }; - } - - if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument", nsmgr) != null) - { - item.ContractReferencedDocument = new ContractReferencedDocument() + if (baseNode == null) + return null; + XmlNode node = baseNode.SelectSingleNode(xpath, nsmgr); + if (node == null) + return null; + var retval = new LegalOrganization() + { + ID = new GlobalID(default(GlobalIDSchemeIdentifiers).FromString(_nodeAsString(node, "ram:ID/@schemeID", nsmgr)), + _nodeAsString(node, "ram:ID", nsmgr)), + TradingBusinessName = _nodeAsString(node, "ram:TradingBusinessName", nsmgr), + }; + return retval; + } + private static Party _nodeAsParty(XmlNode baseNode, string xpath, XmlNamespaceManager nsmgr = null) { - ID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID", nsmgr), - IssueDateTime = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr) - }; - } - - if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeSettlement", nsmgr) != null) - { - XmlNodeList LineTradeSettlementNodes = tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeSettlement", nsmgr).ChildNodes; - foreach (XmlNode LineTradeSettlementNode in LineTradeSettlementNodes) + if (baseNode == null) + { + return null; + } + + XmlNode node = baseNode.SelectSingleNode(xpath, nsmgr); + if (node == null) + { + return null; + } + + Party retval = new Party() + { + ID = new GlobalID(default(GlobalIDSchemeIdentifiers).FromString(_nodeAsString(node, "ram:ID/@schemeID", nsmgr)), + _nodeAsString(node, "ram:ID", nsmgr)), + GlobalID = new GlobalID(default(GlobalIDSchemeIdentifiers).FromString(_nodeAsString(node, "ram:GlobalID/@schemeID", nsmgr)), + _nodeAsString(node, "ram:GlobalID", nsmgr)), + Name = _nodeAsString(node, "ram:Name", nsmgr), + Postcode = _nodeAsString(node, "ram:PostalTradeAddress/ram:PostcodeCode", nsmgr), + City = _nodeAsString(node, "ram:PostalTradeAddress/ram:CityName", nsmgr), + Country = default(CountryCodes).FromString(_nodeAsString(node, "ram:PostalTradeAddress/ram:CountryID", nsmgr)), + SpecifiedLegalOrganization = _nodeAsLegalOrganization(node, "ram:SpecifiedLegalOrganization", nsmgr), + }; + + string lineOne = _nodeAsString(node, "ram:PostalTradeAddress/ram:LineOne", nsmgr); + string lineTwo = _nodeAsString(node, "ram:PostalTradeAddress/ram:LineTwo", nsmgr); + + if (!String.IsNullOrWhiteSpace(lineTwo)) + { + retval.ContactName = lineOne; + retval.Street = lineTwo; + } + else + { + retval.Street = lineOne; + retval.ContactName = null; + } + + retval.AddressLine3 = _nodeAsString(node, "ram:PostalTradeAddress/ram:LineThree", nsmgr); + retval.CountrySubdivisionName = _nodeAsString(node, "ram:PostalTradeAddress/ram:CountrySubDivisionName", nsmgr); + + return retval; + } // !_nodeAsParty() + + private static AdditionalReferencedDocument _getAdditionalReferencedDocument(XmlNode a_oXmlNode, XmlNamespaceManager a_nsmgr) { - switch (LineTradeSettlementNode.Name) - { - case "ram:ApplicableTradeTax": - //TODO - break; - case "ram:BillingSpecifiedPeriod": - //TODO - break; - case "ram:SpecifiedTradeAllowanceCharge": - //TODO - break; - case "ram:SpecifiedTradeSettlementLineMonetarySummation": - //TODO - break; - case "ram:AdditionalReferencedDocument": - //TODO - break; - case "ram:ReceivableSpecifiedTradeAccountingAccount": - item.ReceivableSpecifiedTradeAccountingAccounts.Add(new ReceivableSpecifiedTradeAccountingAccount() - { - TradeAccountID = _nodeAsString(LineTradeSettlementNode, "./ram:ID", nsmgr), - TradeAccountTypeCode = (AccountingAccountTypeCodes)_nodeAsInt(LineTradeSettlementNode, ".//ram:TypeCode", nsmgr) - }); - break; - } + string strBase64BinaryData = _nodeAsString(a_oXmlNode, "ram:AttachmentBinaryObject", a_nsmgr); + return new AdditionalReferencedDocument + { + ID = _nodeAsString(a_oXmlNode, "ram:IssuerAssignedID", a_nsmgr), + TypeCode = default(AdditionalReferencedDocumentTypeCode).FromString(_nodeAsString(a_oXmlNode, "ram:TypeCode", a_nsmgr)), + Name = _nodeAsString(a_oXmlNode, "ram:Name", a_nsmgr), + IssueDateTime = _nodeAsDateTime(a_oXmlNode, "ram:FormattedIssueDateTime/qdt:DateTimeString", a_nsmgr), + AttachmentBinaryObject = !string.IsNullOrWhiteSpace(strBase64BinaryData) ? Convert.FromBase64String(strBase64BinaryData) : null, + Filename = _nodeAsString(a_oXmlNode, "ram:AttachmentBinaryObject/@filename", a_nsmgr), + ReferenceTypeCode = default(ReferenceTypeCodes).FromString(_nodeAsString(a_oXmlNode, "ram:ReferenceTypeCode", a_nsmgr)) + }; } - } - if (tradeLineItem.SelectSingleNode(".//ram:AssociatedDocumentLineDocument", nsmgr) != null) - { - item.AssociatedDocument = new AssociatedDocument(_nodeAsString(tradeLineItem, ".//ram:AssociatedDocumentLineDocument/ram:LineID", nsmgr)); - - XmlNodeList noteNodes = tradeLineItem.SelectNodes(".//ram:AssociatedDocumentLineDocument/ram:IncludedNote", nsmgr); - foreach (XmlNode noteNode in noteNodes) - { - item.AssociatedDocument.Notes.Add(new Note( - content: _nodeAsString(noteNode, ".//ram:Content", nsmgr), - subjectCode: default(SubjectCodes).FromString(_nodeAsString(noteNode, ".//ram:SubjectCode", nsmgr)), - contentCode: default(ContentCodes).FromString(_nodeAsString(noteNode, ".//ram:ContentCode", nsmgr)) - )); - } - } - - XmlNodeList appliedTradeAllowanceChargeNodes = tradeLineItem.SelectNodes(".//ram:SpecifiedLineTradeAgreement/ram:GrossPriceProductTradePrice/ram:AppliedTradeAllowanceCharge", nsmgr); - foreach (XmlNode appliedTradeAllowanceChargeNode in appliedTradeAllowanceChargeNodes) - { - bool chargeIndicator = _nodeAsBool(appliedTradeAllowanceChargeNode, "./ram:ChargeIndicator/udt:Indicator", nsmgr); - decimal? basisAmount = _nodeAsDecimal(appliedTradeAllowanceChargeNode, "./ram:BasisAmount", nsmgr, null); - string basisAmountCurrency = _nodeAsString(appliedTradeAllowanceChargeNode, "./ram:BasisAmount/@currencyID", nsmgr); - decimal actualAmount = _nodeAsDecimal(appliedTradeAllowanceChargeNode, "./ram:ActualAmount", nsmgr, 0).Value; - string actualAmountCurrency = _nodeAsString(appliedTradeAllowanceChargeNode, "./ram:ActualAmount/@currencyID", nsmgr); - string reason = _nodeAsString(appliedTradeAllowanceChargeNode, "./ram:Reason", nsmgr); - decimal? chargePercentage = _nodeAsDecimal(appliedTradeAllowanceChargeNode, "./ram:CalculationPercent", nsmgr, null); - - item.AddTradeAllowanceCharge(!chargeIndicator, // wichtig: das not (!) beachten - default(CurrencyCodes).FromString(basisAmountCurrency), - basisAmount, - actualAmount, - chargePercentage, - reason); - } - - if (item.UnitCode == QuantityCodes.Unknown) - { - // UnitCode alternativ aus BilledQuantity extrahieren - item.UnitCode = default(QuantityCodes).FromString(_nodeAsString(tradeLineItem, ".//ram:BilledQuantity/@unitCode", nsmgr)); - } - - if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID", nsmgr) != null) - { - item.DeliveryNoteReferencedDocument = new DeliveryNoteReferencedDocument() - { - ID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedLineTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:IssuerAssignedID", nsmgr), - IssueDateTime = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeDelivery/ram:DeliveryNoteReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr), - }; - } - - if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime", nsmgr) != null) - { - item.ActualDeliveryDate = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeDelivery/ram:ActualDeliverySupplyChainEvent/ram:OccurrenceDateTime/udt:DateTimeString", nsmgr); - } - - //if (tradeLineItem.SelectSingleNode(".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID", nsmgr) != null) - //{ - // item.ContractReferencedDocument = new ContractReferencedDocument() - // { - // ID = _nodeAsString(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:IssuerAssignedID", nsmgr), - // IssueDateTime = _nodeAsDateTime(tradeLineItem, ".//ram:SpecifiedLineTradeAgreement/ram:ContractReferencedDocument/ram:FormattedIssueDateTime/qdt:DateTimeString", nsmgr), - // }; - //} - - //Get all referenced AND embedded documents - XmlNodeList referenceNodes = tradeLineItem.SelectNodes(".//ram:SpecifiedLineTradeAgreement/ram:AdditionalReferencedDocument", nsmgr); - foreach (XmlNode referenceNode in referenceNodes) - { - item.AdditionalReferencedDocuments.Add(_getAdditionalReferencedDocument(referenceNode, nsmgr)); - } - - return item; - } // !_parseTradeLineItem() - - - private static LegalOrganization _nodeAsLegalOrganization(XmlNode baseNode, string xpath, XmlNamespaceManager nsmgr = null) - { - if (baseNode == null) - return null; - XmlNode node = baseNode.SelectSingleNode(xpath, nsmgr); - if (node == null) - return null; - var retval = new LegalOrganization() - { - ID = new GlobalID(default(GlobalIDSchemeIdentifiers).FromString(_nodeAsString(node, "ram:ID/@schemeID", nsmgr)), - _nodeAsString(node, "ram:ID", nsmgr)), - TradingBusinessName = _nodeAsString(node, "ram:TradingBusinessName", nsmgr), - }; - return retval; } - private static Party _nodeAsParty(XmlNode baseNode, string xpath, XmlNamespaceManager nsmgr = null) - { - if (baseNode == null) - { - return null; - } - - XmlNode node = baseNode.SelectSingleNode(xpath, nsmgr); - if (node == null) - { - return null; - } - - Party retval = new Party() - { - ID = new GlobalID(default(GlobalIDSchemeIdentifiers).FromString(_nodeAsString(node, "ram:ID/@schemeID", nsmgr)), - _nodeAsString(node, "ram:ID", nsmgr)), - GlobalID = new GlobalID(default(GlobalIDSchemeIdentifiers).FromString(_nodeAsString(node, "ram:GlobalID/@schemeID", nsmgr)), - _nodeAsString(node, "ram:GlobalID", nsmgr)), - Name = _nodeAsString(node, "ram:Name", nsmgr), - Postcode = _nodeAsString(node, "ram:PostalTradeAddress/ram:PostcodeCode", nsmgr), - City = _nodeAsString(node, "ram:PostalTradeAddress/ram:CityName", nsmgr), - Country = default(CountryCodes).FromString(_nodeAsString(node, "ram:PostalTradeAddress/ram:CountryID", nsmgr)), - SpecifiedLegalOrganization = _nodeAsLegalOrganization(node, "ram:SpecifiedLegalOrganization", nsmgr), - }; - - string lineOne = _nodeAsString(node, "ram:PostalTradeAddress/ram:LineOne", nsmgr); - string lineTwo = _nodeAsString(node, "ram:PostalTradeAddress/ram:LineTwo", nsmgr); - - if (!String.IsNullOrWhiteSpace(lineTwo)) - { - retval.ContactName = lineOne; - retval.Street = lineTwo; - } - else - { - retval.Street = lineOne; - retval.ContactName = null; - } - - retval.AddressLine3 = _nodeAsString(node, "ram:PostalTradeAddress/ram:LineThree", nsmgr); - retval.CountrySubdivisionName = _nodeAsString(node, "ram:PostalTradeAddress/ram:CountrySubDivisionName", nsmgr); - - return retval; - } // !_nodeAsParty() - - private static AdditionalReferencedDocument _getAdditionalReferencedDocument(XmlNode a_oXmlNode, XmlNamespaceManager a_nsmgr) - { - string strBase64BinaryData = _nodeAsString(a_oXmlNode, "ram:AttachmentBinaryObject", a_nsmgr); - return new AdditionalReferencedDocument - { - ID = _nodeAsString(a_oXmlNode, "ram:IssuerAssignedID", a_nsmgr), - TypeCode = default(AdditionalReferencedDocumentTypeCode).FromString(_nodeAsString(a_oXmlNode, "ram:TypeCode", a_nsmgr)), - Name = _nodeAsString(a_oXmlNode, "ram:Name", a_nsmgr), - IssueDateTime = _nodeAsDateTime(a_oXmlNode, "ram:FormattedIssueDateTime/qdt:DateTimeString", a_nsmgr), - AttachmentBinaryObject = !string.IsNullOrWhiteSpace(strBase64BinaryData) ? Convert.FromBase64String(strBase64BinaryData) : null, - Filename = _nodeAsString(a_oXmlNode, "ram:AttachmentBinaryObject/@filename", a_nsmgr), - ReferenceTypeCode = default(ReferenceTypeCodes).FromString(_nodeAsString(a_oXmlNode, "ram:ReferenceTypeCode", a_nsmgr)) - }; - } - - } }