Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen (https://www.delphipraxis.net/216155-wpxorder-x-factur-zugferd-xml-daten-lesen-und-erzeugen.html)

jziersch 8. Nov 2024 11:57


WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Liste der Anhänge anzeigen (Anzahl: 2)
WPXOrder ist eine Sammlung von Delphi-Units zur Erstellung und Auswertung von X-Factur (ZUGFeRD) XML-Daten.

Diese Library ist eine möglichst komplette Repräsentierung des ZUGFeRD XSD Schemas als Delphi Klassen.

Sie wurde erstellt, um Rechnungs Daten zu laden, zu verarbeiten und zu speichern. Es beinhaltet noch nicht den E-Invoice-Standard und ist darauf ausgerichtet, XML-Daten zu erstellen, die in PDF-Rechnungen eingebettet werden. Um solche Rechnungen zu erstellen, können Sie die praktische PDF-Erstellungs-VCL wPDF verwenden. Um solche Rechnungen zu lesen, können Sie WPViewPDF PLUS verwenden, das nicht nur X-Factur Daten extrahieren, sondern auch anhängen kann.

Bitte schauen Sie sich den Quellcode auf unserer WPXOrder GitHub Seite an.

Zweck und Lizenzierung
WPXOrder wurde entwickelt, um XML-Anhänge für Rechnungen zu erstellen, die als PDFs verteilt werden. Es wurde in Delphi 10.1 entwickelt und funktioniert am besten mit unseren Produkten wPDF oder WPViewPDF PLUS. Es kann auch verwendet werden, um solche XML-Daten zu lesen und auf alle Eigenschaften einfach zuzugreifen. Es kann auch zur Überprüfung der Berechnung (Gesamtsummen) verwendet werden - bitte beachten Sie jedoch, dass wir nicht garantieren können, dass solche Berechnungen in jedem Fall korrekt funktionieren.

Durch die Art der Implementierung werden folgende Fehler bei der Erstellung von XML Daten:
1) Schreibfehler der XML namen
2) Eigenschaften in falschem Eltern XML Element
3) Falsche Reihenfolge der Elemente (Wichtig für die Validierung)
Desweitern kann man Werte wie TDateTime zuweisen.


Mit der mitgelieferten EXE können Sie die Beispiel-PDFs öffnen und die internen Berechnungen mit den in den PDFs hinterlegten Zahlen vergleichen. Mit nur einem Klick können Sie Delphi-Code erstellen, der die Daten so erzeugt, wie sie in die Rechnung geladen werden. Dies wird Ihnen sehr helfen, das XML-Format besser zu verstehen und Ihre Rechnungserstellungssoftware zu konvertieren.

Sie können die Komponente ohne Lizenzkosten verwenden, wenn Sie sie in ein Open-Source-Projekt einbinden, das unter der GNU-Lizenz vertrieben wird - mit Ausnahme von Komponenten jeglicher Art oder „Forks“.

Wenn Sie die Komponente intern oder in einem Closed-Source-Produkt kommerziell nutzen wollen, ist eine kommerzielle Lizenz erforderlich. Diese Lizenz ist zu einem angemessenen Preis pro Unternehmen erhältlich (named license). Die kommerzielle Lizenz beinhaltet auch Support für 60 Tage nach dem Kauf. Bitte beachten Sie, dass wir uns zu rechtlichen und kalkulatorischen Fragen im Zusammenhang mit X-Factur nicht äußern können.

Programmier Referenz (alle Klassen):
https://www.wpcubed.com/manuals/wpxorder/index.html

Beschreibung:
https://www.wpcubed.com/pdf/products/xorder/

GitHub:
https://github.com/wpcubed/xorder

wPDF - PDF Erzeugen:
https://www.wpcubed.com/pdf/products/wpdf/

WPViewPDF PLUS - XML aus PDFs extrahieren oder hinzufügen:
https://www.wpcubed.com/pdf/products/pdf-edit/

Hinweise:
Auf GitHub befindet sich auch eine (signierte!) EXE welche aus PDFs XML extrahieren kann und direkt Delphi code erzeugen kann, der genau einen XML Rechnungsanhang mit den selben Werte erstellt.

Der Code verwendet Generics, erfordert also neuere Delphi Versionen.

Viel Erfolg,
Julian

Anhang: Automatisch generierter code der mit WPXOrder das ZUGFeRD Beispiel "Warenrechnung" erzeugt

jziersch 9. Nov 2024 12:30

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Jetzt gibt es auch ein Beispiel Projekt mit folgenden Features:

