← Back to team overview

banking-addons-team team mailing list archive

lp:~therp-nl/banking-addons/6.1-lp1073545-meaningful_dates_in_currency_conversion into lp:banking-addons

 

Stefan Rijnhart (Therp) has proposed merging lp:~therp-nl/banking-addons/6.1-lp1073545-meaningful_dates_in_currency_conversion into lp:banking-addons.

Requested reviews:
  Banking Addons Team (banking-addons-team)
Related bugs:
  Bug #1073545 in Banking Addons: "Matching with different currencies in 6.1 will not full reconcile invoices"
  https://bugs.launchpad.net/banking-addons/+bug/1073545

For more details, see:
https://code.launchpad.net/~therp-nl/banking-addons/6.1-lp1073545-meaningful_dates_in_currency_conversion/+merge/132349
-- 
https://code.launchpad.net/~therp-nl/banking-addons/6.1-lp1073545-meaningful_dates_in_currency_conversion/+merge/132349
Your team Banking Addons Team is requested to review the proposed merge of lp:~therp-nl/banking-addons/6.1-lp1073545-meaningful_dates_in_currency_conversion into lp:banking-addons.
=== modified file 'account_banking/banking_import_transaction.py'
--- account_banking/banking_import_transaction.py	2012-05-07 11:38:26 +0000
+++ account_banking/banking_import_transaction.py	2012-10-31 15:13:25 +0000
@@ -494,7 +494,7 @@
         if from_curr_id != to_curr_id:
             amount_currency = statement_line_pool._convert_currency(
                 cr, uid, from_curr_id, to_curr_id, move_line_amount,
-                round=True, date=time.strftime('%Y-%m-%d'),
+                round=True, date=transaction.move_line_id.date,
                 context=context)
         else:
             amount_currency = move_line_amount
@@ -1319,7 +1319,8 @@
                             transaction.remote_owner, 
                             transaction.remote_owner_address,
                             transaction.remote_owner_city,
-                            country_code, results['log']
+                            country_code, results['log'],
+                            bic=transaction.remote_bank_bic
                             )
                         partner_banks = partner_bank_obj.browse(
                             cr, uid, [partner_bank_id]
@@ -1560,7 +1561,7 @@
                 from_curr_id = transaction.move_line_id.currency_id and transaction.move_line_id.currency_id.id or transaction.statement_id.company_id.currency_id.id
                 if from_curr_id != to_curr_id:
                     amount_currency = stline_pool._convert_currency(cr, uid, from_curr_id, to_curr_id, move_line_amount, round=True,
-                                                             date=time.strftime('%Y-%m-%d'), context=context)
+                                                             date=transaction.statement_line_id.date, context=context)
                 else:
                     amount_currency = move_line_amount
                 sign = 1

