Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fetching account statements (HKKAU, HKEKA) #164

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 51 additions & 2 deletions fints/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .formals import (
CUSTOMER_ID_ANONYMOUS, KTI1, BankIdentifier, DescriptionRequired,
SynchronizationMode, TANMediaClass4, TANMediaType2,
SupportedMessageTypes)
SupportedMessageTypes, StatementFormat)
from .message import FinTSInstituteMessage
from .models import SEPAAccount
from .parser import FinTS3Serializer
Expand All @@ -36,7 +36,7 @@
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, HKCAZ1
from .segments.statement import DKKKU2, HKKAZ5, HKKAZ6, HKKAZ7, HKCAZ1, HKKAU2, HKKAU1, HKEKA3, HKEKA4, HKEKA5
from .segments.transfer import HKCCM1, HKCCS1, HKIPZ1, HKIPM1
from .types import SegmentSequence
from .utils import (
Expand Down Expand Up @@ -727,6 +727,55 @@ def get_communication_endpoints(self):

return responses

def get_statements(self, account: SEPAAccount):
"""
Retrieve list of statements of an account.
:param account: SEPAAccount to retrieve statements for.
:return: List of HIKAU objects
"""
with self._get_dialog() as dialog:
hkkau = self._find_highest_supported_command(HKKAU1, HKKAU2)

responses = self._fetch_with_touchdowns(
dialog,
lambda touchdown: hkkau(
account=hkkau._fields['account'].type.from_sepa_account(account),
touchdown_point=touchdown,
),
lambda response: response,
'HIKAU'
)

return responses

def _get_statement(self, command_seg, response):
for resp in response.response_segments(command_seg, 'HIEKA'):
return resp

def get_statement(self, account: SEPAAccount, number: int, year: int, format: StatementFormat = None):
"""
Retrieve a given statement of an account.
:param account: SEPAAccount to retrieve statement for.
:param number: Number of the statement to retrieve.
:param year: Year of the statement to retrieve.
:param format: Format to retrieve the statement in.
:return: HIEKA object
"""
with self._get_dialog() as dialog:
hkeka = self._find_highest_supported_command(HKEKA3, HKEKA4, HKEKA5)

seg = hkeka(
account=hkeka._fields['account'].type.from_sepa_account(account),
statement_format=format,
statement_number=number,
statement_year=year
)

response = self._send_with_possible_retry(dialog, seg, self._get_statement)
return response

def _find_supported_sepa_version(self, candidate_versions):
hispas = self.bpd.find_segment_first('HISPAS')
if not hispas:
Expand Down
28 changes: 28 additions & 0 deletions fints/formals.py
Original file line number Diff line number Diff line change
Expand Up @@ -1044,3 +1044,31 @@ class BookedCamtStatements1(DataElementGroup):
Source: Messages - Multibankfähige Geschäftsvorfälle (SEPA)"""
camt_statements = DataElementField(type='bin', min_count=1, required=True, _d="camt-Umsätze gebucht")


@document_enum
class StatementFormat(RepresentableEnum):
"""Kontoauszugsformat
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
MT_940 = '1' # doc: S.W.I.F.T. MT940
ISO_8583 = '2' # doc: ISO 8583
PDF = '3' # doc: printable format (e.g., PDF)


@document_enum
class Confirmation(RepresentableEnum):
"""Quittierung
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
NOT_REQUIRED = '0' # doc: Nicht Notwendig
CONFIRMED = '1' # doc: Quittiert
AWAITING_CONFIRMATION = '2' # doc: Quittierung offen


class ReportPeriod2(DataElementGroup):
"""Berichtszeitraum, version 2
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
start_date = DataElementField(type='dat', _d="Startdatum")
end_date = DataElementField(type='dat', required=False, _d="Enddatum")
144 changes: 142 additions & 2 deletions fints/segments/statement.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from fints.fields import DataElementField, DataElementGroupField
from fints.fields import DataElementField, DataElementGroupField, CodeField
from fints.formals import KTI1, Account2, Account3, QueryCreditCardStatements2, SupportedMessageTypes, \
BookedCamtStatements1
BookedCamtStatements1, StatementFormat, Confirmation, ReportPeriod2

from .base import FinTS3Segment, ParameterSegment

Expand Down Expand Up @@ -111,3 +111,143 @@ class HICAZ1(FinTS3Segment):
camt_descriptor = DataElementField(type='an', _d="camt-Deskriptor")
statement_booked = DataElementGroupField(type=BookedCamtStatements1, _d="Gebuchte Umsätze")
statement_pending = DataElementField(type='bin', required=False, _d="Nicht gebuchte Umsätze")


class HKKAU1(FinTS3Segment):
"""Übersicht Kontoauszüge, version 1
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
account = DataElementGroupField(type=Account3, _d="Kontoverbindung Auftraggeber")
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 HKKAU2(FinTS3Segment):
"""Übersicht Kontoauszüge, version 2
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
account = DataElementGroupField(type=KTI1, _d="Kontoverbindung international")
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 HIKAU1(FinTS3Segment):
"""Übersicht Kontoauszüge, version 1
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
statement_number = DataElementField(type='num', max_length=5, _d="Kontoauszugsnummer")
confirmation = CodeField(enum=Confirmation, length=1, _d="Quittierung")
collection_possible = DataElementField(type='jn', _d="Abholung möglich J/N")
year = DataElementField(type='num', length=4, required=False, _d="Jahr")
date_created = DataElementField(type='dat', required=False, _d="Datum der Erstellung")
time_created = DataElementField(type='tim', required=False, _d="Uhrzeit der Erstellung")
creation_type = DataElementField(type='an', max_length=30, required=False, _d="Erstellart")


class HIKAU2(FinTS3Segment):
"""Übersicht Kontoauszüge, version 2
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
statement_number = DataElementField(type='num', max_length=5, _d="Kontoauszugsnummer")
confirmation = CodeField(enum=Confirmation, length=1, _d="Quittierung")
collection_possible = DataElementField(type='jn', _d="Abholung möglich J/N")
year = DataElementField(type='num', length=4, required=False, _d="Jahr")
date_created = DataElementField(type='dat', required=False, _d="Datum der Erstellung")
time_created = DataElementField(type='tim', required=False, _d="Uhrzeit der Erstellung")
creation_type = DataElementField(type='an', max_length=30, required=False, _d="Erstellart")


class HKEKA3(FinTS3Segment):
"""Kontoauszug anfordern, version 3
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
account = DataElementGroupField(type=Account3, _d="Kontoverbindung Auftraggeber")
statement_format = CodeField(enum=StatementFormat, length=1, required=False, _d="Kontoauszugsformat")
statement_number = DataElementField(type='num', max_length=5, _d="Kontoauszugsnummer")
statement_year = DataElementField(type='num', length=4, _d="Kontoauszugsjahr")
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 HKEKA4(FinTS3Segment):
"""Kontoauszug anfordern, version 4
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
account = DataElementGroupField(type=KTI1, _d="Kontoverbindung international")
statement_format = CodeField(enum=StatementFormat, length=1, required=False, _d="Kontoauszugsformat")
statement_number = DataElementField(type='num', max_length=5, _d="Kontoauszugsnummer")
statement_year = DataElementField(type='num', length=4, _d="Kontoauszugsjahr")
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 HKEKA5(FinTS3Segment):
"""Kontoauszug anfordern, version 5
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
account = DataElementGroupField(type=KTI1, _d="Kontoverbindung international")
statement_format = CodeField(enum=StatementFormat, length=1, required=False, _d="Kontoauszugsformat")
statement_number = DataElementField(type='num', max_length=5, _d="Kontoauszugsnummer")
statement_year = DataElementField(type='num', length=4, _d="Kontoauszugsjahr")
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 HIEKA3(FinTS3Segment):
"""Kontoauszug, version 3
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
statement_format = CodeField(enum=StatementFormat, length=1, required=False, _d="Kontoauszugsformat")
statement_period = DataElementGroupField(type=ReportPeriod2, _d="Berichtszeitraum")
data = DataElementField(type='bin', _d="Gebuchte Umsätze")
statement_info = DataElementField(type='txt', max_length=65536, required=False, _d="Informationen zum Rechnungsabschluss")
customer_info = DataElementField(type='txt', max_length=65536, required=False,
_d="Informationen zu Kundenbedingungen")
advertising_text = DataElementField(type='txt', max_length=65536, required=False, _d="Werbetext")
account_iban = DataElementField(type='an', max_length=34, required=False, _d="IBAN Konto")
account_bic = DataElementField(type='an', max_length=11, required=False, _d="BIC Konto")
statement_name_1 = DataElementField(type='an', max_length=35, required=False, _d="Auszugsname 1")
statement_name_2 = DataElementField(type='an', max_length=35, required=False, _d="Auszugsname 2")
statement_name_extra = DataElementField(type='an', max_length=35, required=False, _d="Namenszusatz")
confirmation_code = DataElementField(type='bin', required=False, _d="Quittungscode")


class HIEKA4(FinTS3Segment):
"""Kontoauszug, version 4
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
statement_format = CodeField(enum=StatementFormat, length=1, required=False, _d="Kontoauszugsformat")
statement_period = DataElementGroupField(type=ReportPeriod2, _d="Berichtszeitraum")
data = DataElementField(type='bin', _d="Gebuchte Umsätze")
statement_info = DataElementField(type='txt', max_length=65536, required=False, _d="Informationen zum Rechnungsabschluss")
customer_info = DataElementField(type='txt', max_length=65536, required=False,
_d="Informationen zu Kundenbedingungen")
advertising_text = DataElementField(type='txt', max_length=65536, required=False, _d="Werbetext")
account_iban = DataElementField(type='an', max_length=34, required=False, _d="IBAN Konto")
account_bic = DataElementField(type='an', max_length=11, required=False, _d="BIC Konto")
statement_name_1 = DataElementField(type='an', max_length=35, required=False, _d="Auszugsname 1")
statement_name_2 = DataElementField(type='an', max_length=35, required=False, _d="Auszugsname 2")
statement_name_extra = DataElementField(type='an', max_length=35, required=False, _d="Namenszusatz")
confirmation_code = DataElementField(type='bin', required=False, _d="Quittungscode")


class HIEKA5(FinTS3Segment):
"""Kontoauszug, version 5
Source: FinTS Financial Transaction Services, Schnittstellenspezifikation, Messages -- Multibankfähige Geschäftsvorfälle"""
statement_format = CodeField(enum=StatementFormat, length=1, required=False, _d="Kontoauszugsformat")
statement_period = DataElementGroupField(type=ReportPeriod2, _d="Berichtszeitraum")
date_created = DataElementField(type='dat', required=False, _d="Erstellungsdatum Kontoauszug")
statement_year = DataElementField(type='num', length=4, required=False, _d="Kontoauszugsjahr")
statement_number = DataElementField(type='num', max_length=5, required=False, _d="Kontoauszugsnummer")
data = DataElementField(type='bin', _d="Gebuchte Umsätze")
statement_info = DataElementField(type='txt', max_length=65536, required=False, _d="Informationen zum Rechnungsabschluss")
customer_info = DataElementField(type='txt', max_length=65536, required=False,
_d="Informationen zu Kundenbedingungen")
advertising_text = DataElementField(type='txt', max_length=65536, required=False, _d="Werbetext")
account_iban = DataElementField(type='an', max_length=34, required=False, _d="IBAN Konto")
account_bic = DataElementField(type='an', max_length=11, required=False, _d="BIC Konto")
statement_name_1 = DataElementField(type='an', max_length=35, required=False, _d="Auszugsname 1")
statement_name_2 = DataElementField(type='an', max_length=35, required=False, _d="Auszugsname 2")
statement_name_extra = DataElementField(type='an', max_length=35, required=False, _d="Namenszusatz")
confirmation_code = DataElementField(type='bin', required=False, _d="Quittungscode")
Loading