1) XML laden und Kontrollrechnung ausführen
2) XML laden um Rechnungsdaten vorzubelegen (Adresse etc)
3) Aus Rechnungsdaten neue XML erzeugen
4) Geladene oder erzeugte Daten als Pascal Quellcode abspeichern

Dies ist der implementation code des Demo Projekts:

Code:
{ TInvoiceCompanyData }
procedure TInvoiceCompanyData.ReadFromStrings(str: TStrings);
begin
  Name := str.Values['Name'];
  PostcodeCode := str.Values['PostcodeCode'];
  Addres := str.Values['Addres'];
  CityName := str.Values['CityName'];
  CountryIDText := str.Values['CountryID'];
  // Optional
  DepartmentName := str.Values['DepartmentName'];
  // Required for Seller
  TAXId := str.Values['TAXId'];
  // Required for EU Sales
  VATID := str.Values['VATID'];
  // Optional: Full text, several lines for Seller!
  ContactInfo := str.Values['ContactInfo'];
  // Optional
  ID := str.Values['ID'];
  GlobalID := str.Values['GlobalID'];
  GlobalIDScheme := str.Values['GlobalIDScheme'];
  // Optional, Reg Nr
  SpecifiedLegalOrganization := str.Values['SpecifiedLegalOrganization'];
end;

procedure TInvoiceCompanyData.WriteToStrings(str: TStrings);
begin
  str.Values['Name'] := Name;
  str.Values['PostcodeCode'] := PostcodeCode;
  str.Values['Addres'] := Addres;
  str.Values['CityName'] := CityName;
  str.Values['CountryID'] := CountryIDText;
  // Optional
  str.Values['DepartmentName'] := DepartmentName;
  // Required for Seller
  str.Values['TAXId'] := TAXId;
  // Required for EU Sales
  str.Values['VATID'] := VATID;
  // Optional: Full text, several lines for Seller!
  str.Values['ContactInfo'] := ContactInfo;
  // Optional
  str.Values['ID'] := ID;
  str.Values['GlobalID'] := GlobalID;
  str.Values['GlobalIDScheme'] := GlobalIDScheme;
  // Optional, Reg Nr
  str.Values['SpecifiedLegalOrganization'] := SpecifiedLegalOrganization;
end;

procedure TInvoiceForm.SaveasDelphiCode1Click(Sender: TObject);
begin
  SaveDialog1.FilterIndex := 1;
  if SaveDialog1.Execute then
     WPXFactur1.SaveToFile(SaveDialog1.FileName, TWPXOrderDumpMode.DelphiCodeCompact);
end;

procedure TInvoiceForm.SaveXML1Click(Sender: TObject);
begin
  SaveDialog1.FilterIndex := 0;
  if SaveDialog1.Execute then
     WPXFactur1.SaveToFile(SaveDialog1.FileName);
end;

procedure TInvoiceForm.btnCalculateClick(Sender: TObject);
begin
   WPXFactur1.VerifySummation;
   outText.Lines := WPXFactur1.Messages;
end;

procedure TInvoiceForm.btnGenerateInvoiceClick(Sender: TObject);
var i : Integer;
begin
   WPXPaymentData.DueDateDateTime := Now;
   WPXPaymentData.TAXCategory := TTaxCategory(taxCombo.ItemIndex);

   WPXFactur1.StartInvoice(
         TDocumentCode.c380_Commercial_invoice,
         WPXPaymentData.DueDateDateTime,
         edREID.Text,
         edREName.Text,
         WPXSeller, WPXBuyer, nil,
         nil, // from Order
         WPXOrderData,
         nil,
         WPXPaymentData
        );

   for I := 1 to ItemGrid.RowCount-1 do
   if ItemGrid.Cells[1,i]<>'' then
   begin
      WPXFactur1.AddSale(
         ItemGrid.Cells[1,i],
         WPXCurrencyStrToFloat( ItemGrid.Cells[2,i] ),
         WPXCurrencyStrToFloat( ItemGrid.Cells[3,i] ),
         WPXCurrencyStrToFloat( ItemGrid.Cells[5,i] ),
         WPXPaymentData.TAXCategory );
   end;

   WPXFactur1.FinalizeInvoice(true,TCurrencyCode.EUR,0,WPXPaymentData);

   outText.Lines.Assign(WPXFactur1.Messages);
end;

procedure TInvoiceForm.FormCreate(Sender: TObject);
begin
  WPXFactur1 := TWPXFactur.Create(Self);

  WPXSeller := TInvoiceCompanyData.Create;
  WPXBuyer := TInvoiceCompanyData.Create;
  WPXShipTo := TInvoiceCompanyData.Create;
  WPXPaymentData := TPaymentData.Create;
  WPXOrderData := TOrderData.Create;

  ReadItems;
