From: Henryk Plötz Date: Mon, 20 Aug 2018 20:26:24 +0000 (+0200) Subject: Improve BPD and UPD: Is now SegmentSequence, allows full querying. X-Git-Tag: v2.0.0~1^2~96 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b7619f5141361d45f314c84371bdd04d613aef9;p=thirdparty%2Fpython-fints.git Improve BPD and UPD: Is now SegmentSequence, allows full querying. Improve get_balance(): Ignore HISALS versions we don't know, don't blindly ask for highest version --- diff --git a/fints/client.py b/fints/client.py index 4554b8d..e43c6f5 100644 --- a/fints/client.py +++ b/fints/client.py @@ -29,6 +29,7 @@ from .segments.dialog import HISYN4, HKSYN3 from .segments.saldo import HISAL5, HISAL6, HISAL7, HKSAL5, HKSAL6, HKSAL7 from .segments.statement import HKKAZ from .segments.transfer import HKCCM, HKCCS +from .types import SegmentSequence from .utils import MT535_Miniparser, Password, mt940_to_array logger = logging.getLogger(__name__) @@ -36,8 +37,6 @@ logger = logging.getLogger(__name__) SYSTEM_ID_UNASSIGNED = '0' class FinTS3Client: - version = 300 - def __init__(self, bank_identifier, user_id, customer_id=None): self.accounts = [] if isinstance(bank_identifier, BankIdentifier): @@ -51,10 +50,10 @@ class FinTS3Client: self.customer_id = customer_id or user_id self.bpd_version = 0 self.bpa = None - self.bpd = [] + self.bpd = SegmentSequence() self.upd_version = 0 self.upa = None - self.upd = [] + self.upd = SegmentSequence() self.allowed_security_functions = [] self.selected_security_function = None self.product_name = 'pyfints' @@ -74,7 +73,7 @@ class FinTS3Client: if bpa: self.bpa = bpa self.bpd_version = bpa.bpd_version - self.bpd = list( + self.bpd = SegmentSequence( message.find_segments( callback = lambda m: len(m.header.type) == 6 and m.header.type[1] == 'I' and m.header.type[5] == 'S' ) @@ -84,7 +83,7 @@ class FinTS3Client: if upa: self.upa = upa self.upd_version = upa.upd_version - self.upd = list( + self.upd = SegmentSequence( message.find_segments('HIUPD') ) @@ -95,11 +94,6 @@ class FinTS3Client: if self.selected_security_function is None: self.selected_security_function = self.allowed_security_functions[0] - def find_bpd(self, type): - for seg in self.bpd: - if seg.header.type == type: - yield seg - def get_sepa_accounts(self): """ Returns a list of SEPA accounts @@ -204,32 +198,26 @@ class FinTS3Client: :return: A mt940.models.Balance object """ - max_hksal_version = max( - (seg.header.version for seg in self.find_bpd('HISALS')), - default=6 - ) - - clazz = { - 5: HKSAL5, - 6: HKSAL6, - 7: HKSAL7, - }.get(max_hksal_version, None) - - if clazz is None: - raise ValueError('Unsupported HKSAL version {}'.format(max_hksal_version)) - - seg = clazz( - account=clazz._fields['account'].type.from_sepa_account(account), - all_accounts=False, - ) - with self._new_dialog() as dialog: + max_hisals = self.bpd.find_segment_highest_version('HISALS', (5, 6, 7)) + if not max_hisals: + raise ValueError('No supported HISALS version found') + + hksal = { + 5: HKSAL5, + 6: HKSAL6, + 7: HKSAL7, + }.get(max_hisals.header.version, None) + + seg = hksal( + account=hksal._fields['account'].type.from_sepa_account(account), + all_accounts=False, + ) + response = dialog.send(seg) - - # find segment - seg = response.find_segment_first((HISAL5, HISAL6, HISAL7)) - if seg: - return seg.balance_booked.as_mt940_Balance() + + for resp in response.response_segments(seg, 'HISAL'): + return resp.balance_booked.as_mt940_Balance() def get_holdings(self, account: SEPAAccount): """ diff --git a/fints/message.py b/fints/message.py index 67ebfee..ddf8783 100644 --- a/fints/message.py +++ b/fints/message.py @@ -27,18 +27,10 @@ class FinTSMessage(SegmentSequence): self.segments.append(segment) return self - def sign_prepare(self, auth_mech): - pass - - def sign_commit(self, auth_mech): - pass - - def encrypt(self, enc_mech): - pass - - def decrypt(self, enc_mech): - pass - + def response_segments(self, ref, *args, **kwargs): + for segment in self.find_segments(*args, **kwargs): + if segment.header.reference == ref.header.number: + yield segment class FinTSCustomerMessage(FinTSMessage): DIRECTION = MessageDirection.FROM_CUSTOMER diff --git a/fints/types.py b/fints/types.py index e5876fa..689276f 100644 --- a/fints/types.py +++ b/fints/types.py @@ -97,7 +97,7 @@ class SegmentSequence: parser = FinTS3Parser() data = parser.explode_segments(segments) segments = [parser.parse_segment(segment) for segment in data] - self.segments = segments or [] + self.segments = list(segments) if segments else [] def render_bytes(self) -> bytes: from .parser import FinTS3Serializer @@ -175,6 +175,24 @@ class SegmentSequence: return None + def find_segment_highest_version(self, query=None, version=None, callback=None, recurse=True, default=None, *args, **kwargs): + """Finds the highest matching segment. + + Same parameters as find_segments(), but returns the match with the highest version, or default if no match is found.""" + # FIXME Test + + retval = None + + for s in self.find_segments(query=query, version=version, callback=callback, recurse=recurse, *args, **kwargs): + if not retval or s.header.version > retval.header.version: + retval = s + + if retval is None: + return default + + return retval + + class ContainerMeta(type): @classmethod def __prepare__(metacls, name, bases):