stephanstapel / ZUGFeRD-csharp

C# assembly for creating and reading ZUGFeRD invoices
Apache License 2.0
199 stars 108 forks source link

AdditionalReferencedDocument should be available in XRechnung profile #189

Closed alex-becker-startp closed 1 year ago

alex-becker-startp commented 2 years ago

The AdditionalReferencedDocument is restricted to profiles Comfort and Extended. I think it should be available in profile XRechnung, too. A XRechnung with embedded PDF as AdditionalReferencedDocument passes the KoSIT Validator without issues.

InvoiceDescriptor21Writer.cs#L546: Writer.WriteStartElement("ram:AdditionalReferencedDocument", Profile.Comfort | Profile.Extended);

patrickkurras commented 2 years ago

I think so too. At the moment this does not write any file to the XML file. You even wrote a test for it "TestInvoiceWithAttachment()", which is also successful, but the resulting XML does not contain the attached file.

I am also honestly sure that this has worked before in a previous version.

Would be great if you could change this.

stephanstapel commented 2 years ago

Good point. Essentially, the test was wrong. It needs to be checked if there is any reference document at all. I will take care of this. Could you help me on two questions:

stephanstapel commented 2 years ago

Hello @alex-becker-startp, could you help me on the two questions mentioned above to complete this fix? Thanks a lot in advance!

alex-becker-startp commented 2 years ago

Hello @stephanstapel ,

sorry, but I am not very deep into this topic and my focus is on XRechnung only. So sadly I am not able to answer your questions. In the XRechnung specs I did not find any hint for receferenced documents on trade line items. But it is clear for me that invoice-level <AdditionalReferencedDocument> is conform to XRechnung, details why I think so see below. From this doc BG-24 should be possible multiple times (0..*) but if I remember correct, test documents where I manually added more then one ref doc were rejected by the validator.

From Spezifikation XRechnung, Standard und Extension v.2.2.0 in der Fassung vom 27.01.2022, page 38:

11.2. Gruppe ADDITIONAL SUPPORTING DOCUMENTS

Dieses Informationselement (ID: BG-24, Anz. 0..*) ist ein direkter Bestandteil des Wurzelelements INVOICE, siehe Abschnitt 11.1: Das Wurzelelement INVOICE.

Eine Gruppe von Informationselementen mit Informationen über rechnungsbegründende Unterlagen, die Belege für die in der Rechnung gestellten Ansprüche enthalten.

Anmerkung: Die Gruppe kann verwendet werden, um auf eine dem Erwerber bekannte Dokumentennummer oder ein externes Dokument (referenziert über eine URL als separat herunterladbare Ressource) oder ein eingebettetes Dokument (wie z. B. ein Leistungsnachweis als pdf) zu referenzieren. Von der Möglichkeit der Trennung von Rechnung und Rechnungsbegründenden Unterlagen kann insbesondere im Fall großer Anlagen oder sensibler Daten Gebrauch gemacht werden.

From XRechnung Visualizer CII-to-XR conversion:

Takes <AdditionalReferencedDocument> elements from XRechnung and transfers them as <ADDITIONAL_SUPPORTING_DOCUMENTS> elements into the intermediate visualization format.

   <xsl:template mode="BG-24"
                 match="/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument">
      <xsl:variable name="bg-contents" as="item()*"><!--Der Pfad /rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument der Instanz in konkreter Syntax wird auf 4 Objekte der EN 16931 abgebildet. -->
         <xsl:apply-templates mode="BT-122"
                              select="./ram:IssuerAssignedID[following-sibling::ram:TypeCode='916']"/>
         <xsl:apply-templates mode="BT-123" select="./ram:Name"/>
         <xsl:apply-templates mode="BT-124" select="./ram:URIID"/>
         <xsl:apply-templates mode="BT-125" select="./ram:AttachmentBinaryObject"/>
      </xsl:variable>
      <xsl:if test="$bg-contents">
         <xr:ADDITIONAL_SUPPORTING_DOCUMENTS>
            <xsl:attribute name="xr:id" select="'BG-24'"/>
            <xsl:attribute name="xr:src" select="xr:src-path(.)"/>
            <xsl:sequence select="$bg-contents"/>
         </xr:ADDITIONAL_SUPPORTING_DOCUMENTS>
      </xsl:if>
   </xsl:template>

From XRechnung Visualizer XR-to-HTML conversion:

Renders all <ADDITIONAL_SUPPORTING_DOCUMENTS> elements as downloadable items.

            #region AdditionalReferencedDocument
            if (this.Descriptor.AdditionalReferencedDocuments != null)
            {
                foreach (AdditionalReferencedDocument document in this.Descriptor.AdditionalReferencedDocuments)
                {
                    Writer.WriteStartElement("ram:AdditionalReferencedDocument", Profile.Comfort | Profile.Extended);
                    Writer.WriteElementString("ram:IssuerAssignedID", document.ID);
                    Writer.WriteElementString("ram:TypeCode", document.TypeCode.EnumValueToString());

                    if (document.ReferenceTypeCode != ReferenceTypeCodes.Unknown)
                    {
                        Writer.WriteElementString("ram:ReferenceTypeCode", document.ReferenceTypeCode.EnumToString());
                    }

                    if (!String.IsNullOrEmpty(document.Name))
                    {
                        Writer.WriteElementString("ram:Name", document.Name);
                    }

                    if (document.AttachmentBinaryObject != null)
                    {
                        Writer.WriteStartElement("ram:AttachmentBinaryObject");
                        Writer.WriteAttributeString("filename", document.Filename);
                        Writer.WriteAttributeString("mimeCode", MimeTypeMapper.GetMimeType(document.Filename));
                        Writer.WriteValue(Convert.ToBase64String(document.AttachmentBinaryObject));
                        Writer.WriteEndElement(); // !AttachmentBinaryObject()
                    }

                    if (document.IssueDateTime.HasValue)
                    {
                        Writer.WriteStartElement("ram:FormattedIssueDateTime");
                        Writer.WriteStartElement("qdt:DateTimeString");
                        Writer.WriteAttributeString("format", "102");
                        Writer.WriteValue(_formatDate(document.IssueDateTime.Value));
                        Writer.WriteEndElement(); // !qdt:DateTimeString
                        Writer.WriteEndElement(); // !ram:FormattedIssueDateTime
                    }

                    Writer.WriteEndElement(); // !ram:AdditionalReferencedDocument
                }
            }
            #endregion
patrickkurras commented 1 year ago

Hi @stephanstapel,

thank you for the quick fix! Could you updated the the nuget package as well? That would be awesome :)