end;

procedure TInvoiceForm.FormDestroy(Sender: TObject);
begin
  WPXFactur1.Free;
  WPXSeller.Free;
  WPXBuyer.Free;
  WPXShipTo.Free;
  WPXPaymentData.Free;
  WPXOrderData.Free;
end;

procedure TInvoiceForm.LoadXML1Click(Sender: TObject);
begin
   if OpenDialog1.Execute then
   begin
     WPXFactur1.LoadFromFile(OpenDialog1.FileName);
     WPXFactur1.ReadCompanyData(WPXSeller,TReadCompanyDataMode.Seller);
     WPXFactur1.ReadCompanyData(WPXBuyer,TReadCompanyDataMode.Buyer);
     WPXFactur1.ReadCompanyData(WPXShipTo,TReadCompanyDataMode.ShipTo);
     // WPXFactur1.ReadCompanyData(xxx,TReadCompanyDataMode.Payee);
     WPXSeller.WriteToStrings(valSeller.Strings);
     WPXBuyer.WriteToStrings(valBuyer.Strings);
     ReadItems;
   end;
end;

procedure TInvoiceForm.ReadItems;
var i : Integer;
    item : TSupplyChainTradeItem;
begin
    ItemGrid.RowCount := 0;
    ItemGrid.RowCount := WPXFactur1.Transaction.Items.Count + 4;
    ItemGrid.ColCount := 7;

    ItemGrid.Cells[0,0] := 'LineID';
    ItemGrid.Cells[1,0] := 'Name';
    ItemGrid.Cells[2,0] := 'Net Charge';
    ItemGrid.Cells[3,0] := 'Quantity';
    ItemGrid.Cells[4,0] := 'TAX Category';
    ItemGrid.Cells[5,0] := 'RateApplicablePercent';
    ItemGrid.Cells[6,0] := 'LineTotalAmount';

    for i := 1 to WPXFactur1.Transaction.Items.Count do
    begin
        item := WPXFactur1.Transaction.Items[i-1];
        with item.Line do
        begin
            ItemGrid.Cells[0,i] := AssociatedDocumentLineDocument.LineID.ValueStr;
            ItemGrid.Cells[1,i] := SpecifiedTradeProduct.Name.ValueStr;
            ItemGrid.Cells[2,i] := SpecifiedLineTradeAgreement.NetPriceProductTradePrice.ChargeAmount.ValueStr;
            ItemGrid.Cells[3,i] := SpecifiedLineTradeAgreement.NetPriceProductTradePrice.BasisQuantity.ValueStr;
            if ItemGrid.Cells[3,i]='' then ItemGrid.Cells[3,i] := '1';
            ItemGrid.Cells[4,i] := SpecifiedLineTradeSettlement.ApplicableTradeTax.CategoryCode.ValueStr;
            ItemGrid.Cells[5,i] := SpecifiedLineTradeSettlement.ApplicableTradeTax.RateApplicablePercent.ValueStr;
            ItemGrid.Cells[6,i] := SpecifiedLineTradeSettlement.SpecifiedTradeSettlementLineMonetarySummation.LineTotalAmount.ValueStr;
            // ItemGrid.Cells[7,i] := SpecifiedLineTradeDelivery.BilledQuantity.ValueStr;
            // ItemGrid.Cells[8,i] := SpecifiedLineTradeSettlement.ApplicableTradeTax.TypeCode.ValueStr;

        end;
    end;
end;
In der unit WPXFactur befindet sich der code zum erzeugen und auslesen der XML Daten sowie zur Berechnung. Hier kann man ganz gut sehen, wie XML Daten ausgelesen werden können, insbesondere die Funktion die die Adressen ausliest.

