From a475611fafec35fc479e61e56ec527165bb8d28f Mon Sep 17 00:00:00 2001 From: "Pieter J. Kersten" Date: Tue, 1 Mar 2011 14:43:09 +0100 Subject: [PATCH] [IMP] account_banking: Added to_swift convertor [IMP] account_banking: Fix 'paid' state for last partial payments [FIX] account_banking_nl_clieop: filter messages to SWIFT set before export [FIX] account_banking_nl_girotel: convert import to SWIFT before interpretation --- account_banking/__terp__.py | 2 +- account_banking/parsers/convert.py | 17 +++++++++++++- account_banking/wizard/bank_import.py | 18 +++++++-------- account_banking/wizard/banktools.py | 1 + account_banking_fi_patu/__terp__.py | 2 +- account_banking_nl_clieop/__terp__.py | 2 +- account_banking_nl_clieop/wizard/clieop.py | 26 ++++++++++++++-------- account_banking_nl_girotel/__terp__.py | 2 +- account_banking_nl_girotel/girotel.py | 15 ++++++++++++- account_banking_nl_multibank/__terp__.py | 2 +- 10 files changed, 61 insertions(+), 26 deletions(-) diff --git a/account_banking/__terp__.py b/account_banking/__terp__.py index 6c65c5efc..bdc75a951 100644 --- a/account_banking/__terp__.py +++ b/account_banking/__terp__.py @@ -25,7 +25,7 @@ ############################################################################## { 'name': 'Account Banking', - 'version': '0.1.47', + 'version': '0.1.49', 'license': 'GPL-3', 'author': 'EduSense BV', 'website': 'http://www.edusense.nl', diff --git a/account_banking/parsers/convert.py b/account_banking/parsers/convert.py index 5105839af..064507110 100644 --- a/account_banking/parsers/convert.py +++ b/account_banking/parsers/convert.py @@ -19,7 +19,9 @@ # ############################################################################## -__all__ = ['str2date', 'date2str', 'date2date'] +import unicodedata + +__all__ = ['str2date', 'date2str', 'date2date', 'to_swift'] try: from datetime import datetime @@ -42,4 +44,17 @@ def date2date(datestr, fromfmt='%d/%m/%y', tofmt='%Y-%m-%d'): ''' return date2str(str2date(datestr, fromfmt), tofmt) +_SWIFT = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-?:().,'+ " + +def to_swift(astr): + ''' + Reduce a string to SWIFT format + ''' + if not isinstance(astr, unicode): + astr = unicode(astr, 'utf-8') + s = [x in _SWIFT and x or ' ' + for x in unicodedata.normalize('NFKD', astr).encode('ascii', 'ignore') + ] + return ''.join(s) + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_banking/wizard/bank_import.py b/account_banking/wizard/bank_import.py index 2e9cec43e..fa78a6bc6 100644 --- a/account_banking/wizard/bank_import.py +++ b/account_banking/wizard/bank_import.py @@ -399,6 +399,12 @@ class banking_import(wizard.interface): found = round(trans.transferred_amount, digits) if abs(expected) == abs(found): partial = False + # Last partial payment will not flag invoice paid without + # manual assistence + invoice_obj = self.pool.get('account.invoice') + invoice_obj.write(cursor, uid, [invoice.id], { + 'state': 'paid' + }) elif abs(expected) > abs(found): # Partial payment, reuse invoice _cache(move_line, expected - found) @@ -424,14 +430,6 @@ class banking_import(wizard.interface): if x.partner_id.id == move_line.partner_id.id ] - # Re-check the cases with multiple candidates again: - # later matches may have removed possible candidates. - for trans, candidates in self.__multiple_matches: - best = [x for x in candidates if not _cached(x)] - if len(best) == 1: - # Now an exact match can be made - pass - return ( self._get_move_info(cursor, uid, move_line, account_ids and account_ids[0] or False, @@ -864,12 +862,12 @@ class banking_import(wizard.interface): if transaction.transferred_amount < 0: if len(partner_banks) == 1: account_id = partner_banks[0].partner_id.property_account_payable - if len(partner_banks) != 1 or account_id.id == def_pay_account_id: + if len(partner_banks) != 1 or not account_id or account_id.id == def_pay_account_id: account_id = account_info.default_credit_account_id else: if len(partner_banks) == 1: account_id = partner_banks[0].partner_id.property_account_receivable - if len(partner_banks) != 1 or account_id.id == def_rec_account_id: + if len(partner_banks) != 1 or not account_id or account_id.id == def_rec_account_id: account_id = account_info.default_debit_account_id else: account_id = move_info.move_line.account_id diff --git a/account_banking/wizard/banktools.py b/account_banking/wizard/banktools.py index acab8d837..af2cc31a7 100644 --- a/account_banking/wizard/banktools.py +++ b/account_banking/wizard/banktools.py @@ -26,6 +26,7 @@ from tools.translate import _ from account_banking.parsers import convert from account_banking import sepa from account_banking.struct import struct +import unicodedata __all__ = [ 'get_period', diff --git a/account_banking_fi_patu/__terp__.py b/account_banking_fi_patu/__terp__.py index 1f4215987..e8236daf2 100644 --- a/account_banking_fi_patu/__terp__.py +++ b/account_banking_fi_patu/__terp__.py @@ -26,7 +26,7 @@ ############################################################################## { 'name': 'Account Banking PATU module', - 'version': '0.47', + 'version': '0.49', 'license': 'GPL-3', 'author': 'Sami Haahtinen', 'website': 'http://ressukka.net', diff --git a/account_banking_nl_clieop/__terp__.py b/account_banking_nl_clieop/__terp__.py index 622e97fa7..e6dfc6c8d 100644 --- a/account_banking_nl_clieop/__terp__.py +++ b/account_banking_nl_clieop/__terp__.py @@ -25,7 +25,7 @@ ############################################################################## { 'name': 'Account Banking NL ClieOp', - 'version': '0.47', + 'version': '0.49', 'license': 'GPL-3', 'author': 'EduSense BV', 'website': 'http://www.edusense.nl', diff --git a/account_banking_nl_clieop/wizard/clieop.py b/account_banking_nl_clieop/wizard/clieop.py index 9020a7946..2ebb6c6cd 100644 --- a/account_banking_nl_clieop/wizard/clieop.py +++ b/account_banking_nl_clieop/wizard/clieop.py @@ -20,6 +20,7 @@ ############################################################################## from account_banking import record +from account_banking.parsers import convert __all__ = ['DirectDebitBatch', 'PaymentsBatch', 'DirectDebit', 'Payment', 'DirectDebitFile', 'PaymentsFile', 'SalaryPaymentsFile', @@ -27,6 +28,13 @@ __all__ = ['DirectDebitBatch', 'PaymentsBatch', 'DirectDebit', 'Payment', 'OrdersFile', ] +class StringField(record.Field): + def take(self, buffer): + return convert.to_swift(super(Field, self).take(buffer)) + + def format(self, value): + return convert.to_swift(super(Field, self).format(value)) + def eleven_test(s): ''' Dutch eleven-test for validating 9-long local bank account numbers. @@ -52,7 +60,7 @@ class HeaderRecord(record.Record): #{{{ record.Filler('variantcode', 1, 'A'), record.DateField('creation_date', '%d%m%y', auto=True), record.Filler('filename', 8, 'CLIEOP03'), - record.Field('sender_id', 5), + StringField('sender_id', 5), record.Field('file_id', 4), record.Field('duplicatecode', 1), record.Filler('filler', 21), @@ -82,7 +90,7 @@ class BatchHeaderRecord(record.Record): record.NumberField('accountno_sender', 10), record.NumberField('batch_tracer', 4), record.Filler('currency_order', 3, 'EUR'), - record.Field('batch_id', 16), + StringField('batch_id', 16), record.Filler('filler', 10), ] @@ -102,7 +110,7 @@ class FixedMessageRecord(record.Record): _fields = [ record.Filler('recordcode', 4, '0020'), record.Filler('variantcode', 1, 'A'), - record.Field('fixed_message', 32), + StringField('fixed_message', 32), record.Filler('filler', 13), ] @@ -114,7 +122,7 @@ class SenderRecord(record.Record): # NAW = Name, Address, Residence record.Field('NAWcode', 1), record.DateField('preferred_execution_date', '%d%m%y', auto=True), - record.Field('name_sender', 35), + StringField('name_sender', 35), record.Field('testcode', 1), record.Filler('filler', 2), ] @@ -136,7 +144,7 @@ class NamePayerRecord(record.Record): _fields = [ record.Filler('recordcode', 4, '0110'), record.Filler('variantcode', 1, 'B'), - record.Field('name', 35), + StringField('name', 35), record.Filler('filler', 10), ] @@ -145,7 +153,7 @@ class PaymentReferenceRecord(record.Record): _fields = [ record.Filler('recordcode', 4, '0150'), record.Filler('variantcode', 1, 'A'), - record.Field('paymentreference', 16), + StringField('paymentreference', 16), record.Filler('filler', 29), ] @@ -154,7 +162,7 @@ class DescriptionRecord(record.Record): _fields = [ record.Filler('recordcode', 4, '0160'), record.Filler('variantcode', 1, 'A'), - record.Field('description', 32), + StringField('description', 32), record.Filler('filler', 13), ] @@ -163,7 +171,7 @@ class NameBeneficiaryRecord(record.Record): _fields = [ record.Filler('recordcode', 4, '0170'), record.Filler('variantcode', 1, 'B'), - record.Field('name', 35), + StringField('name', 35), record.Filler('filler', 10), ] @@ -171,7 +179,7 @@ class OrderRecord(record.Record): '''Order details''' _fields = [ record.Filler('recordcode', 6, 'KAE092'), - record.Field('name_transactioncode', 18), + StringField('name_transactioncode', 18), record.NumberField('total_amount', 13), record.Field('accountno_sender', 10), record.NumberField('total_accountnos', 5), diff --git a/account_banking_nl_girotel/__terp__.py b/account_banking_nl_girotel/__terp__.py index fc2ceb6d4..e2e06af48 100644 --- a/account_banking_nl_girotel/__terp__.py +++ b/account_banking_nl_girotel/__terp__.py @@ -25,7 +25,7 @@ ############################################################################## { 'name': 'Account Banking - Girotel', - 'version': '0.47', + 'version': '0.49', 'license': 'GPL-3', 'author': 'EduSense BV', 'website': 'http://www.edusense.nl', diff --git a/account_banking_nl_girotel/girotel.py b/account_banking_nl_girotel/girotel.py index e6595dd58..b2b374732 100644 --- a/account_banking_nl_girotel/girotel.py +++ b/account_banking_nl_girotel/girotel.py @@ -37,9 +37,13 @@ Assumptions: 2. new transactions are appended after previously known transactions of the same date 3. banks maintain order in transaction lists within a single date + 4. the data comes from the SWIFT-network (limited ASCII) + +Assumption 4 seems not always true, leading to wrong character conversions. +As a counter measure, all imported data is converted to SWIFT-format before usage. ''' from account_banking.parsers import models -from account_banking.parsers.convert import str2date +from account_banking.parsers.convert import str2date, to_swift from tools.translate import _ import csv @@ -59,6 +63,15 @@ class transaction_message(object): ids = {} + def __setattribute__(self, attr, value): + if attr != 'attrnames' and attr in self.attrnames: + value = to_swift(value) + super(transaction_message, self).__setattribute__(attr, val) + + def __getattribute__(self, attr): + retval = super(transaction_message, self).__getattribute__(attr) + return attr != 'attrnames' and attr in self.attrnames and to_swift(retval) or retval + def genid(self): ''' Generate a new id when not assigned before diff --git a/account_banking_nl_multibank/__terp__.py b/account_banking_nl_multibank/__terp__.py index 021899d19..186c38524 100644 --- a/account_banking_nl_multibank/__terp__.py +++ b/account_banking_nl_multibank/__terp__.py @@ -25,7 +25,7 @@ ############################################################################## { 'name': 'Account Banking', - 'version': '0.47', + 'version': '0.49', 'license': 'GPL-3', 'author': 'EduSense BV', 'website': 'http://www.edusense.nl',