diff --git a/account_banking_fi_patu/__init__.py b/account_banking_fi_patu/__init__.py index cb9c0843f..3d20640b5 100644 --- a/account_banking_fi_patu/__init__.py +++ b/account_banking_fi_patu/__init__.py @@ -12,8 +12,8 @@ # garantees and support are strongly adviced to contract EduSense BV # # 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, either version 3 of the License, or +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, @@ -25,6 +25,5 @@ # along with this program. If not, see . # ############################################################################## -import patu -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: +from . import patu diff --git a/account_banking_fi_patu/__openerp__.py b/account_banking_fi_patu/__openerp__.py index 8f2f557b7..35443d4fa 100644 --- a/account_banking_fi_patu/__openerp__.py +++ b/account_banking_fi_patu/__openerp__.py @@ -11,8 +11,8 @@ # garantees and support are strongly adviced to contract EduSense BV # # 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, either version 3 of the License, or +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, @@ -24,6 +24,7 @@ # along with this program. If not, see . # ############################################################################## + { 'name': 'Account Banking PATU module', 'version': '0.62', diff --git a/account_banking_fi_patu/parser.py b/account_banking_fi_patu/parser.py index d5754ba1c..5d5d0bd3b 100644 --- a/account_banking_fi_patu/parser.py +++ b/account_banking_fi_patu/parser.py @@ -1,7 +1,9 @@ #!/usr/bin/env python # encoding: utf-8 """Parser for PATU format files""" -import re, datetime +import re +import datetime + def fixchars(line): """Fix the characters mangled in the input @@ -20,107 +22,120 @@ def fixchars(line): class PatuParser(object): """Parse PATU lines in to structs""" - def __init__( self ): + def __init__(self): """ Initialize PATU parser """ recparse = dict() - recparse["00"] = "T(?P00)(?P\d{3})" \ - + "(?P\d{3})(?P\d{14})" \ - + "(?P\d{3})(?P\d{6})" \ - + "(?P\d{6})" \ - + "(?P\d{6})(?P\d{4})" \ - + "(?P.{17})(?P\d{6})" \ - + "(?P.{19})" \ - + "(?P\d{6})(?P.{3})" \ - + "(?P.{30})"\ - + "(?P\d{18})(?P.{35})" \ - + "(?P.{40})(?P.{40})" \ - + "(?P.{30})(?P.{30})" - recparse["10"] = "T(?P[18]0)(?P\d{3})" \ - + "(?P\d{6})" \ - + "(?P.{18})(?P\d{6})" \ - + "(?P\d{6})" \ - + "(?P\d{6})(?P\d)" \ - + "(?P.{3})(?P.{35})" \ - + "(?P.{19})(?P.)(?P.)" \ - + "(?P.{35})(?P.)" \ - + "(?P.{14})(?P.)" \ - + "(?P.{20})" \ - + "(?P.{8})(?P.)" - recparse["11"] = "T(?P[18]1)(?P\d{3})" \ - + "(?P.{2})" \ - + "(?:(?# Match specific info)" \ - + "(?<=00)(?P.{35})+" \ - + "|" \ - + "(?<=01)(?P\d{8})" \ - + "|" \ - + "(?<=02)(?P.{10})\s(?P.{15})\s" \ - + "(?P\d{6})" \ - + "|" \ - + "(?<=03)(?P.{19})\s(?P.{14})" \ - + "|" \ - + "(?<=04)(?P.{18})" \ - + "|" \ - + "(?<=05)(?P.{19})\s(?P.{3})\s" \ - + "(?P.{11})(?P.{6})" \ - + "|" \ - + "(?<=06)(?P.{35})(?P.{35})" \ - + "|" \ - + "(?<=07)(?P.{35})" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "(?P.{35})?" \ - + "|" \ - + "(?<=08)(?P\d{3})\s(?P.{31})" \ - + "|" \ - + "(?<=09)(?P.{35})" \ - + "|" \ - + "(?<=11)(?P.{35})(?P.{35})" \ - + "(?P.{35})(?P.{70})" \ - + "(?P.{70})(?P.{35})" \ - + "(?P.{70})" \ - + ")" - recparse["40"] = "T(?P40)(?P\d{3})" \ - + "(?P\d{6})(?P.{19})" \ - + "(?P.{19})" - recparse["50"] = "T(?P50)(?P\d{3})" \ - + "(?P\d)(?P\d{6})" \ - + "(?P\d{8})(?P.{19})" \ - + "(?P\d{8})(?P.{19})" - recparse["60"] = "T(?P60)(?P\d{3})" \ - + "(?P.{3})(?P01)" \ - + "(?P\d{6})-" \ - + "(?P\d{6})" \ - + "(?P.)(?P.{19})" \ - + "(?P.)(?P\d{7})" \ - + "(?P.)(?P.{19})" \ - + "(?P.)(?P\d{7})" \ - + "(?P.)(?P\d{7})" \ - + "(?P.)(?P.{19})" \ - + "(?P.)(?P.{35})" \ - + "(?P\d{7})" \ - + "(?P.)(?P.{35})" \ - + "(?P\d{7})" - recparse["70"] = "T(?P70)(?P\d{3})" \ - + "(?P\d{3})" \ - + "(?P.{80})" \ - + "(?P.{80})?" \ - + "(?P.{80})?" \ - + "(?P.{80})?" \ - + "(?P.{80})?" \ - + "(?P.{80})?" + recparse["00"] = ( + "T(?P00)(?P\d{3})" + "(?P\d{3})(?P\d{14})" + "(?P\d{3})(?P\d{6})" + "(?P\d{6})" + "(?P\d{6})(?P\d{4})" + "(?P.{17})(?P\d{6})" + "(?P.{19})" + "(?P\d{6})(?P.{3})" + "(?P.{30})" + "(?P\d{18})(?P.{35})" + "(?P.{40})(?P.{40})" + "(?P.{30})(?P.{30})" + ) + recparse["10"] = ( + "T(?P[18]0)(?P\d{3})" + "(?P\d{6})" + "(?P.{18})(?P\d{6})" + "(?P\d{6})" + "(?P\d{6})(?P\d)" + "(?P.{3})(?P.{35})" + "(?P.{19})(?P.)(?P.)" + "(?P.{35})(?P.)" + "(?P.{14})(?P.)" + "(?P.{20})" + "(?P.{8})(?P.)" + ) + recparse["11"] = ( + "T(?P[18]1)(?P\d{3})" + "(?P.{2})" + "(?:(?# Match specific info)" + "(?<=00)(?P.{35})+" + "|" + "(?<=01)(?P\d{8})" + "|" + "(?<=02)(?P.{10})\s(?P.{15})\s" + "(?P\d{6})" + "|" + "(?<=03)(?P.{19})\s(?P.{14})" + "|" + "(?<=04)(?P.{18})" + "|" + "(?<=05)(?P.{19})\s(?P.{3})\s" + "(?P.{11})(?P.{6})" + "|" + "(?<=06)(?P.{35})(?P.{35})" + "|" + "(?<=07)(?P.{35})" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "(?P.{35})?" + "|" + "(?<=08)(?P\d{3})\s(?P.{31})" + "|" + "(?<=09)(?P.{35})" + "|" + "(?<=11)(?P.{35})(?P.{35})" + "(?P.{35})(?P.{70})" + "(?P.{70})(?P.{35})" + "(?P.{70})" + ")" + ) + recparse["40"] = ( + "T(?P40)(?P\d{3})" + "(?P\d{6})(?P.{19})" + "(?P.{19})" + ) + recparse["50"] = ( + "T(?P50)(?P\d{3})" + "(?P\d)(?P\d{6})" + "(?P\d{8})(?P.{19})" + "(?P\d{8})(?P.{19})" + ) + recparse["60"] = ( + "T(?P60)(?P\d{3})" + "(?P.{3})(?P01)" + "(?P\d{6})-" + "(?P\d{6})" + "(?P.)(?P.{19})" + "(?P.)(?P\d{7})" + "(?P.)(?P.{19})" + "(?P.)(?P\d{7})" + "(?P.)(?P\d{7})" + "(?P.)(?P.{19})" + "(?P.)(?P.{35})" + "(?P\d{7})" + "(?P.)(?P.{35})" + "(?P\d{7})" + ) + recparse["70"] = ( + "T(?P70)(?P\d{3})" + "(?P\d{3})" + "(?P.{80})" + "(?P.{80})?" + "(?P.{80})?" + "(?P.{80})?" + "(?P.{80})?" + "(?P.{80})?" + ) for record in recparse: recparse[record] = re.compile(recparse[record]) self.recparse = recparse - def parse_record(self, line): """Docstring for parse_perus @@ -135,7 +150,7 @@ class PatuParser(object): if matchobj: break if not matchobj: - print " **** failed to match line '%s'" % (line) + print(" **** failed to match line '%s'" % (line)) return # Strip strings matchdict = matchobj.groupdict() @@ -146,7 +161,8 @@ class PatuParser(object): del matchdict[field] matchkeys = set(matchdict.keys()) - needstrip = set(["bankcontact1", "bankcontact2", "bankcontact3", + needstrip = set([ + "bankcontact1", "bankcontact2", "bankcontact3", "customerid", "accountowner", "accountname", "refnr", "formnr", "recipientname", "eventdesc", "recipientaccount", "message", "principalinfo1", "bankinfo1", "bankinfo2", "bankinfo3", @@ -158,30 +174,35 @@ class PatuParser(object): for field in matchkeys & needstrip: matchdict[field] = matchdict[field].strip() # Convert to int - needsint = set(["itemcount", "eventid", "record_len", + needsint = set([ + "itemcount", "eventid", "record_len", "depositcount", "withdrawcount"]) for field in matchkeys & needsint: matchdict[field] = float(matchdict[field]) # Convert to float - needsfloat = set(["startingbalance", "accountlimit", "amount", + needsfloat = set([ + "startingbalance", "accountlimit", "amount", "destinationamount", "balance", "availablefunds", "depositsum", "withdrawsum", "avgbalance", "avglimitbalance", "permanentbalance"]) for field in matchkeys & needsfloat: matchdict[field] = float(matchdict[field]) # convert sents to euros - needseur = set(["startingbalance", "accountlimit", "amount", + needseur = set([ + "startingbalance", "accountlimit", "amount", "destinationamount", "balance", "availablefunds", "depositsum", "withdrawsum", "avgbalance", "permanentbalance"]) for field in matchkeys & needseur: matchdict[field] = matchdict[field] / 100 # convert ibanswift to separate fields - if matchdict.has_key("ibanswift"): - matchdict["iban"], matchdict["swift"] = \ - matchdict["ibanswift"].strip().split() + if "ibanswift" in matchdict: + matchdict["iban"], matchdict["swift"] = ( + matchdict["ibanswift"].strip().split() + ) # Convert date fields - needdate = set(["startdate", "enddate", "creationdate", "balancedate", + needdate = set([ + "startdate", "enddate", "creationdate", "balancedate", "valuedate", "paymentdate", "recorddate", "perioddate"]) for field in matchkeys & needdate: # Base all dates on the year 2000, since it's unlikely that this @@ -191,17 +212,20 @@ class PatuParser(object): matchdict[field] = None continue - matchdict[field] = datetime.date(int("20" + datestring[0:2]), - int(datestring[2:4]), int(datestring[4:6])) + matchdict[field] = datetime.date( + int("20" + datestring[0:2]), + int(datestring[2:4]), int(datestring[4:6])) # convert time fields needtime = set(["creationtime"]) for field in matchkeys & needtime: timestring = matchdict[field] - matchdict[field] = datetime.time(int(timestring[0:2]), - int(timestring[2:4])) + matchdict[field] = datetime.time( + int(timestring[0:2]), + int(timestring[2:4])) return matchdict + def parse_file(filename): """Parse file with PATU format inside @@ -214,6 +238,7 @@ def parse_file(filename): for line in patufile: parser.parse_record(line) + def main(): """The main function, currently just calls a dummy filename @@ -223,5 +248,3 @@ def main(): if __name__ == '__main__': main() - - diff --git a/account_banking_fi_patu/patu.py b/account_banking_fi_patu/patu.py index 329f8c7a3..dadf2c2eb 100644 --- a/account_banking_fi_patu/patu.py +++ b/account_banking_fi_patu/patu.py @@ -6,8 +6,8 @@ # All Rights Reserved # # 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, either version 3 of the License, or +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, @@ -30,20 +30,23 @@ from account_banking_fi_patu.parser import PatuParser __all__ = ['parser'] + class transaction(models.mem_bank_transaction): ''' Implementation of transaction communication class for account_banking. ''' mapping = { - "remote_account": "recipientaccount", - "remote_currency": "currency", - "transferred_amount": "amount", - "execution_date": "recorddate", - "value_date": "paymentdate", - "transfer_type": "eventtype", - "reference": "refnr", - "eventcode": "eventcode", - "message": "message"} + "remote_account": "recipientaccount", + "remote_currency": "currency", + "transferred_amount": "amount", + "execution_date": "recorddate", + "value_date": "paymentdate", + "transfer_type": "eventtype", + "reference": "refnr", + "eventcode": "eventcode", + "message": "message" + } + def __init__(self, record, *args, **kwargs): ''' Initialize own dict with read values. @@ -63,19 +66,19 @@ class transaction(models.mem_bank_transaction): If eventcode is 730, the transaction was initiated by the bank and doesn't have a destination account. ''' - if self.eventcode and (self.eventcode == "720" or self.eventcode == - "710"): + if self.eventcode in ["720", "710"]: # Withdrawal from and deposit to the account return (self.execution_date and self.transferred_amount and True) \ - or False + or False if self.eventcode and self.eventcode == "730": # The transaction is bank initiated, no remote account is present return (self.execution_date and self.transferred_amount and True) \ - or False + or False return super(transaction, self).is_valid() + class statement(models.mem_bank_statement): ''' Implementation of bank_statement communication class of account_banking @@ -110,6 +113,7 @@ class statement(models.mem_bank_statement): return self.transactions.append(transaction(record)) + class parser(models.parser): code = 'FIPATU' name = _('PATU statement sheet')