=== modified file 'account_banking/wizard/banktools.py'
--- account_banking/wizard/banktools.py	2012-06-26 11:17:32 +0000
+++ account_banking/wizard/banktools.py	2012-10-31 15:13:25 +0000
@@ -318,7 +318,7 @@
 
 def create_bank_account(pool, cursor, uid, partner_id,
                         account_number, holder_name, address, city,
-                        country_code, log
+                        country_code, log, bic=False,
                         ):
     '''
     Create a matching bank account with this holder for this partner.
@@ -328,7 +328,6 @@
         owner_name = holder_name,
     )
     bankcode = None
-    bic = None
     country_obj = pool.get('res.country')
 
     # Are we dealing with IBAN?

=== modified file 'account_banking_nl_abnamro/abnamro.py'
--- account_banking_nl_abnamro/abnamro.py	2012-01-17 08:48:10 +0000
+++ account_banking_nl_abnamro/abnamro.py	2012-10-31 15:13:25 +0000
@@ -88,6 +88,7 @@
         'GIRO': bt.ORDER,
         'INTL': bt.ORDER, # international order
         'UNKN': bt.ORDER, # everything else
+        'SEPA': bt.ORDER,
     }
 
     def __init__(self, line, *args, **kwargs):
@@ -134,24 +135,70 @@
             size = 33
             res = []
             while(len(line) > col * size):
-                if line[col * size : (col + 1) * size - 1].strip():
-                    res.append(line[col * size : (col + 1) * size - 1])
+                separation = (col + 1) * size - 1
+                if line[col * size : separation].strip():
+                    part = line[col * size : separation]
+                    # If the separation character is not a space, add it anyway
+                    # presumably for sepa feedback strings only
+                    if (len(line) > separation
+                        and line[separation] != ' '):
+                        part += line[separation]
+                    res.append(part)
                 col += 1
             return res
 
+        def get_sepa_dict(field):
+            """
+            Parses a subset of SEPA feedback strings as occur
+            in this non-SEPA csv format.
+
+            The string consists of slash separated KEY/VALUE pairs,
+            but the slash is allowed to and known to occur in VALUE as well!
+            """
+            items = field[1:].split('/') # skip leading slash
+            sepa_dict = {}
+            prev_key = False
+            known_keys = ['TRTP', 'IBAN', 'BIC', 'NAME', 'RTRN', 'EREF',
+                          'SWOC', 'REMI', ]
+            while items:
+                if len(items) == 1:
+                    raise osv.except_osv(
+                        _('Error !'),
+                        _("unable to parse SEPA string: %s") % field)
+                key = items.pop(0)
+                if key not in known_keys:
+                    # either an unknown key or a value containing a slash
+                    if prev_key:
+                        sepa_dict[prev_key] = sepa_dict[prev_key] + '/' + key
+                    else:
+                        raise osv.except_osv(
+                            _('Error !'),
+                            _("unable to parse SEPA string: %s") % field)
+                else:
+                    sepa_dict[key] = items.pop(0).strip()
+                    prev_key = key
+            return sepa_dict
+
         def parse_type(field):
             # here we process the first field, which identifies the statement type
             # and in case of certain types contains additional information
             transfer_type = 'UNKN'
             remote_account = False
             remote_owner = False
-            if field.startswith('GIRO '):
+            if field.startswith('/TRTP/'):
+                transfer_type = 'SEPA'
+            elif field.startswith('GIRO '):
                 transfer_type = 'GIRO'
-                # columns 6 to 14 contain the left or right aligned account number
-                remote_account = field[:15].strip().zfill(10)
-                # column 15 contains a space
-                # columns 16 to 31 contain remote owner
-                remote_owner = field[16:32].strip() or False
+                # field has markup 'GIRO ACCOUNT OWNER'
+                # separated by clusters of space of varying size
+                account_match = re.match('\s*([0-9]+)\s(.*)$', field[5:])
+                if account_match:
+                    remote_account = account_match.group(1).zfill(10)
+                    remote_owner = account_match.group(2).strip() or ''
+                else:
+                    raise osv.except_osv(
+                        _('Error !'),
+                        _('unable to parse GIRO string: %s') % field)
             elif field.startswith('BEA '):
                 transfer_type = 'BEA'
                 # columns 6 to 16 contain the terminal identifier
@@ -176,8 +223,22 @@
         fields = split_blob(self.blob)
         (self.transfer_type, self.remote_account, self.remote_owner) = parse_type(fields[0])
 
+        if self.transfer_type == 'SEPA':
+            sepa_dict = get_sepa_dict(''.join(fields))
+            sepa_type = sepa_dict.get('TRTP')
+            if sepa_type != 'SEPA OVERBOEKING':
+                raise ValueError,_('Sepa transaction type %s not handled yet')
+            self.remote_account = sepa_dict.get('IBAN',False)
+            self.remote_bank_bic = sepa_dict.get('BIC', False)
+            self.remote_owner = sepa_dict.get('NAME', False)
+            self.reference = sepa_dict.get('REMI', '')
+
         # extract other information depending on type
-        if self.transfer_type == 'GIRO':
+        elif self.transfer_type == 'GIRO':
+            if not self.remote_owner and len(fields) > 1:
+                # OWNER is listed in the second field if not in the first
+                self.remote_owner = fields[1].strip() or False
+                fields = [fields[0]] + fields[2:]
             self.message = ' '.join(field.strip() for field in fields[1:])
 
         elif self.transfer_type == 'BEA':
@@ -219,11 +280,12 @@
         if not self.reference:
             # the reference is sometimes flagged by the prefix "BETALINGSKENM."
             # but can be any numeric line really
-            refexpr = re.compile("^\s*(BETALINGSKENM\.)?\s*([0-9]+ ?)+\s*$")
             for field in fields[1:]:
-                m = refexpr.match(field)
+                m = re.match(
+                    "^\s*((BETALINGSKENM\.)|(ACCEPTGIRO))?\s*([0-9]+([ /][0-9]+)*)\s*$",
+                    field)
                 if m:
-                    self.reference = m.group(2)
+                    self.reference = m.group(4)
                     break
 
 class statement(models.mem_bank_statement):