Code:
procedure TCompanyData.AssignFrom(Source: TTradeParty);
var val : TWPXElement;
begin
  if Source<>nil then
  begin
    // This code reads the value of properties but does not create the elements
    // If they are not existing.
    Source.ReadElementValue([Integer(TXTradeParty.Name)], Name);
    if Source.ReadElementValue([Integer(TXTradeParty.DefinedTradeContact),
            Integer(TXTradeContact.DepartmentName)], val) then
         DepartmentName := val.ValueStr else DepartmentName := '';
    // This code first checks the property exists and then read the values
    Source.ReadElementValue([Integer(TXTradeParty.PostalTradeAddress),
            Integer(TXTradeAddress.PostcodeCode)], PostcodeCode);
    Source.ReadElementValue([Integer(TXTradeParty.PostalTradeAddress),
            Integer(TXTradeAddress.LineOne)], Addres);
    Source.ReadElementValue([Integer(TXTradeParty.PostalTradeAddress),
            Integer(TXTradeAddress.CityName)], CityName);
    if Source.ReadElementValue([Integer(TXTradeParty.PostalTradeAddress),
            Integer(TXTradeAddress.CountryID)], val) then
         CountryIDText := val.ValueStr else CountryID := TCountryID.UNDEFINED;
    Source.ReadElementValue([Integer(TXTradeParty.ID)], ID);
    Source.ReadElementValue([Integer(TXTradeParty.GlobalID)], GlobalID);
    if Source.ReadElementValue([Integer(TXTradeParty.SpecifiedTaxRegistration),
            Integer(TXTaxRegistration.ID)], val) then
         VATID := val.ValueStr else VATID := '';
    if Source.ReadElementValue([Integer(TXTradeParty.SpecifiedLegalOrganization),
            Integer(TXLegalOrganization.ID)], val) then
         SpecifiedLegalOrganization := val.ValueStr else SpecifiedLegalOrganization := '';
  end;
end;
Sie verwendet die Methode ReadElementValue welche auf ein Rechnungsobjekt angewendet, benutzt werden kann ein bestimmtes Unterelement auszulesen, ohne dass diese erzeugt wird, wenn es nicht existiert.

Da der Übergabeparameter ein Array ist, kann man hier auch ein unter-unter Element auslesen.

So liest dieser Code das Element aus:

Code:
if Source.ReadElementValue([Integer(TXTradeParty.DefinedTradeContact),
            Integer(TXTradeContact.DepartmentName)], val) then
         DepartmentName := val.ValueStr else DepartmentName := '';
Welches so geschrieben wird:

TTradeParty(Dest).DefinedTradeContact.DepartmentName.SetValue(DepartmentName);

geschrieben wird. Ohne die Verwendung vom ReadElementValue würde das Unterobjekt DefinedTradeContact und DepartmentName automatisch angelegt, wenn man also einfach auf Source.DefinedTradeContact.DepartmentName.ValueStr zugreifen würde.

Ich hoffe dies erklärt etwas, wie die automatische Erzeugung der Eigenschaften funktioniert.

Übrigens: Viele Eigenschaften in der Rechnung können mehrfach auftreten. Mit Aussnahme der Rechnungsposten (lines), welche durch eine eigene Collection verwaltet werden, wird dies durch eine default Array property von ausgewählten Klassen implementiert.

IncludedNote[1].ContentCode...

greift hier auf die erste Notiz zu, IncludedNote[2].ContentCode... auf die zweite usw. Der Zugriff muss in der richtigen, aufsteigenden Reihenfolge erfolgen. Zu auslesen kann man 'Count' abfragen. Zum sequentiellen Hinzufügen ohne index gibt es ListAdd.

motion 3. Jan 2025 10:30

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Hallo Herr Ziersch,
ich mache gerade Versuche mit den WPXOrder Units und es sieht recht gut aus.

ein paar kurze Fragen:
1. Mir scheint da liegt ein Bug bei der Codierung der Steuernummer-Codes vor? Sehe ich das richtig?
TTaxIDType Funktionen in der WPXFacturTypes.PAS:
Delphi-Quellcode:
function TTaxIDType.AttributeGet(Index: Integer;
  var AName, AValue: String): Boolean;
begin
  if index = 0 then
  begin
    AName := 'schemeID';
    if fschemeID=TTaxID.FC_tax_number then
//      AValue := 'FA' else AValue := 'VA'; <--- FEHLER!!!!
        AValue := 'FC' else AValue := 'VA'; <--- KORREKT!!!
    Result := true;
  end
  else
    Result := false;
end;

function TTaxIDType.AttributeSet(const AName, AValue: String): Boolean;
begin
  if SameText(AName, 'schemeID') then
  begin
    if SameText('FC',AValue) then fschemeID := TTaxID.FC_tax_number
    else if SameText('VA',AValue) then fschemeID := TTaxID.VA_VAT_number
    else raise ENotExpectedAttributeValue( AName+'='+ AValue);
    Result := true;
  end
  else
    Result := false;
end;
2. Der Bestellprozess in Ihrem Shop ist etwas verwirrend.
https://www.wpcubed.com/pdf/products/xorder/ beschreibt den Preis als
"Order commercial license for EURO 199,92 incl. 19% VAT (only available in Germany)"
Beim Abschluß des Bestellprozesses im Shop sind es aber 199,92€ zuzüglich MwSt.

Vielen Dank

