horstoeko / zugferd

ZUGFeRD/XRechnung/Factur-X Library
MIT License
141 stars 25 forks source link

[FEATURE] Support for XRechnung in the UBL Format #117

Closed oschildt closed 1 month ago

oschildt commented 1 month ago

Describe the feature A X-Rechnung can also be in the the UBL Format

https://invoice-portal.de/rechnungsformate/xrechnung-beispiel/

The XRechnung is a structured, standardized data record in XML format that can be automatically sent and processed electronically.

The following two syntaxes are permitted for XRechnung:

The XRechnung must be transmitted in one of the two syntaxes. The recipient of the XRechnung must be able to process both formats.

Do you plan supporting this format?

horstoeko commented 1 month ago

Hi @oschildt,

The following two syntaxes are permitted for XRechnung:

  • Universal Business Language (UBL)
  • UN/CEFACT Cross Industry Invoice (CII)

I know... :-)

Do you plan supporting this format?

We've had this discussion before. (see this issue).

The data models are so different that I can't implement them in the current solution. But you are welcome to pay some attention to horstoeko/zugferdublbrigde... This is still considered unstable at the moment, but if people can be found to support the project, then the library just mentioned may be what you are looking for.

However, if you have any ideas on how to implement UBL in the current version, I would be delighted to hear about possible solutions.

Kind regards

oschildt commented 1 month ago

Hi again!

I found your another project zugferdublbridge. And my request is partially covered:)

But it is still to consider direct support of UBL invoices in the same library with the same interface like

UBLDocumentReader

with the same methods like by ZugferdDocumentReader

oschildt commented 1 month ago

OK. I will look into it. But if you say that the formats are totally different than my idea with the same methods is hardly to realize

Probably, then extend like

class UBLDocumentReader extends ZugferdDocument

and implement the methods related UBL.

horstoeko commented 1 month ago

Hi @oschildt,

Hi,

Unfortunately, I can't find a reasonable XSD with which I can create the required entities for the serializer/deserializer I am using. That might be a first step. But (as I said), the content structure is simply too different to be able to reconcile the two things. Unfortunately, I have no idea who came up with the idea of implementing two different syntaxes for one and the same thing.

Kind regards

oschildt commented 1 month ago

Well. I would act follows:

Create an abstract model of the electronic invoice.

class Tax
{
  ...
}

class Allowance
{
  ...
}

class InvoiceTax
{
  ...
}

class InvoiceAgent
{
  ...
}

class InvoicePostion
{
  function getPostionTaxes() : array[Tax];
  function getPostionAllowances() : array[Allowance];
  ...
}

abstract class EInvoice
{
  function getInvoiceSellers() : array[InvoiceAgent];
  function getInvoiceByers() : array[InvoiceAgent];
  // other possible alternate agents

