diff --git a/src/pretix/plugins/banktransfer/camtimport.py b/src/pretix/plugins/banktransfer/camtimport.py new file mode 100644 index 0000000000..10cc8156f5 --- /dev/null +++ b/src/pretix/plugins/banktransfer/camtimport.py @@ -0,0 +1,71 @@ +# +# This file is part of pretix (Community Edition). +# +# Copyright (C) 2014-2020 Raphael Michel and contributors +# Copyright (C) 2020-today pretix GmbH and contributors +# +# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General +# Public License as published by the Free Software Foundation in version 3 of the License. +# +# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are +# applicable granting you additional permissions and placing additional restrictions on your usage of this software. +# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive +# this file, see . +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along with this program. If not, see +# . +# +from django.utils.translation import gettext_lazy as _ +from lxml import etree + + +def parse(file): + # Spec: https://www.ebics.de/de/datenformate + data = file.read() + root = etree.fromstring(data) + + statements = root.findall("{*}BkToCstmrStmt/{*}Stmt") + if not statements: + raise ValueError(_("Empty file or unknown format.")) + + def get_text(findall_result): + if len(findall_result) == 1: + return findall_result[0].text + return "" + + rows = [] + for stmt in statements: + for ntry in stmt.findall("{*}Ntry"): + minus = "" + otherparty = "Dbtr" + if ntry.findall("{*}CdtDbtInd")[0].text == "DBIT": + otherparty = "Cdtr" + minus = "-" + reference_parts = [ + get_text(ntry.findall("{*}NtryDtls/{*}TxDtls/{*}RmtInf/{*}Ustrd")), + get_text(ntry.findall("{*}NtryDtls/{*}TxDtls/{*}Refs/{*}EndToEndId")), + get_text(ntry.findall("{*}NtryDtls/{*}TxDtls/{*}Refs/{*}InstructionIdentification")), + ] + if ntry.findall("{*}NtryDtls/{*}Btch"): + # Batch booking, we do not support splitting yet + reference_parts.insert(0, get_text(ntry.findall("{*}NtryDtls/{*}Btch/{*}PmtInfId"))) + row = { + 'amount': minus + ntry.findall("{*}Amt")[0].text, + 'date': get_text(ntry.findall("{*}BookgDt/{*}Dt")), + 'reference': "\n".join(filter(lambda a: bool(a) and a != "NOTPROVIDED", reference_parts)) + } + if ext_id := get_text(ntry.findall("{*}AcctSvcrRef")): + row['external_id'] = ext_id + if iban := get_text(ntry.findall(f"{{*}}NtryDtls/{{*}}TxDtls/{{*}}RltdPties/{{*}}{otherparty}Acct/{{*}}Id/{{*}}IBAN")): + row['iban'] = iban + if bic := get_text(ntry.findall(f"{{*}}NtryDtls/{{*}}TxDtls/{{*}}RltdAgts/{{*}}{otherparty}Agt/{{*}}FinInstnId/{{*}}BICFI")): + row['bic'] = bic + if payer := get_text(ntry.findall(f"{{*}}NtryDtls/{{*}}TxDtls/{{*}}RltdPties/{{*}}{otherparty}/{{*}}Nm")): + row['payer'] = payer + rows.append(row) + + return rows diff --git a/src/pretix/plugins/banktransfer/views.py b/src/pretix/plugins/banktransfer/views.py index 3875c934bc..29926aa2cb 100644 --- a/src/pretix/plugins/banktransfer/views.py +++ b/src/pretix/plugins/banktransfer/views.py @@ -66,7 +66,7 @@ from pretix.control.permissions import ( ) from pretix.control.views.organizer import OrganizerDetailViewMixin from pretix.helpers.json import CustomJSONEncoder -from pretix.plugins.banktransfer import csvimport, mt940import +from pretix.plugins.banktransfer import camtimport, csvimport, mt940import from pretix.plugins.banktransfer.models import ( BankImportJob, BankTransaction, RefundExport, ) @@ -419,6 +419,9 @@ class ImportView(ListView): ): return self.process_mt940() + elif 'file' in self.request.FILES and '.xml' in self.request.FILES.get('file').name.lower(): + return self.process_camt() + elif self.request.FILES.get('file') is None: messages.error(self.request, _('You must choose a file to import.')) return self.redirect_back() @@ -432,6 +435,14 @@ class ImportView(ListView): def settings(self): return SettingsSandbox('payment', 'banktransfer', getattr(self.request, 'event', self.request.organizer)) + def process_camt(self): + try: + return self.start_processing(camtimport.parse(self.request.FILES.get('file'))) + except: + logger.exception('Failed to import CAMT file') + messages.error(self.request, _('We were unable to process your input.')) + return self.redirect_back() + def process_mt940(self): try: return self.start_processing(mt940import.parse(self.request.FILES.get('file'))) diff --git a/src/tests/plugins/banktransfer/camt.053_bundesbank.xml b/src/tests/plugins/banktransfer/camt.053_bundesbank.xml new file mode 100644 index 0000000000..d9db118a84 --- /dev/null +++ b/src/tests/plugins/banktransfer/camt.053_bundesbank.xml @@ -0,0 +1,756 @@ + + + + + + + 20240313C0098170 + 2024-03-13T18:40:42.8734727+01:00 + + + 20240313C0098170 + + 00001 + true + + 1 + 2024-03-13T18:40:42.8734727+01:00 + + + DE00IBANdesDotationskontos + + + CACC + + EUR + Testbank, Hamburg + + Testbank-Inhaber + + + + MARKDEF1200 + + + DEBLZ + + 20000000 + + Deutsche Bundesbank + + DE114103555 + UmsStId + + + + Filiale Hamburg + + + + + + + OPBD + + + 0.00 + CRDT +
+
2024-03-13
+ +
+ + + + CLBD + + + 0.00 + CRDT +
+
2024-03-13
+ +
+ + 2000000011240313 + 100000.00 + CRDT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 103600002791/0019200002 + + + PMNT + + CNTR + CDPT + + + + NCMI+082+0019200002 + DK + + + + + + 2000000011240313 + + 100000.00 + + + PMNT + + CNTR + CDPT + + + + NCMI+082+0019200002 + DK + + + + Einzahlung + + Einzahlungen + + + Einzahlungen +
+ + 2000000012240313 + 25000.00 + DBIT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 049000039704/0019000002 + + + PMNT + + CNTR + CWDL + + + + NCMI+083+0019000002 + DK + + + + + + 2000000012240313 + 9998770 + 9998770 + + 25000.00 + + + PMNT + + CNTR + CWDL + + + + NCMI+083+0019000002 + DK + + + + Auszahlung + + Auszahlungen + + + Auszahlungen +
+ + 20000.00 + DBIT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 047200003598/0002000001 + + + PMNT + + ICHQ + CCHQ + + + + NCHK+101+0002000001 + DK + + + + + + 9998771 + 9998771 + + 250000.00 + + + PMNT + + ICHQ + CCHQ + + + + NCHK+101+0002000001 + DK + + + + + + Deutsche Bundesbank KBS HMS Hamburg + + + + + DE98200000000020002633 + + + + + + + + + DEBLZ + + 20000000 + + + + + + LS bestätigter Scheck + + + Bestätigter Scheck vom 13.03.2024 + Scheck Nr. 135469 + + Inhaberscheck + + + Inhaberscheck +
+ + 15.00 + DBIT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 047200003598/0002000001 + + + ACMT + + MDOP + CHRG + + + + NCHG+808+0002000001 + DK + + + + + 15.00 + + + ACMT + + MDOP + CHRG + + + + NCHG+808+0002000001 + DK + + + + LS Entgelte Giro, SchE + + Gebühren + + + Gebühren +
+ + H202403135000000107 + 145015.00 + CRDT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 051500000059/0019000003 + + + PMNT + + RCDT + SDVA + + + + NTRF+088+0019000003 + DK + + + + + + H202403135000000107 + H202403135000000107 + + 145015.00 + + + PMNT + + RCDT + SDVA + + + + NTRF+088+0019000003 + DK + + + + Überw Prior1/SWI + + Überweisungsgutschrift mit Festvaluta + + + Überweisungsgutschrift mit Festvaluta +
+ + H202403135000000108 + 50000.00 + CRDT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 105600004525/0019200003 + + + PMNT + + RCDT + SDVA + + + + NTRF+088+0019200003 + DK + + + + + + H202403135000000108 + H202403135000000108 + + 50000.00 + + + 50000.00 + + + + + PMNT + + RCDT + SDVA + + + + NTRF+088+0019200003 + DK + + + + + + Testbank + + + + + + 0123456789 + + + + + + Überw Prior1/SWI + + + VWZ pacs008 RTGS nach DOTA + + Überweisungsgutschrift mit Festvaluta + + + Überweisungsgutschrift mit Festvaluta +
+ + H202403135000000109 + 80000.00 + CRDT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 051800000156/0019000004 + + + PMNT + + RCDT + SDVA + + + + NTRF+088+0019000004 + DK + + + + + + H202403135000000109 + pacs009-EndToEndId-00004 + + 80000.00 + + + PMNT + + RCDT + SDVA + + + + NTRF+088+0019000004 + DK + + + + Überw Prior1/SWI + + + VWZ pacs009 RTGS nach DOTA + + Überweisungsgutschrift mit Festvaluta + + + Überweisungsgutschrift mit Festvaluta +
+ + pacs009-InstrId-00005 + 30000.00 + DBIT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 055100000086/0019000005 + + + PMNT + + ICDT + SDVA + + + + NTRF+087+0019000005 + DK + + + + + + pacs009-InstrId-00005 + pacs009-InstrId-00005 + + 30000.00 + + + PMNT + + ICDT + SDVA + + + + NTRF+087+0019000005 + DK + + + + Überw Prior1/SWI + + + VWZ pacs009 DOTA nach MCA + + Eilüberweisung + + + Eilüberweisung +
+ + pacs009-InstrId-00006 + 120000.00 + DBIT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 001400001221/0019000006 + + + PMNT + + ICDT + SDVA + + + + NTRF+087+0019000006 + DK + + + + + + pacs009-InstrId-00006 + pacs009-InstrId-00006 + + 120000.00 + + + PMNT + + ICDT + SDVA + + + + NTRF+087+0019000006 + DK + + + + Überw Prior1/SWI + + + VWZ pacs009 DOTA nach RTGS + + Eilüberweisung + + + Eilüberweisung +
+ + 100000.00 + CRDT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 016900004681/0002000002 + + + NCHK+070+0002000002 + DK + + + + + 100000.00 + + + NCHK+070+0002000002 + DK + + + + + + Deutsche Bundesbank / 22772 Hamburg + + + + + DE98200000000020002633 + + + + + + + + + DEBLZ + + 20000000 + + + + + + GS bestätigter Scheck + + + Rückgabe Best. Scheck vom 28.02.2024 + Scheck Nr. 135468 + + + +
+ + pacs008-InstrId-00007 + 280000.00 + DBIT + + BOOK + + +
2024-03-13
+
+ +
2024-03-13
+
+ 010300005153/0019000007 + + + PMNT + + ICDT + SDVA + + + + NTRF+087+0019000007 + DK + + + + + + pacs008-InstrId-00007 + pacs008-InstrId-00007 + + 280000.00 + + + PMNT + + ICDT + SDVA + + + + NTRF+087+0019000007 + DK + + + + + + Testbank, Hamburg + + + + + DE00IBANbeiTestbank + + + + + Überw Prior1/SWI + + + VWZ pacs008 DOTA nach RTGS + + Eilüberweisung + + + Eilüberweisung +
+
+
+
diff --git a/src/tests/plugins/banktransfer/camt.053_sepatools.xml b/src/tests/plugins/banktransfer/camt.053_sepatools.xml new file mode 100644 index 0000000000..abe3407ab9 --- /dev/null +++ b/src/tests/plugins/banktransfer/camt.053_sepatools.xml @@ -0,0 +1,312 @@ + + + + + + 053D2013-12-27T22:05:03.0N130000005 + 2013-12-27T22:04:52.0+01:00 + + 1 + true + + + + 0352C5320131227220503 + 130000005 + 2013-12-27T22:04:52.0+01:00 + + + DE14740618130000033626 + + EUR + + Testkonto Nummer 1 + + + + GENODEF1PFK + VR-Bank Rottal-Inn eG + + DE 129267947 + UmsStId + + + + + + + + PRCD + + + 33.06 + CRDT +
+
2013-12-27
+ +
+ + + + CLBD + + + 23.06 + CRDT +
+
2013-12-27
+ +
+ + 2.00 + DBIT + BOOK + +
2013-12-27
+
+ +
2013-12-27
+
+ 2013122710583450000 + + + + + + NTRF+020 + ZKA + + + + + Testkonto Nummer 2 + + + + + 740618130100033626 + + BBAN + + + + + + + TEST BERWEISUNG MITTELS BLZUND KONTONUMMER - DTA + + + +
+ + 3.00 + DBIT + BOOK + +
2013-12-27
+
+ +
2013-12-27
+
+ 2013122710583600000 + + + + + CCTI/VRNWSW/b044f24cddb92a502b8a1b5 + NOTPROVIDED + + + + NMSC+201 + ZKA + + + + + Testkonto Nummer 1 + + + + DE14740618130000033626 + + + + keine Information vorhanden + + + Testkonto Nummer 2 + + + + DE58740618130100033626 + + + + keine Information vorhanden + + + + + + GENODEF1PFK + + + + + Test+berweisung mit BIC und IBAN SEPA IBAN: DE58740618130100033626 BIC: GENODEF1PFK + + + +
+ + 1.00 + CRDT + BOOK + +
2013-12-27
+
+ +
2013-12-27
+
+ 2013122711085260000 + + + + + + NMSC+051 + ZKA + + + + + Testkonto Nummer 2 + + + + + 740618130100033626 + + BBAN + + + + + + + R CKBUCHUNG + + + +
+ + 6.00 + DBIT + BOOK + +
2013-12-27
+
+ +
2013-12-27
+
+ 2013122711513230000 + + + + STZV-PmInf27122013-11:02-2 + 2 + + + + STZV-Msg27122013-11:02 + STZV-EtE27122013-11:02-1 + + + + 3.50 + + + + + NMSC+201 + ZKA + + + + + Testkonto Nummer 2 + + + + DE58740618130100033626 + + + + keine Information vorhanden + + + Testkonto Nummer 1 + + + + DE14740618130000033626 + + + + Testkonto + + + + Sammelueberwseisung 2. Zahlung TAN:283044 + + + + + STZV-Msg27122013-11:02 + STZV-EtE27122013-11:02-2 + + + + 2.50 + + + + + NMSC+201 + ZKA + + + + + Testkonto Nummer 2 + + + + DE58740618130100033626 + + + + keine Information vorhanden + + + Testkonto Nummer 1 + + + + DE14740618130000033626 + + + + Testkonto + + + + Sammelueberweisung 1. Zahlung TAN:283044 + + + +
+
+
+
\ No newline at end of file diff --git a/src/tests/plugins/banktransfer/test_camt.py b/src/tests/plugins/banktransfer/test_camt.py new file mode 100644 index 0000000000..57d7eede6a --- /dev/null +++ b/src/tests/plugins/banktransfer/test_camt.py @@ -0,0 +1,146 @@ +# +# This file is part of pretix (Community Edition). +# +# Copyright (C) 2014-2020 Raphael Michel and contributors +# Copyright (C) 2020-today pretix GmbH and contributors +# +# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General +# Public License as published by the Free Software Foundation in version 3 of the License. +# +# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are +# applicable granting you additional permissions and placing additional restrictions on your usage of this software. +# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive +# this file, see . +# +# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +# details. +# +# You should have received a copy of the GNU Affero General Public License along with this program. If not, see +# . +# +import os.path + +from django.test import TestCase + +from pretix.plugins.banktransfer import camtimport + +DATA_DIR = os.path.dirname(__file__) + + +class CamtImportTest(TestCase): + def _test_from_sample_file(self, filename, expected_parsed): + with open(os.path.join(DATA_DIR, filename), "rb") as f: + parsed = camtimport.parse(f) + print(parsed) + self.assertEqual(parsed, expected_parsed) + + def test_sample_file_sepatools(self): + expected_parsed = [ + { + "amount": "-2.00", + "date": "2013-12-27", + "reference": "TEST BERWEISUNG MITTELS BLZUND KONTONUMMER - DTA", + "external_id": "2013122710583450000", + "payer": "Testkonto Nummer 2", + }, + { + "amount": "-3.00", + "date": "2013-12-27", + "reference": "Test+berweisung mit BIC und IBAN SEPA IBAN: DE58740618130100033626 BIC: GENODEF1PFK", + "external_id": "2013122710583600000", + "iban": "DE58740618130100033626", + "payer": "Testkonto Nummer 2", + }, + { + "amount": "1.00", + "date": "2013-12-27", + "reference": "R CKBUCHUNG", + "external_id": "2013122711085260000", + "payer": "Testkonto Nummer 2", + }, + { + "amount": "-6.00", + "date": "2013-12-27", + "reference": "STZV-PmInf27122013-11:02-2", + "external_id": "2013122711513230000", + }, + ] + filename = "camt.053_sepatools.xml" + self._test_from_sample_file(filename, expected_parsed) + + def test_sample_file_bundesbank(self): + expected_parsed = [ + { + "amount": "100000.00", + "date": "2024-03-13", + "reference": "", + "external_id": "103600002791/0019200002", + }, + { + "amount": "-25000.00", + "date": "2024-03-13", + "reference": "", + "external_id": "049000039704/0019000002", + }, + { + "amount": "-20000.00", + "date": "2024-03-13", + "reference": "", + "external_id": "047200003598/0002000001", + "iban": "DE98200000000020002633", + }, + { + "amount": "-15.00", + "date": "2024-03-13", + "reference": "", + "external_id": "047200003598/0002000001", + }, + { + "amount": "145015.00", + "date": "2024-03-13", + "reference": "", + "external_id": "051500000059/0019000003", + }, + { + "amount": "50000.00", + "date": "2024-03-13", + "reference": "VWZ pacs008 RTGS nach DOTA", + "external_id": "105600004525/0019200003", + }, + { + "amount": "80000.00", + "date": "2024-03-13", + "reference": "VWZ pacs009 RTGS nach DOTA", + "external_id": "051800000156/0019000004", + }, + { + "amount": "-30000.00", + "date": "2024-03-13", + "reference": "VWZ pacs009 DOTA nach MCA", + "external_id": "055100000086/0019000005", + }, + { + "amount": "-120000.00", + "date": "2024-03-13", + "reference": "VWZ pacs009 DOTA nach RTGS", + "external_id": "001400001221/0019000006", + }, + { + "amount": "100000.00", + "date": "2024-03-13", + "reference": "", + "external_id": "016900004681/0002000002", + "iban": "DE98200000000020002633", + }, + { + "amount": "-280000.00", + "date": "2024-03-13", + "reference": "VWZ pacs008 DOTA nach RTGS", + "external_id": "010300005153/0019000007", + "iban": "DE00IBANbeiTestbank", + }, + ] + + filename = "camt.053_bundesbank.xml" + self._test_from_sample_file(filename, expected_parsed)