motion 4. Jan 2025 19:10

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
und noch eine Sache ist mir aufgefallen:
Die WPXOrder arbeitet noch nach ZUGferd 2.2, oder?
Denn ich kämpfe mit Rundungsdifferenzen (meist nur 0,01€ = 1ct) bei der Summierung von Nettobeträgen, MwSt-Beträgen und dem Bruttopreis.

Wenn ich diese Seite richtig lese:
https://nexoma.de/zugferd/
dann steht dort als Neuerung zu ZUGFeRD 2.3(.2):

Zitat:

ZUGFeRD 2.3: Die neue Version des Formats entspricht gleichzeitig der Factur-X Version 1.0.07. Sie bringt eine angepasste Validierung im Profil EXTENDED mit sich. Nutzer dieses Profils sollten daher ein sofortiges Update durchführen. Zu den weiteren Neuerungen gehören die Korrektur kleinerer Fehler in allen Profilen, Ergänzungen für das französische B2B-Mandat und die Einführung von Rundungsungenauigkeiten (englisch auch als „Slack“ bezeichnet) im Profil EXTENDED.
Diese Rundungsungenauigkeiten treten zum Beispiel bei ‚ungeraden Preisen‘ auf. Ein Bruttopreis von 9,99 € kann mitunter nicht exakt als Nettopreis dargestellt werden, da bei der Umrechnung durch die Division mit 1,19 (wegen 19 % MwSt.) mathematische Rundungsfehler entstehen
. Der resultierende Nettopreis hat dann oft viele Dezimalstellen. Da viele Systeme jedoch nur zwei Dezimalstellen zulassen, kommt es dadurch zu Rundungsdifferenzen.
Ist eine Anpassung an Version 2.3.2 zu erwarten?
Diese Slack-Berücksichtigung für solche (1ct) Differenzen würde sehr helfen.

jziersch 5. Jan 2025 09:34

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Das ganze basiert auf dem Schema 2.2, das ist richtig. Dies war der neueste Download zum Zeitpunkt als der Code geschrieben wurde.

Ich habe mal die Änderungen nachgeschlagen:

"neue Codelisten" müssten in der Tat als angepasste enums im code eingepflegt werden. In allen Fällen kann allerdings anstatt des Enums der code mit SetValueStr gesetzt werden. Nur dieser text wird geschrieben.
Ich habe die XSD Quellen verglichen, die neuen XSD sind zwar viel mehr aber haben insgesamt weniger an Inhalt. So enthält AllowanceChargeReasonCodeContentType kaum noch Werte. Im Moment bin ich mir nicht so sicher, ob es sinnvoll ist, die neuen Werte einzupflegen. Hat jemand Hinweise auf die codes die tatsächlich geändert wurden?

"korrigierte technische Prüfungen" sind nicht Teil von WPXOrder, insbesondere das Schematron wird nicht verwendet.

Zur validierung habe ich diese Seite als sehr hilfreich empfunden: https://portal3.gefeg.com/invoice/page/validation

WPXOrder wurde anhand der offiziellen Beispiele getestet und diese tragen die Versionsnummer 2.3.0.

Zu den Rundungsdifferenzen - die interne Berechnung habe ich aufgrund Feedbacks von der Validator Seite implementiert.
Den code findet man in function TWPXFactur.FinalizeInvoice.

Wesentlich ist hier, dass die Berechnung immer gruppiert nach TAX Value (0,7,19...) erfolgt. Das gilt für Items, Allowances und Charges jeweils insgesamt.

Mit dem Modus TWPXOrderCalcMode.VATAddRoundedOnLine in CalcMode kann die Steuer auch zeilenweise addiert werden.


Die Berechnung ist natürlich optional, das Konzept von WPXOrder erlaubt es jeden Wert einzeln zu setzen.

jziersch 5. Jan 2025 09:55

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
[QUOTE=motion;1544750]1. Mir scheint da liegt ein Bug bei der Codierung der Steuernummer-Codes vor? Sehe ich das richtig?

Vielen Dank. Das ist in der Tat ein Tippfehler.

2. Der Bestellprozess in Ihrem Shop ist etwas verwirrend.

Sie haben recht, das habe ich berichtigt. Stripe addiert offenbar die MwST (was auch korrekt ist)

JDiegelmann 23. Jan 2025 17:32

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Hallo,

ich spiele gerade ein wenig mit diesem tollen Tool, allerdings in erster Linie zum auslesen von eRechnungen.

Ich habe festgestellt das ich skonti mit nullwert angezeigt bekomme. diese Daten aus den bereich

ram:ApplicableHeaderTradeSettlement werden scheinbar nicht geladen.

mache ich an dieser Stelle etwas falsch oder kann dort ein Fehler vorliegen.

