]> git.ipfire.org Git - thirdparty/python-fints.git/commitdiff
Add support for HKCAZ
authorRaphael Michel <mail@raphaelmichel.de>
Fri, 22 Feb 2019 11:20:39 +0000 (12:20 +0100)
committerRaphael Michel <mail@raphaelmichel.de>
Fri, 22 Feb 2019 11:21:17 +0000 (12:21 +0100)
docs/reading.rst
fints/client.py
fints/formals.py
fints/segments/statement.py

index 851d7d4eef148c66333da392ccc6dd8a37605ac5..e9b889e22e4bf88b37202c3905944e7f5dc1e932 100644 (file)
@@ -50,7 +50,7 @@ You can fetch the banking statement of an account within a certain timeframe wit
 operation.
 
 .. autoclass:: fints.client.FinTS3Client
-   :members: get_transactions
+   :members: get_transactions, get_transactions_xml
    :noindex:
 
 This method will return a list of ``Transaction`` objects from the ``mt-940`` library. You can find more information
index 1b6b06a96d213330b9abfa3e3fdd598de3567e59..4dab5f8cbe2f008a68ab6c831d3eb516f6298a6a 100644 (file)
@@ -17,7 +17,7 @@ from .exceptions import *
 from .formals import (
     CUSTOMER_ID_ANONYMOUS, KTI1, BankIdentifier, DescriptionRequired,
     SynchronizationMode, TANMediaClass4, TANMediaType2,
-)
+    SupportedMessageTypes)
 from .message import FinTSInstituteMessage
 from .models import SEPAAccount
 from .parser import FinTS3Serializer
@@ -36,7 +36,7 @@ from .segments.depot import HKWPD5, HKWPD6
 from .segments.dialog import HIRMG2, HIRMS2, HISYN4, HKSYN3
 from .segments.journal import HKPRO3, HKPRO4
 from .segments.saldo import HKSAL5, HKSAL6, HKSAL7
-from .segments.statement import DKKKU2, HKKAZ5, HKKAZ6, HKKAZ7
+from .segments.statement import DKKKU2, HKKAZ5, HKKAZ6, HKKAZ7, HKCAZ1
 from .segments.transfer import HKCCM1, HKCCS1
 from .types import SegmentSequence
 from .utils import (
@@ -508,6 +508,40 @@ class FinTS3Client:
 
         return statement
 
+    def get_transactions_xml(self, account: SEPAAccount, start_date: datetime.date = None,
+                             end_date: datetime.date = None) -> list:
+        """
+        Fetches the list of transactions of a bank account in a certain timeframe as camt.052.001.02 XML files.
+
+        :param account: SEPA
+        :param start_date: First day to fetch
+        :param end_date: Last day to fetch
+        :return: A list of binary XML objects
+        """
+
+        with self._get_dialog() as dialog:
+            hkcaz = self._find_highest_supported_command(HKCAZ1)
+
+            logger.info('Start fetching from {} to {}'.format(start_date, end_date))
+            responses = self._fetch_with_touchdowns(
+                dialog,
+                lambda touchdown: hkcaz(
+                    account=hkcaz._fields['account'].type.from_sepa_account(account),
+                    all_accounts=False,
+                    date_start=start_date,
+                    date_end=end_date,
+                    touchdown_point=touchdown,
+                    supported_camt_messages=SupportedMessageTypes('urn:iso:std:iso:20022:tech:xsd:camt.052.001.02'),
+                ),
+                'HICAZ'
+            )
+            logger.info('Fetching done.')
+
+        xml_streams = []
+        for seg in responses:
+            xml_streams.append(seg.statement_booked)
+        return xml_streams
+
     def get_credit_card_transactions(self, account: SEPAAccount, credit_card_number: str, start_date: datetime.date = None, end_date: datetime.date = None):
         # FIXME Reverse engineered, probably wrong
         with self._get_dialog() as dialog:
index 8cc547730896ca954d5ee957f37bb4348376c014..2bd5548e7ddddc9a3fb75110c55b093adceaeb34 100644 (file)
@@ -953,3 +953,12 @@ class GetSEPAAccountParameter1(DataElementGroup):
     national_account_allowed = DataElementField(type='jn', _d="Nationale Kontoverbindung erlaubt")
     structured_purpose_allowed = DataElementField(type='jn', _d="Strukturierter Verwendungszweck erlaubt")
     supported_sepa_formats = DataElementField(type='an', max_length=256, max_count=99, required=False, _d="Unterstützte SEPA-Datenformate")
+
+
+class SupportedMessageTypes(DataElementGroup):
+    """Unterstützte camt-Messages
+
+    Source:  Messages - Multibankfähige Geschäftsvorfälle (SEPA) - C.2.3.1.1.1
+    """
+    expected_type = AlphanumericField(_d='Unterstützte camt-messages')
+    # TODO: Support passing an arbitrary number of values here
index 9fa6b5e0cb573d2e40fba23d26c2712ad2491edc..aa9e020db9af0d0f18bc0f65d90a7b4559485b9d 100644 (file)
@@ -1,5 +1,5 @@
 from fints.fields import DataElementField, DataElementGroupField
-from fints.formals import KTI1, Account2, Account3, QueryCreditCardStatements2
+from fints.formals import KTI1, Account2, Account3, QueryCreditCardStatements2, SupportedMessageTypes
 
 from .base import FinTS3Segment, ParameterSegment
 
@@ -87,3 +87,29 @@ class DIKKUS2(ParameterSegment):
 
     Source: Reverse engineered"""
     parameter = DataElementGroupField(type=QueryCreditCardStatements2, _d="Parameter Kreditkartenumsätze anfordern")
+
+
+class HKCAZ1(FinTS3Segment):
+    """Kontoumsätze anfordern/Zeitraum, version 5
+
+    Source: HBCI Homebanking-Computer-Interface, Schnittstellenspezifikation"""
+    account = DataElementGroupField(type=KTI1, _d="Kontoverbindung international")
+    supported_camt_messages = DataElementGroupField(type=SupportedMessageTypes, _d="Kontoverbindung international")
+    all_accounts = DataElementField(type='jn', _d="Alle Konten")
+    date_start = DataElementField(type='dat', required=False, _d="Von Datum")
+    date_end = DataElementField(type='dat', required=False, _d="Bis Datum")
+    max_number_responses = DataElementField(type='num', max_length=4, required=False, _d="Maximale Anzahl Einträge")
+    touchdown_point = DataElementField(type='an', max_length=35, required=False, _d="Aufsetzpunkt")
+
+
+class HICAZ1(FinTS3Segment):
+    """Kontoumsätze rückmelden/Zeitraum, version 1
+
+    Source: HBCI Homebanking-Computer-Interface, Schnittstellenspezifikation"""
+    account = DataElementGroupField(type=Account3, _d="Kontoverbindung Auftraggeber")
+    all_accounts = DataElementField(type='jn', _d="Alle Konten")
+    camt_descriptor = DataElementField(type='an', _d="camt-Deskriptor")
+    # According to specification, statement_booked is a DEG with one binary XML *per day*. However, banks apparently
+    # send just one XML instead.
+    statement_booked = DataElementField(type='bin', _d="Gebuchte Umsätze")
+    statement_pending = DataElementField(type='bin', required=False, _d="Nicht gebuchte Umsätze")