diff --git a/assets/gdpdu-01-09-2004.dtd b/assets/gdpdu-01-09-2004.dtd new file mode 100644 index 0000000..8a96a97 --- /dev/null +++ b/assets/gdpdu-01-09-2004.dtd @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/index.xml b/assets/index.xml new file mode 100644 index 0000000..8ba98b6 --- /dev/null +++ b/assets/index.xml @@ -0,0 +1,1640 @@ + + + + 1.0 + + + + Datentraegerueberlassung nach GDPdU vom 12.11.2010 + + + CD Nummer 1 + + cashpointclosing.csv + Stamm_Abschluss + cashpointclosing.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + Z_BUCHUNGSTAG + Vom Erstellungsdatum abweichender Verbuchungstag + + 25 + + + TAXONOMIE_VERSION + Version der DFKA-Taxonomie-Kasse + + 10 + + + Z_START_ID + Erste BON_ID im Abschluss + + 40 + + + Z_ENDE_ID + Letzte BON_ID im Abschluss + + 40 + + + NAME + Name des Unternehmens + + 60 + + + STRASSE + Straße + + 60 + + + PLZ + Postleitzahl + + 10 + + + ORT + Ort + + 62 + + + LAND + Land + + 3 + + + STNR + Steuernummer des Unternehmens + + 20 + + + USTID + USTID + + 15 + + + Z_SE_ZAHLUNGEN + Summe aller Zahlungen + + 2 + + + + Z_SE_BARZAHLUNGEN + Summe aller Barzahlungen + + 2 + + + +
+ + location.csv + Stamm_Orte + location.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + LOC_NAME + Name des Standortes + + 60 + + + LOC_STRASSE + Straße + + 60 + + + LOC_PLZ + Postleitzahl + + 10 + + + LOC_ORT + Ort + + 62 + + + LOC_LAND + Land + + 3 + + + LOC_USTID + USTID + + 15 + + +
+ + cashregister.csv + Stamm_Kassen + cashregister.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + KASSE_BRAND + Marke der Kasse + + 50 + + + KASSE_MODELL + Modellbezeichnung + + 50 + + + KASSE_SERIENNR + Seriennummer der Kasse + + 70 + + + KASSE_SW_BRAND + Markenbezeichnung der Software + + 50 + + + KASSE_SW_VERSION + Version der Software + + 50 + + + KASSE_BASISWAEH_CODE + Basiswährung der Kasse + + 3 + + + KEINE_UST_ZUORDNUNG + UmsatzsteuerNichtErmittelbar (bei späterem Zahlungseingang) + + 1 + + +
+ + slaves.csv + Stamm_Terminals + slaves.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + TERMINAL_ID + ID des Terminals + + 50 + + + TERMINAL_BRAND + Marke der Terminals + + 50 + + + TERMINAL_MODELL + Modellbezeichnung des Terminals + + 50 + + + TERMINAL_SERIENNR + Seriennummer des Terminals + + 70 + + + TERMINAL_SW_BRAND + Markenbezeichnung der Software + + 50 + + + TERMINAL_SW_VERSION + Version der Software + + 50 + + +
+ + pa.csv + Stamm_Agenturen + pa.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + AGENTUR_ID + ID der Agentur + + + + AGENTUR_NAME + Name des Auftraggebers + + 60 + + + AGENTUR_STRASSE + Straße + + 60 + + + AGENTUR_PLZ + Postleitzahl + + 10 + + + AGENTUR_ORT + Ort + + 62 + + + AGENTUR_LAND + Land + + 3 + + + AGENTUR_STNR + Steuernummer des Auftraggebers + + 20 + + + AGENTUR_USTID + USTID des Auftraggebers + + 15 + + +
+ + tse.csv + Stamm_TSE + tse.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + TSE_ID + ID der TSE - wird nur zur Referenzierung innerhalb eines Kassenabschlusses verwendet + + + + TSE_SERIAL + Seriennummer der TSE (Entspricht laut TR-03153 Abschnitt 7.5. dem Hashwert des im Zertifikat enthaltenen Schlüssels in Octet-String-Darstellung) + + 68 + + + TSE_SIG_ALGO + Der von der TSE verwendete Signaturalgo-rithmus + + 21 + + + TSE_ZEITFORMAT + Das von der TSE verwendete Format für die Log-Time - 'unixTime', 'utcTime' = YYMMDDhhmmZ, 'utcTimeWithSeconds' = YYMMDDhhmmssZ, 'generalizedTime' = YYYYMMDDhhmmssZ, 'generalizedTimeWithMilliseconds' = YYYYMMDDhhmmss.fffZ + + 31 + + + TSE_PD_ENCODING + Das Text-Encoding der ProcessData (UTF-8 oder ASCII) + + 5 + + + TSE_PUBLIC_KEY + Öffentlicher Schlüssel - extrahiert aus dem Zertifikat der TSE - in base64-Codierung + + 512 + + + TSE_ZERTIFIKAT_I + Erste 1000 Zeichen des base64-codierten Zertifikats der TSE (in base64-Codierung) + + 1000 + + + TSE_ZERTIFIKAT_II + Ggf. Rest des base64-codierten Zertifikats der TSE (in base64-Codierung) + + 1000 + + +
+ + vat.csv + Stamm_USt + vat.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + UST_SCHLUESSEL + ID des Umsatzsteuersatzes + + + + UST_SATZ + Prozentsatz + + 2 + + + + UST_BESCHR + Beschreibung + + 55 + + +
+ + businesscases.csv + Z_GV_Typ + businesscases.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + GV_TYP + Geschäftsvorfall-Art + + 30 + + + GV_NAME + Name des Geschäftsvorfalls + + 40 + + + AGENTUR_ID + ID der Agentur + + + + UST_SCHLUESSEL + ID des USt-Satzes + + + + Z_UMS_BRUTTO + Bruttoumsatz + + 5 + + + + Z_UMS_NETTO + Nettoumsatz + + 5 + + + + Z_UST + Umsatzsteuer + + 5 + + + +
+ + payment.csv + Z_Zahlart + payment.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + ZAHLART_TYP + Typ der Zahlart + + 25 + + + ZAHLART_NAME + Name der Zahlart + + 60 + + + Z_ZAHLART_BETRAG + Betrag + + 2 + + + +
+ + cash_per_currency.csv + Z_Waehrungen + cash_per_currency.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + ZAHLART_WAEH + Währung + + 3 + + + ZAHLART_BETRAG_WAEH + Betrag + + 2 + + + +
+ + transactions.csv + Bonkopf + transactions.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + BON_NR + Bonnummer + + + + BON_TYP + Bontyp + + 30 + + + BON_NAME + Zusatz-Beschreibung zum Bontyp + + 60 + + + TERMINAL_ID + ID des Erfassungsterminals + + 50 + + + BON_STORNO + Storno-Kennzeichen + + 1 + + + BON_START + Zeitpunkt des Vorgangsstarts + + 30 + + + BON_ENDE + Zeitpunkt der Vorgangsbeendigung + + 30 + + + BEDIENER_ID + Bediener-ID + + 50 + + + BEDIENER_NAME + Bediener-Name + + 50 + + + UMS_BRUTTO + Brutto-Gesamtumsatz + + 2 + + + + KUNDE_NAME + Name des Leistungsempfängers + + 50 + + + KUNDE_ID + Kundennummer des Leistungsempfängers + + 50 + + + KUNDE_TYP + Art des Leistungsempfängers (z. B. Mitarbeiter) + + 50 + + + KUNDE_STRASSE + Straße und Hausnummer des Leistungsempfängers + + 60 + + + KUNDE_PLZ + PLZ des Leistungsempfängers + + 10 + + + KUNDE_ORT + Ort des Leistungsempfängers + + 62 + + + KUNDE_LAND + Land des Leistungsempfängers + + 3 + + + KUNDE_USTID + UStID des Leistungsempfängers + + 15 + + + BON_NOTIZ + Zusätzliche Informationen zum Bonkopf + + 255 + + +
+ + datapayment.csv + Bonkopf_Zahlarten + datapayment.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + ZAHLART_TYP + Typ der Zahlart + + 25 + + + ZAHLART_NAME + Name der Zahlart + + 60 + + + ZAHLWAEH_CODE + Währungscode + + 3 + + + ZAHLWAEH_BETRAG + Betrag in Fremdwährung + + 2 + + + + BASISWAEH_BETRAG + Betrag in Basiswährung (i.d.R. EUR) + + 2 + + + +
+ + lines.csv + Bonpos + lines.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + POS_ZEILE + Zeilennummer + + 50 + + + GUTSCHEIN_NR + Gutschein-Nr. + + 50 + + + ARTIKELTEXT + Artikeltext + + 255 + + + POS_TERMINAL_ID + ID des POS-Terminals + + 50 + + + GV_TYP + Geschäftsvorfall-Art + + 30 + + + GV_NAME + Name des Geschäftsvorfalls + + 40 + + + INHAUS + Verzehr an Ort und Stelle + + 1 + + + P_STORNO + Positionsstorno-Kennzeichnung + + 1 + + + AGENTUR_ID + ID der Agentur + + + + ART_NR + Artikelnummer + + 50 + + + GTIN + GTIN + + 50 + + + WARENGR_ID + Warengruppen-ID + + 40 + + + WARENGR + Bezeichnung Warengruppe + + 50 + + + MENGE + Menge + + 3 + + + + FAKTOR + Faktor, z. B. Gebindegrößen + + 3 + + + + EINHEIT + Maßeinheit, z. B. kg, Liter oder Stück + + 50 + + + STK_BR + Preis pro Einheit inkl. USt + + 5 + + + +
+ + itemamounts.csv + Bonpos_Preisfindung + itemamounts.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + POS_ZEILE + Zeilennummer + + 50 + + + TYP + Basispreis, Rabatt oder Zuschlag + + 20 + + + UST_SCHLUESSEL + ID des USt-Satzes + + + + PF_BRUTTO + Bruttoumsatz + + 5 + + + + PF_NETTO + Nettoumsatz + + 5 + + + + PF_UST + Umsatzsteuer + + 5 + + + +
+ + subitems.csv + Bonpos_Zusatzinfo + subitems.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + POS_ZEILE + Zeilennummer + + 50 + + + ZI_ART_NR + Artikelnummer + + 50 + + + ZI_GTIN + GTIN + + 50 + + + ZI_NAME + Artikelbezeichnung + + 60 + + + ZI_WARENGR_ID + Warengruppen-ID + + 40 + + + ZI_WARENGR + Bezeichnung Warengruppe + + 50 + + + ZI_MENGE + Menge + + 3 + + + + ZI_FAKTOR + Faktor, z. B. Gebindegrößen + + 3 + + + + ZI_EINHEIT + Maßeinheit, z. B. kg, Liter oder Stück + + 50 + + + ZI_UST_SCHLUESSEL + ID USt-Satz des Basispreises + + + + ZI_BASISPREIS_BRUTTO + Basispreis brutto + + 5 + + + + ZI_BASISPREIS_NETTO + Basispreis netto + + 5 + + + + ZI_BASISPREIS_UST + Basispreis USt + + 5 + + + +
+ + transactions_tse.csv + TSE_Transaktionen + transactions_tse.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + TSE_ID + Die Id der für eine Transaktion verwendeten TSE + + + + TSE_TANR + Die Transaktionsnummer der TSE-Transaktion + + + + TSE_TA_START + Die Log-Time der StartTransaction-Operation + + 30 + + + TSE_TA_ENDE + Die Log-Time der FinishTransaction-Operation + + 30 + + + TSE_TA_VORGANGSART + Der processType der FinishTransaction-Operation + + 30 + + + TSE_TA_SIGZ + Der Signaturzähler der FinishTransaction-Operation + + + + TSE_TA_SIG + Die Signatur der FinishTransaction-Operation + + 512 + + + TSE_TA_FEHLER + Beschreibung des TSE-Ausfalls oder Fehlers + + 200 + + + TSE_VORGANGSDATEN + An die zertifizierte technische Sicherheitseinrichtung übergebene Daten des Vorgangs (optional) + + 1000 + + +
+ + transactions_vat.csv + Bonkopf_USt + transactions_vat.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + UST_SCHLUESSEL + ID des USt-Satzes + + + + BON_BRUTTO + Bruttoumsatz + + 5 + + + + BON_NETTO + Nettoumsatz + + 5 + + + + BON_UST + Umsatzsteuer + + 5 + + + +
+ + lines_vat.csv + Bonpos_USt + lines_vat.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + POS_ZEILE + Zeilennummer + + 50 + + + UST_SCHLUESSEL + ID des USt-Satzes + + + + POS_BRUTTO + Bruttoumsatz + + 5 + + + + POS_NETTO + Nettoumsatz + + 5 + + + + POS_UST + Umsatzsteuer + + 5 + + + +
+ + allocation_groups.csv + Bonkopf_AbrKreis + allocation_groups.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + ABRECHNUNGSKREIS + z. B. Tischnummer + + 50 + + +
+ + references.csv + Bon_Referenzen + references.csv + + , + . + + 2 + + + ; + + " + + Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + Z_ERSTELLUNG + Zeitpunkt des Kassenabschlusses + + 30 + + + Z_NR + Nr. des Kassenabschlusses + + + + BON_ID + Vorgangs-ID + + 40 + + + POS_ZEILE + Zeilennummer des referenzierenden Vorgangs (nicht bei Verweis aus einem Bonkopf heraus) + + 50 + + + REF_TYP + Art der Referenz + + 20 + + + REF_NAME + Beschreibung bei Art “ExterneSonstige” + + 40 + + + REF_DATUM + Datum des Kassenabschlusses + + 30 + + + REF_Z_KASSE_ID + ID der (Abschluss-) Kasse + + 50 + + + REF_Z_NR + Nr. des Kassenabschlusses + + + + REF_BON_ID + Vorgangs-ID + + 40 + + +
+
+
\ No newline at end of file diff --git a/dsfinvk/collection.py b/dsfinvk/collection.py index fece4c3..8b10980 100644 --- a/dsfinvk/collection.py +++ b/dsfinvk/collection.py @@ -1,20 +1,22 @@ import csv +import os from collections import defaultdict from io import StringIO +from tempfile import TemporaryFile, NamedTemporaryFile from zipfile import ZipFile +from lxml import etree from .table import Model class Collection: - def __init__(self): self.records = defaultdict(list) def add(self, record: Model): self.records[record._filename].append(record) - def write(self, name, xml_path, dtd_path): + def write(self, name, xml_path=None, dtd_path=None): with ZipFile(name, 'w') as zf: for k, l in self.records.items(): b = StringIO() @@ -25,5 +27,49 @@ def write(self, name, xml_path, dtd_path): w.writerow(r._data) b.seek(0) zf.writestr(k, b.read()) - zf.write(xml_path, 'index.xml') - zf.write(dtd_path, 'gdpdu-01-08-2002.dtd') \ No newline at end of file + + if not xml_path: + xml_path, dtd_path = self.generate_xml() + zf.write(xml_path, 'index.xml') + zf.write(dtd_path, os.path.basename(dtd_path)) + os.unlink(xml_path) + else: + zf.write(xml_path, 'index.xml') + zf.write(dtd_path, os.path.basename(dtd_path)) + + def find_asset(self, fn): + dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../assets')) + f = os.path.join(dir, fn) + if os.path.exists(f): + return f + return None + + def generate_xml(self): + xml_file = self.find_asset('index.xml') + if not xml_file: + raise RuntimeError('cannot find bundled index.xml') + parser = etree.XMLParser(load_dtd=True, resolve_entities=False) + tree = etree.parse(xml_file, parser) + root = tree.getroot() + + for media in root.xpath(".//Media"): + for table in media.xpath("Table"): + url_element = table.find("URL") + if url_element is not None and url_element.text not in self.records: + media.remove(table) + + dtd_uri = self.find_asset(tree.docinfo.system_url) + if not os.path.exists(dtd_uri): + raise RuntimeError('cannot find referenced DTD') + + with NamedTemporaryFile('wb+', delete=False) as new_xml_file: + tree.write(new_xml_file, pretty_print=True, encoding="utf-8", xml_declaration=True, + doctype=tree.docinfo.doctype) + with open(new_xml_file.name, 'r+') as f: + # LXML ersetzt beim RecordDelimiter das Newline durch ein echtes Newline. + # Das ist möglicherweise ein Problem. Daher ersetzen wir das danach in der Datei. + content = f.read() + f.seek(0) + f.write(content.replace(' \n', + ' ')) + return new_xml_file.name, dtd_uri diff --git a/requirements_dev.txt b/requirements_dev.txt index a733d4b..8876ed1 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -2,4 +2,5 @@ pytest flake8 isort -pytz \ No newline at end of file +pytz +lxml