jziersch 24. Jan 2025 08:10

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Mit einer Beispiel XML schaue ich mir das gerne an.
THeaderTradeSettlement ist ein sehr kompliziertes konstruct, was genau wird denn nicht geladen?

Die Einträge sind definiert wie folgt

Code:
   CreditorReferenceID, // name=CreditorReferenceID,type=udt:IDType,minOccurs=0
   PaymentReference, // name=PaymentReference,type=udt:TextType,minOccurs=0
   TaxCurrencyCode, // name=TaxCurrencyCode,type=qdt:CurrencyCodeType,minOccurs=0
   InvoiceCurrencyCode, // name=InvoiceCurrencyCode,type=qdt:CurrencyCodeType
   InvoiceIssuerReference, // name=InvoiceIssuerReference,type=udt:TextType,minOccurs=0
   InvoicerTradeParty, // name=InvoicerTradeParty,type=ram:TradePartyType,minOccurs=0
   InvoiceeTradeParty, // name=InvoiceeTradeParty,type=ram:TradePartyType,minOccurs=0
   PayeeTradeParty, // name=PayeeTradeParty,type=ram:TradePartyType,minOccurs=0
   PayerTradeParty, // name=PayerTradeParty,type=ram:TradePartyType,minOccurs=0
   TaxApplicableTradeCurrencyExchange, // name=TaxApplicableTradeCurrencyExchange,type=ram:TradeCurrencyExchangeType,minOccurs=0
   SpecifiedTradeSettlementPaymentMeans, // name=SpecifiedTradeSettlementPaymentMeans,type=ram:TradeSettlementPaymentMeansType,minOccurs=0,maxOccurs=unbounded
   ApplicableTradeTax, // name=ApplicableTradeTax,type=ram:TradeTaxType,maxOccurs=unbounded
   BillingSpecifiedPeriod, // name=BillingSpecifiedPeriod,type=ram:SpecifiedPeriodType,minOccurs=0
   SpecifiedTradeAllowanceCharge, // name=SpecifiedTradeAllowanceCharge,type=ram:TradeAllowanceChargeType,minOccurs=0,maxOccurs=unbounded
   SpecifiedLogisticsServiceCharge, // name=SpecifiedLogisticsServiceCharge,type=ram:LogisticsServiceChargeType,minOccurs=0,maxOccurs=unbounded
   SpecifiedTradePaymentTerms, // name=SpecifiedTradePaymentTerms,type=ram:TradePaymentTermsType,minOccurs=0,maxOccurs=unbounded
   SpecifiedTradeSettlementHeaderMonetarySummation, // name=SpecifiedTradeSettlementHeaderMonetarySummation,type=ram:TradeSettlementHeaderMonetarySummationType
   InvoiceReferencedDocument, // name=InvoiceReferencedDocument,type=ram:ReferencedDocumentType,minOccurs=0
   ReceivableSpecifiedTradeAccountingAccount, // name=ReceivableSpecifiedTradeAccountingAccount,type=ram:TradeAccountingAccountType,minOccurs=0,maxOccurs=unbounded
   SpecifiedAdvancePayment // name=SpecifiedAdvancePayment,type=ram:AdvancePaymentType,minOccurs=0,maxOccurs=unbounded

Hobbycoder 24. Jan 2025 11:17

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Kleine Frage auf die ich im Internet nicht unbedingt eindeutige Antworten finde:

Der Dateiname der im PDF integrierten XML, muss der einen bestimmten Namen haben?

Ich finde Hinweise auf "ZUGFeRD-invoice.xml" oder auch "factur-x.xml". Ist es egal welchen man nimmt? Spielt es überhaupt eine Rolle? Oder ist das Versionsabhängig?

AuronTLG 24. Jan 2025 11:53

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Aus der ZUGFeRD-Dokumentation Punkt 6.2:

Zitat:

Die XML-Datei wird immer unter dem Namen "factur-x.xml" eingebettet. Die einzige Ausnahme
bilden Referenzprofile wie das Profil XRECHNUNG; hier muss der Name „xrechnung.xml“ lauten.
Optional können auch weitere unterstützende Dokumente eingebunden werden

Hobbycoder 24. Jan 2025 13:07

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Danke

Hobbycoder 24. Jan 2025 18:30

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
In der TWPXSeller gibt es VATID und TATid. Was gehört da rein? Es gibt ja die Steuernummer und die UmsStID.

jziersch 25. Jan 2025 09:20

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Zitat:

Zitat von Hobbycoder (Beitrag 1545561)
Kleine Frage auf die ich im Internet nicht unbedingt eindeutige Antworten finde:

Der Dateiname der im PDF integrierten XLM, muss der einen bestimmten Namen haben?

"ZUGFeRD-invoice.xml" oder auch "factur-x.xml" wird historisch bedingt von Applikationen gesucht.
Der Name muss aber in den XMP (den metadaten) genannt werden und mir sind auch schon Rechnungen untergekommen, die einen anderen Namen verwenden und dann eben dort, in den XMP, eintragen. Das nächste Build von WPViewPDF 5 wird intern eine entsprechende Abfrage enthalten, damit die richtige Datei extrahiert wird.

jziersch 25. Jan 2025 09:35

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Zitat:

Zitat von Hobbycoder (Beitrag 1545591)
In der TWPXSeller gibt es VATID und TATid. Was gehört da rein? Es gibt ja die Steuernummer und die UmsStID.

Du meinst wahrscheinlich TCompanyData

Aktuell wird nur VATID verwendet (also UmsStID) und entsprechend zugewiesen. Alle anderen Felder sind zugänglich über den Pfad zu der TTradeParty Struktur. Als Beispielcode siehe bitte die TCompanyData.AssignTo()

Edit: Ich habe den code wie unten ergänzt. Damit wird sowohl TaxID also auch VATId geschrieben. Es wird dann ein mehrfach Eintrag erzeugt. Ob das so unterstützt wird kann ich im Moment nicht sagen. Der code ist auf jeden Fall aber ein gutes Beispiel wie man mehrfache Einträge erzeugen kann.

Code:
procedure TCompanyData.AssignTo(Dest: TTradeParty);
var i : Integer;
begin
  if Self<>nil then
  begin
    i := 1;
    if VATID<>'' then
    begin
       Dest.SpecifiedTaxRegistration[i].ID.SetValue(VATID,TTaxID.VA_VAT_number);
       inc(i);
    end;
    if TAXId<>'' then
    begin
       Dest.SpecifiedTaxRegistration[i].ID.SetValue(TAXId,TTaxID.FC_tax_number);
    end;
// ...
  end;
end;

procedure TCompanyData.AssignFrom(Source: TTradeParty);
var val : TWPXElement;
    i : Integer;
begin
  if Source<>nil then
  begin  
    VATID := '';
    TAXId := '';
    if Source.ReadElementValue([Integer(TXTradeParty.SpecifiedTaxRegistration)], val) then
    begin
       for i := 0 to (val as TTaxRegistration).ListCount-1 do
       begin
          if TTaxRegistration(val)[i].ID.schemeID=TTaxID.VA_VAT_number then
               VATID := TTaxRegistration(val)[i].ID.ValueStr
          else TAXId := TTaxRegistration(val)[i].ID.ValueStr;
       end;
    end;
//    ...
  end;
end;

Hobbycoder 25. Jan 2025 11:16

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Super Danke. Ich komme der Sache näher.

Ein paar Fragen habe ich noch.

[Edit]
[Erledigt]Wie kann ich aus der TWPXFactur die PaymentData, oder die Rechnungsnummer bzw. das Rechnungsdatum auslesen?
Hab ich mittlerweile gefunden
Mit einem XML-Viewer kann man da schon einiges lernen https://xmlexplorer.github.io/#google_vignette
[/Edit]

Und mir ist gerade noch eine Kleinigkeit aufgefallen.
Wenn ich die Artikel in die TWPXFatur eintrage
Delphi-Quellcode:
   for I := 0 to A.PositionList.Count-1 do
   begin
      wpxfctr1.AddSale(
         A.PositionList[i].Kurztext,                    //ProductName
         A.PositionList[i].EP,                          //SinglePriceNET
         A.PositionList[i].Menge,                       //Quantity
         A.PositionList[i].MwSt,                        //VATRate
         WPXPaymentData.TAXCategory );                  //VATCategory
                                                         //QuantityCode
                                                         //Totsl
   end;