  function getInvoiceInformation() : array;
  function getInvoiceSummation() : array;
  function getInvoiceTaxes() : array[[Tax];
  function getInvoiceAllowances() : array[Allowance];
  function getInvoicePositions() : array[InvoicePostion];
  function readAndGuessFromFile();
  function readAndGuessFromContent();
  ...
  function generateUblXML();
  function generateCllXML();
  function generateZugferdPDF();
}

Then, derive the classes for each concrete type of the electronic invoices and implement the methods for each case. Just parse and analyze the XML data.

class UBLInvoice extends EInvoice
{

}

class ZugferdInvoice extends EInvoice
{

}

Probably, the static factory method would be useful:

abstract class EInvoice
{
  static getAndGuessEInvoiceFromContent(string $content): EInvoice;
  static getAndGuessEInvoiceFromFile(string $filename): EInvoice;
}

It should guess the type of document and return the corresponding EInvoice (UBLInvoice or ZugferdInvoice)

If a new type of electronic invoices appears, its support can be flexibly added like this

class OtherEInvoice extends EInvoice
{

}

For instance, I found another type of Erechnung that can be generated here:

https://xrechnung-erstellen.com/

It generates some strange XML format. Some viewers support it, but I have no idea what it is. It can be also covered my my model.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rechnung>
    <rechnungsdaten>
        <leitwegId>76767767676</leitwegId>
        <auftragsnummer></auftragsnummer>
        <bestellnummer>56566556</bestellnummer>
        <rechnungsnummer>5656565656</rechnungsnummer>
        <projektreferenz></projektreferenz>
        <vertragsnummer></vertragsnummer>
        <rechnungsart>380</rechnungsart>
        <waehrungRechnung>EUR</waehrungRechnung>
        <vergabenummer></vergabenummer>
        <objektkennung></objektkennung>
        <objektkennungMuster></objektkennungMuster>
        <kontierungsinformationen></kontierungsinformationen>
        <refEmpfangsbestaetigung></refEmpfangsbestaetigung>
        <refVersandanzeige></refVersandanzeige>
        <businessKontext>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</businessKontext>
        <zahlungsbedingungen></zahlungsbedingungen>
        <rechnungsdatum>2024-09-16</rechnungsdatum>
        <faelligkeitsdatum>2024-09-28</faelligkeitsdatum>
        <kontierungsinfoUStCode></kontierungsinfoUStCode>
    </rechnungsdaten>
    <rechnungstexte/>
    <rechnungsverlauf/>
    <rechnungssteller>
        <unternehmen>334343434</unternehmen>
        <abweichenderHandelsname>23232332</abweichenderHandelsname>
        <umsatzsteuerId>DE122086355</umsatzsteuerId>
        <eindeutigeKennung>2322323</eindeutigeKennung>
        <eindeutigeKennungSchema></eindeutigeKennungSchema>
        <eRechnungsAdresse>oleg.schildt@masch.com</eRechnungsAdresse>
        <eRechnungsAdresseSchema>EM</eRechnungsAdresseSchema>
        <handelsregisterNr>23322323</handelsregisterNr>
        <anschrift>
            <strasse1>23232323</strasse1>
            <strasse2>23233223</strasse2>
            <strasse3>32232323</strasse3>
            <plz>23322323</plz>
            <ort>322323</ort>
            <bundesland></bundesland>
            <land>DE</land>
        </anschrift>
        <kontaktdaten>
            <name>23232323</name>
            <email>christian.schildt@masch.com</email>
            <telefon>23232323</telefon>
        </kontaktdaten>
        <steuernummer>3223232323</steuernummer>
        <verkauferinformation></verkauferinformation>
        <rechtlicheInformationen>23233223</rechtlicheInformationen>
    </rechnungssteller>
    <rechnungsempfaenger>
        <unternehmen>2132312323</unternehmen>
        <abweichenderHandelsname></abweichenderHandelsname>
        <umsatzsteuerId>DE122086355</umsatzsteuerId>
        <eindeutigeKennung>23322332</eindeutigeKennung>
        <eindeutigeKennungSchema></eindeutigeKennungSchema>
        <eRechnungsAdresse></eRechnungsAdresse>
        <anschrift>
            <strasse1>23232323</strasse1>
            <strasse2>32232323</strasse2>
            <strasse3>232323</strasse3>
            <plz>23322323</plz>
            <ort>323232</ort>
            <bundesland></bundesland>
            <land>DE</land>
        </anschrift>
        <kontaktdaten>
            <name></name>
            <email></email>
            <telefon></telefon>
        </kontaktdaten>
    </rechnungsempfaenger>
    <zahlungsdaten>
        <zahlungsmittelCode>58</zahlungsmittelCode>
        <verwendungszweck>34343434</verwendungszweck>
        <zahlungsbedingungen>
            <zahlungsbedingung>
                <prozent>0.0</prozent>
                <tage>0</tage>
                <typ>SKONTO</typ>
                <zahlungszeile>#SKONTO#TAGE=0#PROZENT=0.00#</zahlungszeile>
            </zahlungsbedingung>
        </zahlungsbedingungen>
        <sepaMandatsreferenz></sepaMandatsreferenz>
        <sepaGlaeubigerID></sepaGlaeubigerID>
        <sepaIbanKonto></sepaIbanKonto>
        <kreditkartennummer></kreditkartennummer>
        <karteninhaber></karteninhaber>
        <abweichenderZahlungsempfaenger>
            <name></name>
            <kennung></kennung>
            <kennungSchema></kennungSchema>
            <handelsregisterNr></handelsregisterNr>
            <handelsregisterNrSchema></handelsregisterNrSchema>
        </abweichenderZahlungsempfaenger>
        <ueberweisungen>
            <ueberweisung>
                <iban>DE84500105175424900805</iban>
                <bic>34343434</bic>
                <kontoinhaber>34343434</kontoinhaber>
            </ueberweisung>
        </ueberweisungen>
    </zahlungsdaten>
    <positionen>
        <position>
            <positionsnummer>1</positionsnummer>
            <positionstext></positionstext>
            <positionskennung></positionskennung>
            <positionskennungCode></positionskennungCode>
            <menge>0.00</menge>
            <einheit>C62</einheit>
            <gesamtpreisNetto>0.00</gesamtpreisNetto>
            <bestellreferenz>232332322323</bestellreferenz>
            <kontierungshinweis></kontierungshinweis>
            <umsatzsteuer>19.00</umsatzsteuer>
            <umsatzsteuerCode>S</umsatzsteuerCode>
            <artikelbezeichnung>232323</artikelbezeichnung>
            <artikelbeschreibung>23232323</artikelbeschreibung>
            <artikelnummerVerkaeufer>232323</artikelnummerVerkaeufer>
            <artikelnummerKaeufer></artikelnummerKaeufer>
            <artikelnummer></artikelnummer>
            <artikelnummerCode>0197</artikelnummerCode>
            <artikelklassifizierung></artikelklassifizierung>
            <artikelklassifizierungSchema>ZZZ</artikelklassifizierungSchema>
            <artikelklassifizierungSchemaVersion></artikelklassifizierungSchemaVersion>
            <artikelherkunft></artikelherkunft>
            <einzelpreisNettoMitRabatt>4.00</einzelpreisNettoMitRabatt>
            <rabattGesamt>0.00</rabattGesamt>
            <einzelpreisNettoOhneRabatt>5.00</einzelpreisNettoOhneRabatt>
            <preisbasisMenge>1.00</preisbasisMenge>
            <preisbasisEinheit>C62</preisbasisEinheit>
            <positionAbschlaege/>
            <positionZuschlaege/>
            <positionZeitraum/>
            <positionMetadaten/>
            <unterPositionen/>
        </position>
    </positionen>
    <anlagen/>
    <lieferinformation>
        <name></name>
        <kennung></kennung>
        <kennungSchema></kennungSchema>
        <lieferdatum>2024-09-19</lieferdatum>
        <lieferadresse/>
    </lieferinformation>
    <rechnungAbschlaege/>
    <rechnungZuschlaege/>
    <gesamtsummen>
        <summePositionenNetto>0.00</summePositionenNetto>
        <summeAbschlaegeNetto>0.00</summeAbschlaegeNetto>
        <summeZuschlaegeNetto>0.00</summeZuschlaegeNetto>
        <gesamtsummeNetto>0.00</gesamtsummeNetto>
        <summeUmsatzsteuer>0.00</summeUmsatzsteuer>
        <gesamtsummeBrutto>0.00</gesamtsummeBrutto>
        <gezahlterBetrag>0.00</gezahlterBetrag>
        <rundungsBetrag>0.00</rundungsBetrag>
        <faelligerBetrag>0.00</faelligerBetrag>
    </gesamtsummen>
    <steuerDetails>
        <detail>
            <gesamtsummeNetto>0.00</gesamtsummeNetto>
            <umsatzsteuerbetrag>0.00</umsatzsteuerbetrag>
            <umsatzsteuerCode>S</umsatzsteuerCode>
            <umsatzsteuersatz>19.00</umsatzsteuersatz>
            <befreiungsgrund></befreiungsgrund>
            <befreiungsgrundCode></befreiungsgrundCode>
        </detail>
    </steuerDetails>
    <zahlungThirdParties/>
</rechnung>

Now I am a little bit under pressure. This topic was new for me, and now I have been bad surprised that there is another important format ubl that has to be supported.

I will try to start a project and implement Zugferd based on your library and add support for other formats like described above.

horstoeko commented 1 month ago

Hi @oschildt,

I will try to start a project and implement Zugferd based on your library and add support for other formats like described above.

Maybe you make a fork of my project.

Now I am a little bit under pressure. This topic was new for me, and now I have been bad surprised that there is another important format ubl that has to be supported.

As I said, I still don't understand why people do such nonsense. It could all be so simple. I deliberately “jumped on board” ZUGFeRD, as our French friends are also doing well with their Factur-X in my view.

Kind regards