diff --git a/account_banking/account_banking.py b/account_banking/account_banking.py
index 7f68b1cca..e49212284 100644
--- a/account_banking/account_banking.py
+++ b/account_banking/account_banking.py
@@ -501,6 +501,7 @@ class account_bank_statement(osv.osv):
'period_id': period_id, # AB
'date': st_line.date,
'name': st_line_number,
+ 'ref': st_line.ref,
}, context=context)
account_bank_statement_line_obj.write(cr, uid, [st_line.id], {
'move_ids': [(4, move_id, False)]
@@ -524,7 +525,6 @@ class account_bank_statement(osv.osv):
val = {
'name': st_line.name,
'date': st_line.date,
- 'ref': st_line.ref,
'move_id': move_id,
'partner_id': (((st_line.partner_id) and st_line.partner_id.id) or
False),
@@ -566,7 +566,6 @@ class account_bank_statement(osv.osv):
account_move_line_obj.create(cr, uid, {
'name': st_line.name,
'date': st_line.date,
- 'ref': st_line.ref,
'move_id': move_id,
'partner_id': (((st_line.partner_id) and st_line.partner_id.id) or
False),
diff --git a/account_banking/sepa/iban.py b/account_banking/sepa/iban.py
index 6ed5d06c5..9e1c9b35a 100644
--- a/account_banking/sepa/iban.py
+++ b/account_banking/sepa/iban.py
@@ -190,7 +190,7 @@ class IBAN(str):
BBAN_formats = {
'AL': BBANFormat('CCBBBBVAAAAAAAAAAAAAAAAAA', '%B%A'),
'AD': BBANFormat('CCCCBBBBAAAAAAAAAAAA', '%A'),
- 'AT': BBANFormat('BBBBBAAAAAAAAAAA', '%A BLZ %C'),
+ 'AT': BBANFormat('BBBBBAAAAAAAAAAA', '%A BLZ %B'),
'BE': BBANFormat('CCCAAAAAAAVV', '%C-%A-%V'),
'BA': BBANFormat('BBBCCCAAAAAAAA', '%I'),
'BG': BBANFormat('BBBBCCCCAAAAAAAAAA', '%I'),
@@ -214,7 +214,7 @@ class IBAN(str):
'GR': BBANFormat('BBBCCCCAAAAAAAAAAAAAAAA', '%B-%C-%A', nolz=True),
'HR': BBANFormat('BBBBBBBAAAAAAAAAA', '%B-%A'),
'HU': BBANFormat('BBBCCCCXAAAAAAAAAAAAAAAV', '%B%C%X %A%V'),
- 'IE': BBANFormat('BBBBCCCCCCAAAAAAAAV', '%C %A%V'),
+ 'IE': BBANFormat('BBBBCCCCCCAAAAAAAA', '%C %A'),
'IL': BBANFormat('BBBCCCAAAAAAAAAAAAA', '%C%A'),
# Iceland uses an extra identification number, split in two on
# display. Coded here as %P%V.
diff --git a/account_banking_sepa_credit_transfer/data/payment_type_sepa_sct.xml b/account_banking_sepa_credit_transfer/data/payment_type_sepa_sct.xml
index fce8213d0..322fb4b42 100644
--- a/account_banking_sepa_credit_transfer/data/payment_type_sepa_sct.xml
+++ b/account_banking_sepa_credit_transfer/data/payment_type_sepa_sct.xml
@@ -7,7 +7,8 @@
SEPA Credit Transfer v04
pain.001.001.04
-
+
payment
@@ -15,7 +16,8 @@
SEPA Credit Transfer v03
pain.001.001.03
-
+
payment
@@ -23,7 +25,8 @@
SEPA Credit Transfer v02
pain.001.001.02
-
+
payment
diff --git a/account_banking_sepa_credit_transfer/wizard/export_sepa.py b/account_banking_sepa_credit_transfer/wizard/export_sepa.py
index 3033674aa..bb059c466 100644
--- a/account_banking_sepa_credit_transfer/wizard/export_sepa.py
+++ b/account_banking_sepa_credit_transfer/wizard/export_sepa.py
@@ -212,8 +212,9 @@ class banking_export_sepa_wizard(osv.osv_memory):
debtor_account_iban.text = my_company_iban
debtor_agent = etree.SubElement(payment_info, 'DbtrAgt')
debtor_agent_institution = etree.SubElement(debtor_agent, 'FinInstnId')
- debtor_agent_bic = etree.SubElement(debtor_agent_institution, bic_xml_tag)
- debtor_agent_bic.text = my_company_bic
+ if my_company_bic:
+ debtor_agent_bic = etree.SubElement(debtor_agent_institution, bic_xml_tag)
+ debtor_agent_bic.text = my_company_bic
charge_bearer = etree.SubElement(payment_info, 'ChrgBr')
charge_bearer.text = sepa_export.charge_bearer
@@ -239,10 +240,11 @@ class banking_export_sepa_wizard(osv.osv_memory):
amount_control_sum += line.amount_currency
creditor_agent = etree.SubElement(credit_transfer_transaction_info, 'CdtrAgt')
creditor_agent_institution = etree.SubElement(creditor_agent, 'FinInstnId')
- creditor_agent_bic = etree.SubElement(creditor_agent_institution, bic_xml_tag)
if not line.bank_id:
raise osv.except_osv(_('Error :'), _("Missing Bank Account on invoice '%s' (payment order line reference '%s').") %(line.ml_inv_ref.number, line.name))
- creditor_agent_bic.text = line.bank_id.bank.bic
+ if line.bank_id.bank.bic:
+ creditor_agent_bic = etree.SubElement(creditor_agent_institution, bic_xml_tag)
+ creditor_agent_bic.text = line.bank_id.bank.bic
creditor = etree.SubElement(credit_transfer_transaction_info, 'Cdtr')
creditor_name = etree.SubElement(creditor, 'Nm')
creditor_name.text = self._limit_size(cr, uid, line.partner_id.name, name_maxsize, context=context)
diff --git a/account_banking_uk_lloyds_corporate/__init__.py b/account_banking_uk_lloyds_corporate/__init__.py
new file mode 100644
index 000000000..42f3e358b
--- /dev/null
+++ b/account_banking_uk_lloyds_corporate/__init__.py
@@ -0,0 +1,24 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2013 credativ Ltd ().
+# 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 (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import lloydscorporate
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/account_banking_uk_lloyds_corporate/__openerp__.py b/account_banking_uk_lloyds_corporate/__openerp__.py
new file mode 100644
index 000000000..a22592b96
--- /dev/null
+++ b/account_banking_uk_lloyds_corporate/__openerp__.py
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2013 credativ Ltd ().
+# 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 (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+{
+ 'name': 'Account Banking Lloyds Corporate CSV import',
+ 'version': '1.0',
+ 'license': 'AGPL-3',
+ 'author': 'credativ Ltd',
+ 'website': 'http://www.credativ.co.uk',
+ 'category': 'Account Banking',
+ 'depends': ['account_banking'],
+ 'init_xml': [],
+ 'update_xml': [],
+ 'demo_xml': [],
+ 'description': '''
+ Module to import bank statement CSV for Bank of Lloyds Corporate.
+ ''',
+ 'active': False,
+ 'installable': True,
+}
diff --git a/account_banking_uk_lloyds_corporate/lloydscorporate.py b/account_banking_uk_lloyds_corporate/lloydscorporate.py
new file mode 100644
index 000000000..fcf845cdf
--- /dev/null
+++ b/account_banking_uk_lloyds_corporate/lloydscorporate.py
@@ -0,0 +1,157 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2013 credativ Ltd ().
+# 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 (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+# Imports LLoyds Corporate format
+#
+
+from account_banking.parsers import models, convert
+from tools.translate import _
+import re
+import osv
+import logging
+import csv
+from StringIO import StringIO
+from operator import itemgetter
+
+logger = logging.getLogger('lloydscorporate_csv_import')
+
+class CSVTransaction(models.mem_bank_transaction):
+
+ mapping = {
+ 'execution_date' : 'date',
+ 'effective_date': 'date',
+ 'message' : 'description',
+ 'name' : 'description', # Use description as transaction name
+ 'balance' : 'Balance', # Store balance from line for calculating statement balances
+ }
+
+ def __init__(self, record, *args, **kwargs):
+ '''
+ Transaction creation
+ '''
+ super(CSVTransaction, self).__init__(*args, **kwargs)
+
+ # Parse date of format 01APR13
+ record['date'] = convert.str2date(re.sub(r'\W*','',record['Date']), '%d%b%y')
+
+ record['description'] = record['Narrative'].strip()
+
+ # Mapping of simple items
+ for key, value in self.mapping.iteritems():
+ if record.has_key(value):
+ setattr(self, key, record[value])
+
+ # Convert debit/credit to float amount
+ if len(record['Payments'].strip()):
+ self.transferred_amount = record['Payments'] and -float(record['Payments']) or 0.0
+ else:
+ self.transferred_amount = record['Receipts'] and float(record['Receipts']) or 0.0
+
+ # Cheque - set reference
+ transfer_account = re.match(r'\w*\s\d{1,12}$', record['description'])
+ if transfer_account:
+ self.reference = transfer_account.group()
+
+ if not self.is_valid():
+ logger.info("Invalid: %s", record)
+
+ def is_valid(self):
+ '''
+ We don't have remote_account so override base
+ '''
+ return (self.execution_date
+ and self.transferred_amount and True) or False
+
+class Statement(models.mem_bank_statement):
+
+ def import_statement(self, record):
+ self.transactions.append(CSVTransaction(record))
+
+def raise_error(message, line):
+ raise osv.osv.except_osv(_('Import error'),
+ 'Error in import:%s\n\n%s' % (message, line))
+
+class parser(models.parser):
+ code = 'LLOYDSCORPORATE-CSV'
+ name = _('Lloyds Corporate CSV Statement IMPORT')
+ country_code = 'GB'
+ doc = _('''\
+ This format is available through
+ the web interface.
+ ''')
+
+ def parse(self, cr, data):
+ ''' Lloyds corporate CSV parser'''
+
+ data = data.replace('\r','')
+ csv_header = data.split('\n')[0].replace('"', '').split(',')
+ header_list = ['Account', 'Date', 'Type', 'Narrative', 'Value Date', 'Payments', 'Receipts', 'Balance']
+ result = []
+
+ #compare header list and process csv if equal
+ if cmp(csv_header,header_list) != 0:
+ logger.info("Invalid import Statement:")
+ logger.info("Expected Header: %s" %(str(header_list)))
+ logger.info("Header found: %s"%(str(csv_header)))
+ raise osv.osv.except_osv(_('Import error'),
+ 'Error in import:%s\n' % (_('Invalid file format')))
+
+ bankdata = StringIO(data)
+ lines = list(csv.DictReader(bankdata))
+ stmnt = Statement()
+ # lines as they are imported
+ if len(lines):
+ #Store opening balance from first record
+ line = lines[0]
+ stmnt.start_balance = line['Balance']
+ account_number = re.sub('\D', '', line['Account'])
+
+ #Assuming if payment and receipts are both null then its opening balance
+ if not (line['Payments'] and line['Receipts']):
+ lines = lines[1:]
+
+ #Skip records which do not contains transaction type
+ for line in lines[:-int(len(lines)-map(itemgetter('Type'), lines).index(''))]:
+ #create Statement lines from csv records
+ stmnt.import_statement(line)
+
+ #Get statement Closing balance from CSV data list
+ try:
+ stmnt.end_balance = lines[map(itemgetter('Narrative'), lines).\
+ index('Closing Ledger Balance')]['Balance']
+ except ValueError:
+ raise osv.osv.except_osv(_('Closing Balance'),
+ _('Statement Closing Balance not found.'))
+
+
+ #GB account number format stored in ERP
+ stmnt.local_account = account_number[:6] +' '+ account_number[6:]
+
+ # Take date of last line of statement
+ stmnt.date = stmnt.transactions[-1].effective_date
+
+ statement_id = self.get_unique_statement_id(
+ cr, stmnt.date.strftime('%Yw%W'))
+ stmnt.id = statement_id
+ result.append(stmnt)
+ return result
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/account_banking_uk_lloyds_corporate/samplestatement.csv b/account_banking_uk_lloyds_corporate/samplestatement.csv
new file mode 100644
index 000000000..ce8dc1a56
--- /dev/null
+++ b/account_banking_uk_lloyds_corporate/samplestatement.csv
@@ -0,0 +1,14 @@
+"Account","Date","Type","Narrative","Value Date","Payments","Receipts","Balance"
+"210999-40010000 (GBP)",31MAY13,"","Opening Ledger Balance",,,,30000
+"210999-40010000 (GBP)",31MAY13,"BGC","AXELOR 56465463 BGC
+5656546456 30/05","","",20000,50000
+"210999-40010000 (GBP)",31MAY13,"CR","ARGOS
+INVOICES PAID","","",10000,60000
+"210999-40010000 (GBP)",31MAY13,"DR","DEBANHAMS
+EUROS 307.70","",2000,"",58000
+"210999-40010000 (GBP)",31MAY13,"DR","HOTEL HILTON PARKLANE","",2000,"",56000
+"210999-40010000 (GBP)",31MAY13,"DR","TO 30999999999999 TFR","",6000,"",50000
+"210999-40010000 (GBP)",21JUN13,"","Value of Credits (96)","","",30000,
+"210999-40010000 (GBP)",21JUN13,"","Value of Debits (43)","",10000,,
+"210999-40010000 (GBP)",21JUN13,"","Closing Ledger Balance","","","",50000
+"210999-40010000 (GBP)",21JUN13,"","Closing Cleared Balance","","","",50000
diff --git a/account_direct_debit/model/account_payment.py b/account_direct_debit/model/account_payment.py
index 0f6275f9b..aa69dec7c 100644
--- a/account_direct_debit/model/account_payment.py
+++ b/account_direct_debit/model/account_payment.py
@@ -153,7 +153,7 @@ class payment_order(osv.osv):
move_id = account_move_obj.create(cr, uid, {
'journal_id': order.mode.transfer_journal_id.id,
'name': 'Debit order %s' % line.move_line_id.move_id.name,
- 'reference': 'DEB%s' % line.move_line_id.move_id.name,
+ 'ref': 'DEB%s' % line.move_line_id.move_id.name,
}, context=context)
# TODO: take multicurrency into account