dann steht hinterher in der XML:
XML-Code:
 <rsm:SupplyChainTradeTransaction>
   <ram:IncludedSupplyChainTradeLineItem>
    <ram:AssociatedDocumentLineDocument>
     <ram:LineID>1</ram:LineID>
    </ram:AssociatedDocumentLineDocument>
    <ram:SpecifiedTradeProduct>
     <ram:Name>ABUS IP-Kamery TVIP44510</ram:Name>
    </ram:SpecifiedTradeProduct>
    <ram:SpecifiedLineTradeAgreement>
     <ram:NetPriceProductTradePrice>
      <ram:ChargeAmount>149.00</ram:ChargeAmount>
      <ram:BasisQuantity unitCode="H87">1.0000</ram:BasisQuantity>   <!-- VPE? -->
     </ram:NetPriceProductTradePrice>
    </ram:SpecifiedLineTradeAgreement>
    <ram:SpecifiedLineTradeDelivery>
     <ram:BilledQuantity unitCode="H87">2.0000</ram:BilledQuantity>  <!-- Tatsächliche Artikelmenge -->
    </ram:SpecifiedLineTradeDelivery>
    <ram:SpecifiedLineTradeSettlement>
     <ram:ApplicableTradeTax>
      <ram:TypeCode>VAT</ram:TypeCode>
      <ram:CategoryCode>S</ram:CategoryCode>
      <ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
     </ram:ApplicableTradeTax>
     <ram:SpecifiedTradeSettlementLineMonetarySummation>
      <ram:LineTotalAmount>298.00</ram:LineTotalAmount>
     </ram:SpecifiedTradeSettlementLineMonetarySummation>
    </ram:SpecifiedLineTradeSettlement>
   </ram:IncludedSupplyChainTradeLineItem>
BaseQuantity ist 1, BillingQuantity ist 2.
Also gehe ich mal davon aus, dass sich BaseQuatity auf die VPE bezieht, oder halt die Menge je Einzelpreis.

Wenn ich das jedoch auslesen will:
Delphi-Quellcode:
wpxfctr.Transaction.Items[i].Line.SpecifiedLineTradeAgreement.NetPriceProductTradePrice.BasisQuantity
dann gibt es unter NetPriceProductTracePrice kein BillingQuantity. Wie komme ich dann beim Auslesen an die tatsächliche Menge?

Ein Ähnliches Problem habe ich mit der LineID, die ja im AddSale nicht übergeben wird. In meinem erstellten factur-x.XML ist sie dann immer 1.
Müsste die sich nicht nach jedem AddSale um 1 erhöhen?

Ich taste mich jetzt langsam an die E-Rechnung ran, also bitte ich bei den Fragen, wie dumm sie auch sind, um etwas Nachsicht :wink:

jziersch 25. Jan 2025 15:31

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
AddSale ist eine high-level API die nicht alle Probleme lösen kann oder will.
Die Funktion AddSale erstellt ein element der Klasse TSupplyChainTradeItem welches es zurückgibt. Dort kann man dann weitere elemente anlegen indem man einfach darauf zugreift.

Empfehlenswert ist anstatt einfach mal Delphi code zu erzeugen:
procedure SaveToFile(Filename : String; Mode : TWPXOrderDumpMode = TWPXOrderDumpMode.DelphiCode);

Das kann man auch nach dem laden einer Beispiel XML Datei machen. Damit hat man bereits das Code gerüst um eine XML zu erzeugen und die nötigen Zeilen um Werte zu lesen.

Hobbycoder 25. Jan 2025 17:26

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Ich hab mir mal die Dokumentation heruntergeladen https://www.ferd-net.de/publikatione...publikationen/

Das erklärt die ganzen Eigenschaften recht gut.
Damit versuche ich mal mein Grück.

Bodenseematze 26. Mai 2025 09:25

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
Ich habe mir mal diesen Thread durchgelesen - ohne es bisher ausprobiert zu haben: auf den ersten Blick sieht das WPXOrder ganz gut aus :wink:

Aber ein paar Fragen hätte ich vor dem richtigen Testen noch:
1.) hat es irgendwelche Abhängigkeiten zu Java oder kommt es komplett ohne aus?
2.) welche Delphi-Versionen werden unterstützt bzw. bis zu welcher alten Version ist es kompatibel?
3.) unterstützt es inzwischen die aktuellen ZUGFeRD-Versionen 2.3.2 / 2.3.3?

jziersch 26. Mai 2025 14:17

AW: WPXOrder - X-Factur (ZUGFeRD) XML Daten lesen und erzeugen
 
1) das ist in pascal geschrieben und verwendet generics. Es ist eine Umsetzung der ersten ZUGFeRD specs als pascal code.

2) Delphi 10.1 oder neuer empfehle ich

3) Leider wurde der Aufbau der XML Dateien der Specs ohne ersichtlichen Grund komplett geändert sodass sich die letzten Downloads nicht mehr umwandeln lassen. Die Erneuerungen betreffen nach meinem Verständnis aber nur die Codes, die zum Teil in WPXOrder als Enums implementiert sind. Da die Verwendung von strings hier möglich ist, sollte dadurch kein Hindernis entstehen.

Die Besonderheit von WPXOrder ist:

Man kann eine XML Rechnungsdatei lesen und sich Delphi Code schreiben lassen der dann genau diese Rechnungsdatei wieder schreibt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:27 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz