From e2b0767a791707ad97d4ba0086cba82f46c016b6 Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Thu, 4 Jan 2024 22:42:37 +0100 Subject: [PATCH 1/3] Update format version --- lib/datev/base/header/booking_header.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/datev/base/header/booking_header.rb b/lib/datev/base/header/booking_header.rb index 7a5fa32..e060fd3 100644 --- a/lib/datev/base/header/booking_header.rb +++ b/lib/datev/base/header/booking_header.rb @@ -6,7 +6,7 @@ class BookingHeader < Header 'Versionsnummer' => 700, 'Datenkategorie' => 21, 'Formatname' => 'Buchungsstapel', - 'Formatversion' => 9, + 'Formatversion' => 13, 'Erzeugt am' => Time.now.utc, 'Sachkontenlänge' => 4, 'Bezeichnung' => 'Buchungen', From 2269a44c3867773eba44bff4a8cab728401b3e07 Mon Sep 17 00:00:00 2001 From: Michael Kaiser Date: Thu, 4 Jan 2024 23:09:10 +0100 Subject: [PATCH 2/3] Update booking.rb Add fields up to format version 700/13 --- lib/datev/base/booking.rb | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/datev/base/booking.rb b/lib/datev/base/booking.rb index ce8bd6b..1cbbcae 100644 --- a/lib/datev/base/booking.rb +++ b/lib/datev/base/booking.rb @@ -365,5 +365,44 @@ def output(value, context) # 120 field 'Land', :string, limit: 2 # Beispiel: DE für Deutschland + + # 121 + field 'Abrechnungsreferent', :string, limit: 50 + # Die Abrechnungsreferenz stellt eine Klammer über alle Transaktionen + # des Zahlungsdienstleisters und die dazu gehörige Auszahlung dar. + # Sie wird über den Zahlungsdatenservice bereitgestellt und bei der + # Erzeugung von Buchungsvorschläge berücksichtigt. + + # 122 + field 'BVV-Position', :integer, limit: 1 + # Betriebsvermögensvergleich + # 1 Kapitalanpassung + # 2 Entnahme / Ausschüttung lfd. WJ + # 3 Einlage / Kapitalzuführung lfd. WJ + # 4 Übertragung § 6b Rücklage + # 5 Umbuchung (keine Zuordnung) + + # 123 + field 'EU-Mitgliedstaat u. UStID (Ursprung)', :string, limit: 15 + # Die USt-IdNr. besteht aus + # - 2-stelligen Länderkürzel (siehe Dok.-Nr. 1080169) + # Ausnahme Griechenland: Das Länderkürzel lautet EL) + # - 13-stelliger USt-IdNr. + # - Beispiel: DE133546770. Die USt-IdNr kann auch Buchstaben haben, z.B.: bei Österreich + # Detaillierte Informationen zur Erfassung von EU-Informationen im Buchungssatz: Dok.-Nr: 9211462 + + # 124 + field 'EU-Steuersatz (Ursprung)', :decimal, precision: 4, scale: 2 + # Nur für entsprechende EU-Buchungen: + # Der im EU-Ursprungsland gültige Steuersatz. + # Beispiel: 12,12 + + # 125 + field 'Abw. Skontokonto', :integer, limit: 8 + # Zulässig sind hier, bei Zahlungsbuchungen mit Skontoabzug, Konten mit dem Kontenzweck „sonstige betriebliche Aufwendungen“. + # Eine Eingabe in diesem Feld bedeutet, dass der Skontobetrag auf dieses Aufwandskonto gebucht wird. + # Wenn in der Importdatei keine Angaben zum Skontokonto enthalten sind, wird der Skontobetrag auf das entsprechende Skontosammelkonto gebucht. + + end end From 6744ba270268ce60af437ae505fe63f6fa2f554b Mon Sep 17 00:00:00 2001 From: Patrick Detlefsen Date: Thu, 23 Oct 2025 14:40:32 +0200 Subject: [PATCH 3/3] Fix CSV field formatting for DATEV API compliance Update StringField and IntegerField output methods to correctly handle nil and empty values according to DATEV CSV format specifications. Changes: - StringField now returns empty string instead of quoted empty string for nil/empty values, ensuring reserved fields are completely empty - IntegerField explicitly returns empty string for nil values - Update tests to verify new nil/empty value handling - Regenerate example CSV files with correct format This resolves validation errors from DATEV Buchungsdatenservice API where reserved fields must be completely empty (no quotes). --- examples/EXTF_Buchungsstapel.csv | 8 ++++---- examples/EXTF_Kontenbeschriftungen.csv | 2 +- examples/EXTF_Stammdaten.csv | 10 +++++----- lib/datev/field/integer_field.rb | 6 +++++- lib/datev/field/string_field.rb | 5 +++++ spec/datev/export/contact_export_spec.rb | 2 +- spec/datev/field/integer_field_spec.rb | 8 +++++++- spec/datev/field/string_field_spec.rb | 8 ++++++-- 8 files changed, 34 insertions(+), 15 deletions(-) diff --git a/examples/EXTF_Buchungsstapel.csv b/examples/EXTF_Buchungsstapel.csv index 9f61f9c..7477670 100644 --- a/examples/EXTF_Buchungsstapel.csv +++ b/examples/EXTF_Buchungsstapel.csv @@ -1,4 +1,4 @@ -"EXTF";700;21;"Buchungsstapel";9;20180306102500000;;"XY";"Chief Accounting Officer";"";1001;456;20180101;4;20180201;20180228;"Beispiel-Buchungen";"";1;;0;"EUR";"";"";"";"";"";;;"";"" -Umsatz (ohne Soll/Haben-Kz);Soll/Haben-Kennzeichen;WKZ Umsatz;Kurs;Basisumsatz;WKZ Basisumsatz;Konto;Gegenkonto (ohne BU-Schlüssel);BU-Schlüssel;Belegdatum;Belegfeld 1;Belegfeld 2;Skonto;Buchungstext;Postensperre;Diverse Adressnummer;Geschäftspartnerbank;Sachverhalt;Zinssperre;Beleglink;Beleginfo – Art 1;Beleginfo – Inhalt 1;Beleginfo – Art 2;Beleginfo – Inhalt 2;Beleginfo – Art 3;Beleginfo – Inhalt 3;Beleginfo – Art 4;Beleginfo – Inhalt 4;Beleginfo – Art 5;Beleginfo – Inhalt 5;Beleginfo – Art 6;Beleginfo – Inhalt 6;Beleginfo – Art 7;Beleginfo – Inhalt 7;Beleginfo – Art 8;Beleginfo – Inhalt 8;KOST1 – Kostenstelle;KOST2 – Kostenstelle;Kost Menge;EU-Land u. USt-IdNr.;EU-Steuersatz;Abw. Versteuerungsart;Sachverhalt L+L;Funktionsergänzung L+L;BU 49 Hauptfunktionstyp;BU 49 Hauptfunktionsnummer;BU 49 Funktionsergänzung;Zusatzinformation – Art 1;Zusatzinformation – Inhalt 1;Zusatzinformation – Art 2;Zusatzinformation – Inhalt 2;Zusatzinformation – Art 3;Zusatzinformation – Inhalt 3;Zusatzinformation – Art 4;Zusatzinformation – Inhalt 4;Zusatzinformation – Art 5;Zusatzinformation – Inhalt 5;Zusatzinformation – Art 6;Zusatzinformation – Inhalt 6;Zusatzinformation – Art 7;Zusatzinformation – Inhalt 7;Zusatzinformation – Art 8;Zusatzinformation – Inhalt 8;Zusatzinformation – Art 9;Zusatzinformation – Inhalt 9;Zusatzinformation – Art 10;Zusatzinformation – Inhalt 10;Zusatzinformation – Art 11;Zusatzinformation – Inhalt 11;Zusatzinformation – Art 12;Zusatzinformation – Inhalt 12;Zusatzinformation – Art 13;Zusatzinformation – Inhalt 13;Zusatzinformation – Art 14;Zusatzinformation – Inhalt 14;Zusatzinformation – Art 15;Zusatzinformation – Inhalt 15;Zusatzinformation – Art 16;Zusatzinformation – Inhalt 16;Zusatzinformation – Art 17;Zusatzinformation – Inhalt 17;Zusatzinformation – Art 18;Zusatzinformation – Inhalt 18;Zusatzinformation – Art 19;Zusatzinformation – Inhalt 19;Zusatzinformation – Art 20;Zusatzinformation – Inhalt 20;Stück;Gewicht;Zahlweise;Forderungsart;Veranlagungsjahr;Zugeordnete Fälligkeit;Skontotyp;Auftragsnummer;Buchungstyp;USt-Schlüssel (Anzahlungen);EU-Mitgliedstaat (Anzahlungen);Sachverhalt L+L (Anzahlungen);EU-Steuersatz (Anzahlungen);Erlöskonto (Anzahlungen);Herkunft-Kz;Leerfeld;KOST-Datum;SEPA-Mandatsreferenz;Skontosperre;Gesellschaftername;Beteiligtennummer;Identifikationsnummer;Zeichnernummer;Postensperre bis;Bezeichnung;Kennzeichen;Festschreibung;Leistungsdatum;Datum Zuord.;Fälligkeit;Generalumkehr;Steuersatz;Land -24,95;"H";"";;;"";1200;4940;"8";2102;"";"";;"Fachbuch: Controlling für Dummies";;"";;;;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;"";;"";;;;;;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;;"";;;;"";"";;"";;;;"";"";;"";;"";;"";"";;"";;;;;;"";;"" -5950,00;"S";"";;;"";10000;8400;"";2202;"RE201802-135";"";;"Honorar FiBu-Seminar";;"";;;;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;"";;"";;;;;;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;;"";;;;"";"";;"";;;;"";"";;"";;"";;"";"";;"";;;;;;"";;"" +"EXTF";700;21;"Buchungsstapel";13;20180306102500000;;"XY";"Chief Accounting Officer";;1001;456;20180101;4;20180201;20180228;"Beispiel-Buchungen";;1;;0;"EUR";;;;;;;;; +Umsatz (ohne Soll/Haben-Kz);Soll/Haben-Kennzeichen;WKZ Umsatz;Kurs;Basisumsatz;WKZ Basisumsatz;Konto;Gegenkonto (ohne BU-Schlüssel);BU-Schlüssel;Belegdatum;Belegfeld 1;Belegfeld 2;Skonto;Buchungstext;Postensperre;Diverse Adressnummer;Geschäftspartnerbank;Sachverhalt;Zinssperre;Beleglink;Beleginfo – Art 1;Beleginfo – Inhalt 1;Beleginfo – Art 2;Beleginfo – Inhalt 2;Beleginfo – Art 3;Beleginfo – Inhalt 3;Beleginfo – Art 4;Beleginfo – Inhalt 4;Beleginfo – Art 5;Beleginfo – Inhalt 5;Beleginfo – Art 6;Beleginfo – Inhalt 6;Beleginfo – Art 7;Beleginfo – Inhalt 7;Beleginfo – Art 8;Beleginfo – Inhalt 8;KOST1 – Kostenstelle;KOST2 – Kostenstelle;Kost Menge;EU-Land u. USt-IdNr.;EU-Steuersatz;Abw. Versteuerungsart;Sachverhalt L+L;Funktionsergänzung L+L;BU 49 Hauptfunktionstyp;BU 49 Hauptfunktionsnummer;BU 49 Funktionsergänzung;Zusatzinformation – Art 1;Zusatzinformation – Inhalt 1;Zusatzinformation – Art 2;Zusatzinformation – Inhalt 2;Zusatzinformation – Art 3;Zusatzinformation – Inhalt 3;Zusatzinformation – Art 4;Zusatzinformation – Inhalt 4;Zusatzinformation – Art 5;Zusatzinformation – Inhalt 5;Zusatzinformation – Art 6;Zusatzinformation – Inhalt 6;Zusatzinformation – Art 7;Zusatzinformation – Inhalt 7;Zusatzinformation – Art 8;Zusatzinformation – Inhalt 8;Zusatzinformation – Art 9;Zusatzinformation – Inhalt 9;Zusatzinformation – Art 10;Zusatzinformation – Inhalt 10;Zusatzinformation – Art 11;Zusatzinformation – Inhalt 11;Zusatzinformation – Art 12;Zusatzinformation – Inhalt 12;Zusatzinformation – Art 13;Zusatzinformation – Inhalt 13;Zusatzinformation – Art 14;Zusatzinformation – Inhalt 14;Zusatzinformation – Art 15;Zusatzinformation – Inhalt 15;Zusatzinformation – Art 16;Zusatzinformation – Inhalt 16;Zusatzinformation – Art 17;Zusatzinformation – Inhalt 17;Zusatzinformation – Art 18;Zusatzinformation – Inhalt 18;Zusatzinformation – Art 19;Zusatzinformation – Inhalt 19;Zusatzinformation – Art 20;Zusatzinformation – Inhalt 20;Stück;Gewicht;Zahlweise;Forderungsart;Veranlagungsjahr;Zugeordnete Fälligkeit;Skontotyp;Auftragsnummer;Buchungstyp;USt-Schlüssel (Anzahlungen);EU-Mitgliedstaat (Anzahlungen);Sachverhalt L+L (Anzahlungen);EU-Steuersatz (Anzahlungen);Erlöskonto (Anzahlungen);Herkunft-Kz;Leerfeld;KOST-Datum;SEPA-Mandatsreferenz;Skontosperre;Gesellschaftername;Beteiligtennummer;Identifikationsnummer;Zeichnernummer;Postensperre bis;Bezeichnung;Kennzeichen;Festschreibung;Leistungsdatum;Datum Zuord.;Fälligkeit;Generalumkehr;Steuersatz;Land;Abrechnungsreferent;BVV-Position;EU-Mitgliedstaat u. UStID (Ursprung);EU-Steuersatz (Ursprung);Abw. Skontokonto +24,95;"H";;;;;1200;4940;"8";2102;;;;"Fachbuch: Controlling für Dummies";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +5950,00;"S";;;;;10000;8400;;2202;"RE201802-135";;;"Honorar FiBu-Seminar";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/examples/EXTF_Kontenbeschriftungen.csv b/examples/EXTF_Kontenbeschriftungen.csv index ad968b6..8de488c 100644 --- a/examples/EXTF_Kontenbeschriftungen.csv +++ b/examples/EXTF_Kontenbeschriftungen.csv @@ -1,4 +1,4 @@ -"EXTF";700;20;"Kontenbeschriftungen";2;20180223152500000;;"XY";"Chief Accounting Officer";"";1001;456;20180101;4;;;"Beispiel-Konten";"";;;;"";"";"";"";"";"";;;"";"" +"EXTF";700;20;"Kontenbeschriftungen";2;20180223152500000;;"XY";"Chief Accounting Officer";;1001;456;20180101;4;;;"Beispiel-Konten";;;;;;;;;;;;;; Konto;Kontenbeschriftung;Sprach-ID 400;"Betriebsausstattung";"de-DE" 1000;"Kasse";"de-DE" diff --git a/examples/EXTF_Stammdaten.csv b/examples/EXTF_Stammdaten.csv index 9560a22..336daf9 100644 --- a/examples/EXTF_Stammdaten.csv +++ b/examples/EXTF_Stammdaten.csv @@ -1,6 +1,6 @@ -"EXTF";700;16;"Debitoren/Kreditoren";5;20180306102500000;;"XY";"Chief Accounting Officer";"";1001;456;20180101;4;;;"Kunden und Lieferanten";"";;;;"";"";"";"";"";"";;;"";"" +"EXTF";700;16;"Debitoren/Kreditoren";5;20180306102500000;;"XY";"Chief Accounting Officer";;1001;456;20180101;4;;;"Kunden und Lieferanten";;;;;;;;;;;;;; Konto;Name (Adressatentyp Unternehmen);Unternehmensgegenstand;Name (Adressatentyp natürl. Person);Vorname (Adressatentyp natürl. Person);Name (Adressatentyp keine Angabe);Adressatentyp;Kurzbezeichnung;EU-Land;EU-USt-IdNr.;Anrede;Titel/Akad. Grad;Adelstitel;Namensvorsatz;Adressart;Straße;Postfach;Postleitzahl;Ort;Land;Versandzusatz;Adresszusatz;Abweichende Anrede;Abw. Zustellbezeichnung 1;Abw. Zustellbezeichnung 2;Kennz. Korrespondenzadresse;Adresse Gültig von;Adresse Gültig bis;Telefon;Bemerkung (Telefon);Telefon Geschäftsleitung;Bemerkung (Telefon GL);E-Mail;Bemerkung (E-Mail);Internet;Bemerkung (Internet);Fax;Bemerkung (Fax);Sonstige;Bemerkung (Sonstige);Bankleitzahl 1;Bankbezeichnung 1;Bankkonto-Nummer 1;Länderkennzeichen 1;IBAN 1;Leerfeld 1;SWIFT-Code 1;Abw. Kontoinhaber 1;Kennz. Haupt-Bankverb. 1;Bankverb. 1 Gültig von;Bankverb. 1 Gültig bis;Bankleitzahl 2;Bankbezeichnung 2;Bankkonto-Nummer 2;Länderkennzeichen 2;IBAN 2;Leerfeld 2;SWIFT-Code 2;Abw. Kontoinhaber 2;Kennz. Haupt-Bankverb. 2;Bankverb. 2 Gültig von;Bankverb. 2 Gültig bis;Bankleitzahl 3;Bankbezeichnung 3;Bankkonto-Nummer 3;Länderkennzeichen 3;IBAN 3;Leerfeld 3;SWIFT-Code 3;Abw. Kontoinhaber 3;Kennz. Haupt-Bankverb. 3;Bankverb. 3 Gültig von;Bankverb. 3 Gültig bis;Bankleitzahl 4;Bankbezeichnung 4;Bankkonto-Nummer 4;Länderkennzeichen 4;IBAN 4;Leerfeld 4;SWIFT-Code 4;Abw. Kontoinhaber 4;Kennz. Haupt-Bankverb. 4;Bankverb. 4 Gültig von;Bankverb. 4 Gültig bis;Bankleitzahl 5;Bankbezeichnung 5;Bankkonto-Nummer 5;Länderkennzeichen 5;IBAN 5;Leerfeld 5;SWIFT-Code 5;Abw. Kontoinhaber 5;Kennz. Haupt-Bankverb. 5;Bankverb. 5 Gültig von;Bankverb. 5 Gültig bis;Leerfeld 11;Briefanrede;Grußformel;Kundennummer;Steuernummer;Sprache;Ansprechpartner;Vertreter;Sachbearbeiter;Diverse-Konto;Ausgabeziel;Währungssteuerung;Kreditlimit (Debitor);Zahlungsbedingung;Fälligkeit in Tagen (Debitor);Skonto in Prozent (Debitor);Kreditoren-Ziel 1 (Tage);Kreditoren-Skonto 1 (%);Kreditoren-Ziel 2 (Tage);Kreditoren-Skonto 2 (%);Kreditoren-Ziel 3 Brutto (Tage);Kreditoren-Ziel 4 (Tage);Kreditoren-Skonto 4 (%);Kreditoren-Ziel 5 (Tage);Kreditoren-Skonto 5 (%);Mahnung;Kontoauszug;Mahntext;Mahntext 2;Mahntext 3;Kontoauszugstext;Mahnlimit Betrag;Mahnlimit %;Zinsberechnung;Mahnzinssatz 1;Mahnzinssatz 2;Mahnzinssatz 3;Lastschrift;Verfahren;Mandantenbank;Zahlungsträger;Indiv. Feld 1;Indiv. Feld 2;Indiv. Feld 3;Indiv. Feld 4;Indiv. Feld 5;Indiv. Feld 6;Indiv. Feld 7;Indiv. Feld 8;Indiv. Feld 9;Indiv. Feld 10;Indiv. Feld 11;Indiv. Feld 12;Indiv. Feld 13;Indiv. Feld 14;Indiv. Feld 15;Abweichende Anrede (Rechnungsadresse);Adressart (Rechnungsadresse);Straße (Rechnungsadresse);Postfach (Rechnungsadresse);Postleitzahl (Rechnungsadresse);Ort (Rechnungsadresse);Land (Rechnungsadresse);Versandzusatz (Rechnungsadresse);Adresszusatz (Rechnungsadresse);Abw. Zustellbezeichnung 1 (Rechnungsadresse);Abw. Zustellbezeichnung 2 (Rechnungsadresse);Adresse Gültig von (Rechnungsadresse);Adresse Gültig bis (Rechnungsadresse);Bankleitzahl 6;Bankbezeichnung 6;Bankkonto-Nummer 6;Länderkennzeichen 6;IBAN 6;Leerfeld 6;SWIFT-Code 6;Abw. Kontoinhaber 6;Kennz. Haupt-Bankverb. 6;Bankverb. 6 Gültig von;Bankverb. 6 Gültig bis;Bankleitzahl 7;Bankbezeichnung 7;Bankkonto-Nummer 7;Länderkennzeichen 7;IBAN 7;Leerfeld 7;SWIFT-Code 7;Abw. Kontoinhaber 7;Kennz. Haupt-Bankverb. 7;Bankverb. 7 Gültig von;Bankverb. 7 Gültig bis;Bankleitzahl 8;Bankbezeichnung 8;Bankkonto-Nummer 8;Länderkennzeichen 8;IBAN 8;Leerfeld 8;SWIFT-Code 8;Abw. Kontoinhaber 8;Kennz. Haupt-Bankverb. 8;Bankverb. 8 Gültig von;Bankverb. 8 Gültig bis;Bankleitzahl 9;Bankbezeichnung 9;Bankkonto-Nummer 9;Länderkennzeichen 9;IBAN 9;Leerfeld 9;SWIFT-Code 9;Abw. Kontoinhaber 9;Kennz. Haupt-Bankverb. 9;Bankverb. 9 Gültig von;Bankverb. 9 Gültig bis;Bankleitzahl 10;Bankbezeichnung 10;Bankkonto-Nummer 10;Länderkennzeichen 10;IBAN 10;Leerfeld 10;SWIFT-Code 10;Abw. Kontoinhaber 10;Kennz. Haupt-Bankverb. 10;Bankverb. 10 Gültig von;Bankverb. 10 Gültig bis;Nummer Fremdsystem;Insolvent;SEPA-Mandatsreferenz 1;SEPA-Mandatsreferenz 2;SEPA-Mandatsreferenz 3;SEPA-Mandatsreferenz 4;SEPA-Mandatsreferenz 5;SEPA-Mandatsreferenz 6;SEPA-Mandatsreferenz 7;SEPA-Mandatsreferenz 8;SEPA-Mandatsreferenz 9;SEPA-Mandatsreferenz 10;Verknüpftes OPOS-Konto;Mahnsperre bis;Lastschriftsperre bis;Zahlungssperre bis;Gebührenberechnung;Mahngebühr 1;Mahngebühr 2;Mahngebühr 3;Pauschalberechnung;Verzugspauschale 1;Verzugspauschale 2;Verzugspauschale 3;Alternativer Suchname;Status;Anschrift manuell geändert (Korrespondenzadresse);Anschrift individuell (Korrespondenzadresse);Anschrift manuell geändert (Rechnungsadresse);Anschrift individuell (Rechnungsadresse);Fristberechnung bei Debitor;Mahnfrist 1;Mahnfrist 2;Mahnfrist 3;Letzte Frist -10000;"";"";"Mustermann";"Sabine";"";"1";"";"";"";"Frau";"Dr.";"";"";"STR";"Am Haagelspfädchen 14";"";"50999";"Köln";"DE";"";"";"";"";"";;;;"0221/1234567";"";"";"";"sabine@mustermann.de";"";"www.mustermann.de";"";"0221/1234568";"";"";"";"";"";"";"";"DE12500105170648489890";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;;"Sehr geehrte Frau Dr. Mustermann";"";"";"";1;"";"";"";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"";"";;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";;"";"";"";"";"";"";"";"";"";"";;;;;;;;;;;;;"";;;"";;"";;;;; -70001;"Meyer GmbH";"";"";"";"";"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;;"";"";"";"";;"";"";"";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"";"";;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";;"";"";"";"";"";"";"";"";"";"";;;;;;;;;;;;;"";;;"";;"";;;;; -70002;"Schulze GmbH";"";"";"";"";"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;;"";"";"";"";;"";"";"";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"";"";;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";;"";"";"";"";"";"";"";"";"";"";;;;;;;;;;;;;"";;;"";;"";;;;; -70003;"Scary Kitten AG";"";"";"";"";"2";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;;"";"";"";"";;"";"";"";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"";"";;"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";"";;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";"";"";"";"";"";"";"";;;;"";;"";"";"";"";"";"";"";"";"";"";;;;;;;;;;;;;"";;;"";;"";;;;; +10000;;;"Mustermann";"Sabine";;"1";;;;"Frau";"Dr.";;;"STR";"Am Haagelspfädchen 14";;"50999";"Köln";"DE";;;;;;;;;"0221/1234567";;;;"sabine@mustermann.de";;"www.mustermann.de";;"0221/1234568";;;;;;;;"DE12500105170648489890";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"Sehr geehrte Frau Dr. Mustermann";;;;1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +70001;"Meyer GmbH";;;;;"2";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +70002;"Schulze GmbH";;;;;"2";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +70003;"Scary Kitten AG";;;;;"2";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/lib/datev/field/integer_field.rb b/lib/datev/field/integer_field.rb index fd0b726..9020674 100644 --- a/lib/datev/field/integer_field.rb +++ b/lib/datev/field/integer_field.rb @@ -24,7 +24,11 @@ def validate!(value) end def output(value, _context=nil) - value.to_s if value + # Return empty string for nil values (required for DATEV reserved fields) + return '' if value.nil? + + # Return bare integer value without quotes (DATEV CSV format requirement) + value.to_s end end end diff --git a/lib/datev/field/string_field.rb b/lib/datev/field/string_field.rb index d934fc4..cb2eacb 100644 --- a/lib/datev/field/string_field.rb +++ b/lib/datev/field/string_field.rb @@ -19,6 +19,11 @@ def validate!(value) end def output(value, _context=nil) + # If value is nil or empty, return empty string (no quotes) + # This is required for DATEV's reserved fields which MUST be completely empty + return '' if value.nil? || (value.respond_to?(:empty?) && value.empty?) + + # Original behavior for non-empty values value = value.slice(0, limit || 255) if value quote(value) diff --git a/spec/datev/export/contact_export_spec.rb b/spec/datev/export/contact_export_spec.rb index bff689c..1a2e131 100644 --- a/spec/datev/export/contact_export_spec.rb +++ b/spec/datev/export/contact_export_spec.rb @@ -87,7 +87,7 @@ end it "should contain accounts" do - expect(subject.lines[2]).to include('10000;"";"";"Mustermann"') + expect(subject.lines[2]).to include('10000;;;"Mustermann"') expect(subject.lines[3]).to include('70001;"Meyer GmbH"') expect(subject.lines[4]).to include('70002;"Schulze GmbH"') end diff --git a/spec/datev/field/integer_field_spec.rb b/spec/datev/field/integer_field_spec.rb index 1a48dcf..a669a51 100644 --- a/spec/datev/field/integer_field_spec.rb +++ b/spec/datev/field/integer_field_spec.rb @@ -29,8 +29,14 @@ end describe :output do - it "should return value as string" do + it "should return value as unquoted string (DATEV CSV format requirement)" do expect(subject.output(1)).to eq('1') + expect(subject.output(700)).to eq('700') + expect(subject.output(42)).to eq('42') + end + + it "should return empty string for nil value (DATEV reserved fields requirement)" do + expect(subject.output(nil)).to eq('') end end end diff --git a/spec/datev/field/string_field_spec.rb b/spec/datev/field/string_field_spec.rb index 187d019..7d4173f 100644 --- a/spec/datev/field/string_field_spec.rb +++ b/spec/datev/field/string_field_spec.rb @@ -27,8 +27,12 @@ expect(subject.output('foo')).to eq('"foo"') end - it "should quote nil value" do - expect(subject.output(nil)).to eq('""') + it "should return empty string for nil value (DATEV reserved fields requirement)" do + expect(subject.output(nil)).to eq('') + end + + it "should return empty string for empty string value" do + expect(subject.output('')).to eq('') end it "should handle single quotes" do