[FIX] account: create_sequence may not receive vals['company_id']
[odoo/odoo.git] / addons / account / account.py
index af5972a..342c2ef 100644 (file)
@@ -20,7 +20,6 @@
 ##############################################################################
 
 import time
-import random
 from datetime import datetime
 from dateutil.relativedelta import relativedelta
 from operator import itemgetter
@@ -103,7 +102,7 @@ class account_payment_term_line(osv.osv):
                                    ('fixed', 'Fixed Amount')], 'Valuation',
                                    required=True, help="""Select here the kind of valuation related to this payment term line. Note that you should have your last line with the type 'Balance' to ensure that the whole amount will be threated."""),
 
-        'value_amount': fields.float('Value Amount', digits_compute=dp.get_precision('Payment Term'), help="For Value percent enter % ratio between 0-1."),
+        'value_amount': fields.float('Amount To Pay', digits_compute=dp.get_precision('Payment Term'), help="For percent enter a ratio between 0-1."),
         'days': fields.integer('Number of Days', required=True, help="Number of days to add before computation of the day of month." \
             "If Date=15/01, Number of Days=22, Day of Month=-1, then the due date is 28/02."),
         'days2': fields.integer('Day of the Month', required=True, help="Day of the month, set -1 for the last day of the current month. If it's positive, it gives the day of the next month. Set 0 for net days (otherwise it's based on the beginning of the month)."),
@@ -132,7 +131,7 @@ class account_account_type(osv.osv):
     _name = "account.account.type"
     _description = "Account Type"
     _columns = {
-        'name': fields.char('Acc. Type Name', size=64, required=True),
+        'name': fields.char('Account Type', size=64, required=True),
         'code': fields.char('Code', size=32, required=True),
         'close_method': fields.selection([('none', 'None'), ('balance', 'Balance'), ('detail', 'Detail'), ('unreconciled', 'Unreconciled')], 'Deferral Method', required=True, help="""Set here the method that will be used to generate the end of year journal entries for all the accounts of this type.
 
@@ -140,14 +139,14 @@ class account_account_type(osv.osv):
  'Balance' will generally be used for cash accounts.
  'Detail' will copy each existing journal item of the previous year, even the reconciled ones.
  'Unreconciled' will copy only the journal items that were unreconciled on the first day of the new fiscal year."""),
-        'sign': fields.selection([(-1, 'Negative'), (1, 'Positive')], 'Sign on Reports', required=True, help='Allows you to change the sign of the balance amount displayed in the reports, so that you can see positive figures instead of negative ones in expenses accounts.'),
+        'sign': fields.selection([(-1, 'Reverse balance sign'), (1, 'Preserve balance sign')], 'Sign on Reports', required=True, help='For accounts that are typically more debited than credited and that you would like to print as negative amounts in your reports, you should reverse the sign of the balance; e.g.: Expense account. The same applies for  accounts that are typically more credited than debited and that you would like to print as positive amounts in your reports; e.g.: Income account.'),
         'report_type':fields.selection([
             ('none','/'),
             ('income','Profit & Loss (Income Accounts)'),
             ('expense','Profit & Loss (Expense Accounts)'),
-            ('asset','Balance Sheet (Assets Accounts)'),
+            ('asset','Balance Sheet (Asset Accounts)'),
             ('liability','Balance Sheet (Liability Accounts)')
-        ],'P&L / BS Category', select=True, readonly=False, help="According value related accounts will be display on respective reports (Balance Sheet Profit & Loss Account)", required=True),
+        ],'P&L / BS Category', select=True, readonly=False, help="This field is used to generate legal reports: profit and loss, balance sheet.", required=True),
         'note': fields.text('Description'),
     }
     _defaults = {
@@ -244,13 +243,15 @@ class account_account(osv.osv):
             'balance': "COALESCE(SUM(l.debit),0) " \
                        "- COALESCE(SUM(l.credit), 0) as balance",
             'debit': "COALESCE(SUM(l.debit), 0) as debit",
-            'credit': "COALESCE(SUM(l.credit), 0) as credit"
+            'credit': "COALESCE(SUM(l.credit), 0) as credit",
+            'foreign_balance': "COALESCE(SUM(l.amount_currency), 0) as foreign_balance",
         }
         #get all the necessary accounts
         children_and_consolidated = self._get_children_and_consol(cr, uid, ids, context=context)
         #compute for each account the balance/debit/credit from the move lines
         accounts = {}
         res = {}
+        null_result = dict((fn, 0.0) for fn in field_names)
         if children_and_consolidated:
             aml_query = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
 
@@ -270,7 +271,7 @@ class account_account(osv.osv):
             # ON l.account_id = tmp.id
             # or make _get_children_and_consol return a query and join on that
             request = ("SELECT l.account_id as id, " +\
-                       ', '.join(map(mapping.__getitem__, field_names)) +
+                       ', '.join(map(mapping.__getitem__, mapping.keys())) +
                        " FROM account_move_line l" \
                        " WHERE l.account_id IN %s " \
                             + filters +
@@ -289,7 +290,7 @@ class account_account(osv.osv):
             sums = {}
             currency_obj = self.pool.get('res.currency')
             while brs:
-                current = brs[0]
+                current = brs.pop(0)
 #                can_compute = True
 #                for child in current.child_id:
 #                    if child.id not in sums:
@@ -299,7 +300,6 @@ class account_account(osv.osv):
 #                        except ValueError:
 #                            brs.insert(0, child)
 #                if can_compute:
-                brs.pop(0)
                 for fn in field_names:
                     sums.setdefault(current.id, {})[fn] = accounts.get(current.id, {}).get(fn, 0.0)
                     for child in current.child_id:
@@ -307,12 +307,21 @@ class account_account(osv.osv):
                             sums[current.id][fn] += sums[child.id][fn]
                         else:
                             sums[current.id][fn] += currency_obj.compute(cr, uid, child.company_id.currency_id.id, current.company_id.currency_id.id, sums[child.id][fn], context=context)
-            null_result = dict((fn, 0.0) for fn in field_names)
+
+                # as we have to relay on values computed before this is calculated separately than previous fields
+                if current.currency_id and current.exchange_rate and \
+                            ('adjusted_balance' in field_names or 'unrealized_gain_loss' in field_names):
+                    # Computing Adjusted Balance and Unrealized Gains and losses
+                    # Adjusted Balance = Foreign Balance / Exchange Rate
+                    # Unrealized Gains and losses = Adjusted Balance - Balance
+                    adj_bal = sums[current.id].get('foreign_balance', 0.0) / current.exchange_rate
+                    sums[current.id].update({'adjusted_balance': adj_bal, 'unrealized_gain_loss': adj_bal - sums[current.id].get('balance', 0.0)})
+
             for id in ids:
                 res[id] = sums.get(id, null_result)
         else:
             for id in ids:
-                res[id] = 0.0
+                res[id] = null_result
         return res
 
     def _get_company_currency(self, cr, uid, ids, field_name, arg, context=None):
@@ -341,14 +350,61 @@ class account_account(osv.osv):
         accounts = self.browse(cr, uid, ids, context=context)
         for account in accounts:
             level = 0
-            if account.parent_id:
-                obj = self.browse(cr, uid, account.parent_id.id)
-                level = obj.level + 1
+            parent = account.parent_id
+            while parent:
+                level += 1
+                parent = parent.parent_id
             res[account.id] = level
         return res
 
+    def _set_credit_debit(self, cr, uid, account_id, name, value, arg, context=None):
+        if context.get('config_invisible', True):
+            return True
+
+        account = self.browse(cr, uid, account_id, context=context)
+        diff = value - getattr(account,name)
+        if not diff:
+            return True
+
+        journal_obj = self.pool.get('account.journal')
+        jids = journal_obj.search(cr, uid, [('type','=','situation'),('centralisation','=',1),('company_id','=',account.company_id.id)], context=context)
+        if not jids:
+            raise osv.except_osv(_('Error!'),_("You need an Opening journal with centralisation checked to set the initial balance!"))
+
+        period_obj = self.pool.get('account.period')
+        pids = period_obj.search(cr, uid, [('special','=',True),('company_id','=',account.company_id.id)], context=context)
+        if not pids:
+            raise osv.except_osv(_('Error!'),_("No opening/closing period defined, please create one to set the initial balance!"))
+
+        move_obj = self.pool.get('account.move.line')
+        move_id = move_obj.search(cr, uid, [
+            ('journal_id','=',jids[0]),
+            ('period_id','=',pids[0]),
+            ('account_id','=', account_id),
+            (name,'>', 0.0),
+            ('name','=', _('Opening Balance'))
+        ], context=context)
+        if move_id:
+            move = move_obj.browse(cr, uid, move_id[0], context=context)
+            move_obj.write(cr, uid, move_id[0], {
+                name: diff+getattr(move,name)
+            }, context=context)
+        else:
+            if diff<0.0:
+                raise osv.except_osv(_('Error!'),_("Unable to adapt the initial balance (negative value)!"))
+            nameinv = (name=='credit' and 'debit') or 'credit'
+            move_id = move_obj.create(cr, uid, {
+                'name': _('Opening Balance'),
+                'account_id': account_id,
+                'journal_id': jids[0],
+                'period_id': pids[0],
+                name: diff,
+                nameinv: 0.0
+            }, context=context)
+        return True
+
     _columns = {
-        'name': fields.char('Name', size=128, required=True, select=True),
+        'name': fields.char('Name', size=256, required=True, select=True),
         'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."),
         'code': fields.char('Code', size=64, required=True, select=1),
         'type': fields.selection([
@@ -359,21 +415,28 @@ class account_account(osv.osv):
             ('liquidity','Liquidity'),
             ('consolidation', 'Consolidation'),
             ('closed', 'Closed'),
-        ], 'Internal Type', required=True, help="This type is used to differentiate types with "\
-            "special effects in OpenERP: view can not have entries, consolidation are accounts that "\
+        ], 'Internal Type', required=True, help="The 'Internal Type' is used for features available on "\
+            "different types of accounts: view can not have journal items, consolidation are accounts that "\
             "can have children accounts for multi-company consolidations, payable/receivable are for "\
             "partners accounts (for debit/credit computations), closed for depreciated accounts."),
         'user_type': fields.many2one('account.account.type', 'Account Type', required=True,
-            help="These types are defined according to your country. The type contains more information "\
-            "about the account and its specificities."),
+            help="Account Type is used for information purpose, to generate "
+              "country-specific legal reports, and set the rules to close a fiscal year and generate opening entries."),
         'parent_id': fields.many2one('account.account', 'Parent', ondelete='cascade', domain=[('type','=','view')]),
         'child_parent_ids': fields.one2many('account.account','parent_id','Children'),
         'child_consol_ids': fields.many2many('account.account', 'account_account_consol_rel', 'child_id', 'parent_id', 'Consolidated Children'),
         'child_id': fields.function(_get_child_ids, type='many2many', relation="account.account", string="Child Accounts"),
         'balance': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Balance', multi='balance'),
-        'credit': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Credit', multi='balance'),
-        'debit': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Debit', multi='balance'),
-        'reconcile': fields.boolean('Reconcile', help="Check this if the user is allowed to reconcile entries in this account."),
+        'credit': fields.function(__compute, fnct_inv=_set_credit_debit, digits_compute=dp.get_precision('Account'), string='Credit', multi='balance'),
+        'debit': fields.function(__compute, fnct_inv=_set_credit_debit, digits_compute=dp.get_precision('Account'), string='Debit', multi='balance'),
+        'foreign_balance': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Foreign Balance', multi='balance',
+                                           help="Total amount (in Secondary currency) for transactions held in secondary currency for this account."),
+        'adjusted_balance': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Adjusted Balance', multi='balance',
+                                            help="Total amount (in Company currency) for transactions held in secondary currency for this account."),
+        'unrealized_gain_loss': fields.function(__compute, digits_compute=dp.get_precision('Account'), string='Unrealized Gain or Loss', multi='balance',
+                                                help="Value of Loss or Gain due to changes in exchange rate when doing multi-currency transactions."),
+        'reconcile': fields.boolean('Allow Reconciliation', help="Check this box if this account allows reconciliation of journal items."),
+        'exchange_rate': fields.related('currency_id', 'rate', type='float', string='Exchange Rate', digits=(12,6)),
         'shortcut': fields.char('Shortcut', size=12),
         'tax_ids': fields.many2many('account.tax', 'account_account_tax_default_rel',
             'account_id', 'tax_id', 'Default Taxes'),
@@ -391,11 +454,14 @@ class account_account(osv.osv):
             'manage this. So if you import from another software system you may have to use the rate at date. ' \
             'Incoming transactions always use the rate at date.', \
             required=True),
-        'level': fields.function(_get_level, string='Level', store=True, type='integer'),
+        'level': fields.function(_get_level, string='Level', method=True, type='integer',
+             store={
+                    'account.account': (_get_children_and_consol, ['level', 'parent_id'], 10),
+                   }),
     }
 
     _defaults = {
-        'type': 'view',
+        'type': 'other',
         'reconcile': False,
         'active': True,
         'currency_mode': 'current',
@@ -432,9 +498,16 @@ class account_account(osv.osv):
                 return False
         return True
 
+    def _check_account_type(self, cr, uid, ids, context=None):
+        for account in self.browse(cr, uid, ids, context=context):
+            if account.type in ('receivable', 'payable') and account.user_type.close_method != 'unreconciled':
+                return False
+        return True
+
     _constraints = [
         (_check_recursion, 'Error ! You can not create recursive accounts.', ['parent_id']),
-        (_check_type, 'Configuration Error! \nYou cannot define children to an account with internal type different of "View"! ', ['type']),
+        (_check_type, 'Configuration Error! \nYou can not define children to an account with internal type different of "View"! ', ['type']),
+        (_check_account_type, 'Configuration Error! \nYou can not select an account type with a deferral method different of "Unreconciled" for accounts with internal type "Payable/Receivable"! ', ['user_type','type']),
     ]
     _sql_constraints = [
         ('code_company_uniq', 'unique (code,company_id)', 'The code of the account must be unique per company !')
@@ -510,14 +583,14 @@ class account_account(osv.osv):
 
         if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]):
             if method == 'write':
-                raise osv.except_osv(_('Error !'), _('You cannot deactivate an account that contains account moves.'))
+                raise osv.except_osv(_('Error !'), _('You can not desactivate an account that contains some journal items.'))
             elif method == 'unlink':
-                raise osv.except_osv(_('Error !'), _('You cannot remove an account which has account entries!. '))
+                raise osv.except_osv(_('Error !'), _('You can not remove an account containing journal items!. '))
         #Checking whether the account is set as a property to any Partner or not
         value = 'account.account,' + str(ids[0])
         partner_prop_acc = self.pool.get('ir.property').search(cr, uid, [('value_reference','=',value)], context=context)
         if partner_prop_acc:
-            raise osv.except_osv(_('Warning !'), _('You cannot remove/deactivate an account which is set as a property to any Partner.'))
+            raise osv.except_osv(_('Warning !'), _('You can not remove/desactivate an account which is set on a customer or supplier.'))
         return True
 
     def _check_allow_type_change(self, cr, uid, ids, new_type, context=None):
@@ -530,15 +603,20 @@ class account_account(osv.osv):
             if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]):
                 #Check for 'Closed' type
                 if old_type == 'closed' and new_type !='closed':
-                    raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from 'Closed' to any other type which contains account entries!"))
+                    raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from 'Closed' to any other type which contains journal items!"))
                 #Check for change From group1 to group2 and vice versa
                 if (old_type in group1 and new_type in group2) or (old_type in group2 and new_type in group1):
-                    raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from '%s' to '%s' type as it contains account entries!") % (old_type,new_type,))
+                    raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from '%s' to '%s' type as it contains journal items!") % (old_type,new_type,))
         return True
 
     def write(self, cr, uid, ids, vals, context=None):
+
         if context is None:
             context = {}
+        if not ids:
+            return True
+        if isinstance(ids, (int, long)):
+            ids = [ids]
 
         # Dont allow changing the company_id when account_move_line already exist
         if 'company_id' in vals:
@@ -605,11 +683,11 @@ class account_journal(osv.osv):
         'name': fields.char('Journal Name', size=64, required=True),
         'code': fields.char('Code', size=5, required=True, help="The code will be displayed on reports."),
         'type': fields.selection([('sale', 'Sale'),('sale_refund','Sale Refund'), ('purchase', 'Purchase'), ('purchase_refund','Purchase Refund'), ('cash', 'Cash'), ('bank', 'Bank and Cheques'), ('general', 'General'), ('situation', 'Opening/Closing Situation')], 'Type', size=32, required=True,
-                                 help="Select 'Sale' for Sale journal to be used at the time of making invoice."\
-                                 " Select 'Purchase' for Purchase Journal to be used at the time of approving purchase order."\
-                                 " Select 'Cash' to be used at the time of making payment."\
-                                 " Select 'General' for miscellaneous operations."\
-                                 " Select 'Opening/Closing Situation' to be used at the time of new fiscal year creation or end of year entries generation."),
+                                 help="Select 'Sale' for customer invoices journals."\
+                                 " Select 'Purchase' for supplier invoices journals."\
+                                 " Select 'Cash' or 'Bank' for journals that are used in customer or supplier payments."\
+                                 " Select 'General' for miscellaneous operations journals."\
+                                 " Select 'Opening/Closing Situation' for entries generated for new fiscal years."),
         'type_control_ids': fields.many2many('account.account.type', 'account_journal_type_rel', 'journal_id','type_id', 'Type Controls', domain=[('code','<>','view'), ('code', '<>', 'closed')]),
         'account_control_ids': fields.many2many('account.account', 'account_account_type_rel', 'journal_id','account_id', 'Account', domain=[('type','<>','view'), ('type', '<>', 'closed')]),
         'view_id': fields.many2one('account.journal.view', 'Display Mode', required=True, help="Gives the view used when writing or browsing entries in this journal. The view tells OpenERP which fields should be visible, required or readonly and in which order. You can create your own view for a faster encoding in each journal."),
@@ -624,7 +702,7 @@ class account_journal(osv.osv):
         'currency': fields.many2one('res.currency', 'Currency', help='The currency used to enter statement'),
         'entry_posted': fields.boolean('Skip \'Draft\' State for Manual Entries', help='Check this box if you don\'t want new journal entries to pass through the \'draft\' state and instead goes directly to the \'posted state\' without any manual validation. \nNote that journal entries that are automatically created by the system are always skipping that state.'),
         'company_id': fields.many2one('res.company', 'Company', required=True, select=1, help="Company related to this journal"),
-        'allow_date':fields.boolean('Check Date not in the Period', help= 'If set to True then do not accept the entry if the entry date is not into the period dates'),
+        'allow_date':fields.boolean('Check Date in Period', help= 'If set to True then do not accept the entry if the entry date is not into the period dates'),
     }
 
     _defaults = {
@@ -638,6 +716,19 @@ class account_journal(osv.osv):
 
     _order = 'code'
 
+    def _check_currency(self, cr, uid, ids, context=None):
+        for journal in self.browse(cr, uid, ids, context=context):
+            if journal.currency:
+                if journal.default_credit_account_id and not journal.default_credit_account_id.currency_id.id == journal.currency.id:
+                    return False
+                if journal.default_debit_account_id and not journal.default_debit_account_id.currency_id.id == journal.currency.id:
+                    return False
+        return True
+
+    _constraints = [
+        (_check_currency, 'Configuration error! The currency chosen should be shared by the default accounts too.', ['currency','default_debit_account_id','default_credit_account_id']),
+    ]
+
     def copy(self, cr, uid, id, default={}, context=None, done_list=[], local=False):
         journal = self.browse(cr, uid, id, context=context)
         if not default:
@@ -651,44 +742,32 @@ class account_journal(osv.osv):
     def write(self, cr, uid, ids, vals, context=None):
         if context is None:
             context = {}
+        if isinstance(ids, (int, long)):
+            ids = [ids]
         for journal in self.browse(cr, uid, ids, context=context):
             if 'company_id' in vals and journal.company_id.id != vals['company_id']:
                 move_lines = self.pool.get('account.move.line').search(cr, uid, [('journal_id', 'in', ids)])
                 if move_lines:
-                    raise osv.except_osv(_('Warning !'), _('You cannot modify company of this journal as its related record exist in Entry Lines'))
+                    raise osv.except_osv(_('Warning !'), _('You can not modify the company of this journal as its related record exist in journal items'))
         return super(account_journal, self).write(cr, uid, ids, vals, context=context)
 
     def create_sequence(self, cr, uid, vals, context=None):
+        """ Create new no_gap entry sequence for every new Joural
         """
-        Create new entry sequence for every new Joural
-        @param cr: cursor to database
-        @param user: id of current user
-        @param ids: list of record ids to be process
-        @param context: context arguments, like lang, time zone
-        @return: return a result
-        """
-        seq_pool = self.pool.get('ir.sequence')
-        seq_typ_pool = self.pool.get('ir.sequence.type')
-
-        name = vals['name']
-        code = vals['code'].lower()
-
-        types = {
-            'name': name,
-            'code': code
-        }
-        seq_typ_pool.create(cr, uid, types)
+        # in account.journal code is actually the prefix of the sequence
+        # whereas ir.sequence code is a key to lookup global sequences.
+        prefix = vals['code'].upper()
 
         seq = {
-            'name': name,
-            'code': code,
-            'company_id': vals['company_id'],
-            'active': True,
-            'prefix': code + "/%(year)s/",
+            'name': vals['name'],
+            'implementation':'no_gap',
+            'prefix': prefix + "/%(year)s/",
             'padding': 4,
             'number_increment': 1
         }
-        return seq_pool.create(cr, uid, seq)
+        if 'company_id' in vals:
+            seq['company_id'] = vals['company_id']
+        return self.pool.get('ir.sequence').create(cr, uid, seq)
 
     def create(self, cr, uid, vals, context=None):
         if not 'sequence_id' in vals or not vals['sequence_id']:
@@ -710,9 +789,11 @@ class account_journal(osv.osv):
         result = self.browse(cr, user, ids, context=context)
         res = []
         for rs in result:
-            name = rs.name
             if rs.currency:
-                name = "%s (%s)" % (rs.name, rs.currency.name)
+                currency = rs.currency
+            else:
+                currency = rs.company_id.currency_id
+            name = "%s (%s)" % (rs.name, currency.name)
             res += [(rs.id, name)]
         return res
 
@@ -780,21 +861,8 @@ class account_fiscalyear(osv.osv):
         'state': 'draft',
         'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id,
     }
-    _order = "date_start"
-
-    def _check_fiscal_year(self, cr, uid, ids, context=None):
-        current_fiscal_yr = self.browse(cr, uid, ids, context=context)[0]
-        obj_fiscal_ids = self.search(cr, uid, [('company_id', '=', current_fiscal_yr.company_id.id)], context=context)
-        obj_fiscal_ids.remove(ids[0])
-        data_fiscal_yr = self.browse(cr, uid, obj_fiscal_ids, context=context)
-
-        for old_fy in data_fiscal_yr:
-            if old_fy.company_id.id == current_fiscal_yr['company_id'].id:
-                # Condition to check if the current fiscal year falls in between any previously defined fiscal year
-                if old_fy.date_start <= current_fiscal_yr['date_start'] <= old_fy.date_stop or \
-                    old_fy.date_start <= current_fiscal_yr['date_stop'] <= old_fy.date_stop:
-                    return False
-        return True
+    _order = "date_start, id"
+
 
     def _check_duration(self, cr, uid, ids, context=None):
         obj_fy = self.browse(cr, uid, ids[0], context=context)
@@ -803,8 +871,7 @@ class account_fiscalyear(osv.osv):
         return True
 
     _constraints = [
-        (_check_duration, 'Error! The duration of the Fiscal Year is invalid. ', ['date_stop']),
-        (_check_fiscal_year, 'Error! You cannot define overlapping fiscal years',['date_start', 'date_stop'])
+        (_check_duration, 'Error! The start date of the fiscal year must be before his end date.', ['date_start','date_stop'])
     ]
 
     def create_period3(self, cr, uid, ids, context=None):
@@ -815,7 +882,7 @@ class account_fiscalyear(osv.osv):
         for fy in self.browse(cr, uid, ids, context=context):
             ds = datetime.strptime(fy.date_start, '%Y-%m-%d')
             period_obj.create(cr, uid, {
-                    'name': _('Opening Period'),
+                    'name':  "%s %s" % (_('Opening Period'), ds.strftime('%Y')),
                     'code': ds.strftime('00/%Y'),
                     'date_start': ds,
                     'date_stop': ds,
@@ -839,15 +906,26 @@ class account_fiscalyear(osv.osv):
         return True
 
     def find(self, cr, uid, dt=None, exception=True, context=None):
+        res = self.finds(cr, uid, dt, exception, context=context)
+        return res and res[0] or False
+
+    def finds(self, cr, uid, dt=None, exception=True, context=None):
+        if context is None: context = {}
         if not dt:
             dt = time.strftime('%Y-%m-%d')
-        ids = self.search(cr, uid, [('date_start', '<=', dt), ('date_stop', '>=', dt)])
+        args = [('date_start', '<=' ,dt), ('date_stop', '>=', dt)]
+        if context.get('company_id', False):
+            args.append(('company_id', '=', context['company_id']))
+        else:
+            company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
+            args.append(('company_id', '=', company_id))
+        ids = self.search(cr, uid, args, context=context)
         if not ids:
             if exception:
                 raise osv.except_osv(_('Error !'), _('No fiscal year defined for this date !\nPlease create one.'))
             else:
-                return False
-        return ids[0]
+                return []
+        return ids
 
     def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80):
         if args is None:
@@ -882,6 +960,9 @@ class account_period(osv.osv):
         'state': 'draft',
     }
     _order = "date_start, special desc"
+    _sql_constraints = [
+        ('name_company_uniq', 'unique(name, company_id)', 'The name of the period must be unique per company!'),
+    ]
 
     def _check_duration(self,cr,uid,ids,context=None):
         obj_period = self.browse(cr, uid, ids[0], context=context)
@@ -918,10 +999,17 @@ class account_period(osv.osv):
         return False
 
     def find(self, cr, uid, dt=None, context=None):
+        if context is None: context = {}
         if not dt:
             dt = time.strftime('%Y-%m-%d')
 #CHECKME: shouldn't we check the state of the period?
-        ids = self.search(cr, uid, [('date_start','<=',dt),('date_stop','>=',dt)])
+        args = [('date_start', '<=' ,dt), ('date_stop', '>=', dt)]
+        if context.get('company_id', False):
+            args.append(('company_id', '=', context['company_id']))
+        else:
+            company_id = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
+            args.append(('company_id', '=', company_id))
+        ids = self.search(cr, uid, args, context=context)
         if not ids:
             raise osv.except_osv(_('Error !'), _('No period defined for this date: %s !\nPlease create one.')%dt)
         return ids
@@ -948,7 +1036,7 @@ class account_period(osv.osv):
         if 'company_id' in vals:
             move_lines = self.pool.get('account.move.line').search(cr, uid, [('period_id', 'in', ids)])
             if move_lines:
-                raise osv.except_osv(_('Warning !'), _('You cannot modify company of this period as its related record exist in Entry Lines'))
+                raise osv.except_osv(_('Warning !'), _('You can not modify company of this period as some journal items exists.'))
         return super(account_period, self).write(cr, uid, ids, vals, context=context)
 
     def build_ctx_periods(self, cr, uid, period_from_id, period_to_id):
@@ -1137,7 +1225,7 @@ class account_move(osv.osv):
         'period_id': fields.many2one('account.period', 'Period', required=True, states={'posted':[('readonly',True)]}),
         'journal_id': fields.many2one('account.journal', 'Journal', required=True, states={'posted':[('readonly',True)]}),
         'state': fields.selection([('draft','Unposted'), ('posted','Posted')], 'State', required=True, readonly=True,
-            help='All manually created new journal entry are usually in the state \'Unposted\', but you can set the option to skip that state on the related journal. In that case, they will be behave as journal entries automatically created by the system on document validation (invoices, bank statements...) and will be created in \'Posted\' state.'),
+            help='All manually created new journal entries are usually in the state \'Unposted\', but you can set the option to skip that state on the related journal. In that case, they will be behave as journal entries automatically created by the system on document validation (invoices, bank statements...) and will be created in \'Posted\' state.'),
         'line_id': fields.one2many('account.move.line', 'move_id', 'Entries', states={'posted':[('readonly',True)]}),
         'to_check': fields.boolean('To Review', help='Check this box if you are unsure of that journal entry and if you want to note it as \'to be reviewed\' by an accounting expert.'),
         'partner_id': fields.related('line_id', 'partner_id', type="many2one", relation="res.partner", string="Partner", store=True),
@@ -1165,22 +1253,10 @@ class account_move(osv.osv):
                     return False
         return True
 
-    def _check_period_journal(self, cursor, user, ids, context=None):
-        for move in self.browse(cursor, user, ids, context=context):
-            for line in move.line_id:
-                if line.period_id.id != move.period_id.id:
-                    return False
-                if line.journal_id.id != move.journal_id.id:
-                    return False
-        return True
-
     _constraints = [
         (_check_centralisation,
-            'You cannot create more than one move per period on centralized journal',
+            'You can not create more than one move per period on centralized journal',
             ['journal_id']),
-        (_check_period_journal,
-            'You cannot create entries on different periods/journals in the same move',
-            ['line_id']),
     ]
 
     def post(self, cr, uid, ids, context=None):
@@ -1190,7 +1266,7 @@ class account_move(osv.osv):
         valid_moves = self.validate(cr, uid, ids, context)
 
         if not valid_moves:
-            raise osv.except_osv(_('Integrity Error !'), _('You cannot validate a non-balanced entry !\nMake sure you have configured Payment Term properly !\nIt should contain atleast one Payment Term Line with type "Balance" !'))
+            raise osv.except_osv(_('Integrity Error !'), _('You can not validate a non-balanced entry !\nMake sure you have configured payment terms properly !\nThe latest payment term line should be of the type "Balance" !'))
         obj_sequence = self.pool.get('ir.sequence')
         for move in self.browse(cr, uid, valid_moves, context=context):
             if move.name =='/':
@@ -1202,7 +1278,7 @@ class account_move(osv.osv):
                 else:
                     if journal.sequence_id:
                         c = {'fiscalyear_id': move.period_id.fiscalyear_id.id}
-                        new_name = obj_sequence.get_id(cr, uid, journal.sequence_id.id, context=c)
+                        new_name = obj_sequence.next_by_id(cr, uid, journal.sequence_id.id, c)
                     else:
                         raise osv.except_osv(_('Error'), _('No sequence defined on the journal !'))
 
@@ -1226,7 +1302,7 @@ class account_move(osv.osv):
                 if not top:
                     top = account2.id
                 elif top<>account2.id:
-                    raise osv.except_osv(_('Error !'), _('You cannot validate a Journal Entry unless all journal items are in same chart of accounts !'))
+                    raise osv.except_osv(_('Error !'), _('You can not validate a journal entry unless all journal items belongs to the same chart of accounts !'))
         return self.post(cursor, user, ids, context=context)
 
     def button_cancel(self, cr, uid, ids, context=None):
@@ -1244,7 +1320,7 @@ class account_move(osv.osv):
             context = {}
         c = context.copy()
         c['novalidate'] = True
-        result = super(osv.osv, self).write(cr, uid, ids, vals, c)
+        result = super(account_move, self).write(cr, uid, ids, vals, c)
         self.validate(cr, uid, ids, context=context)
         return result
 
@@ -1313,7 +1389,7 @@ class account_move(osv.osv):
         for move in self.browse(cr, uid, ids, context=context):
             if move['state'] != 'draft':
                 raise osv.except_osv(_('UserError'),
-                        _('You can not delete posted movement: "%s"!') % \
+                        _('You can not delete a posted journal entry "%s"!') % \
                                 move['name'])
             line_ids = map(lambda x: x.id, move.line_id)
             context['journal_id'] = move.journal_id.id
@@ -1333,7 +1409,7 @@ class account_move(osv.osv):
 
     def _centralise(self, cr, uid, move, mode, context=None):
         assert mode in ('debit', 'credit'), 'Invalid Mode' #to prevent sql injection
-        currency_obj = self.pool.get('res.currency') 
+        currency_obj = self.pool.get('res.currency')
         if context is None:
             context = {}
 
@@ -1463,8 +1539,6 @@ class account_move(osv.osv):
                 # Update the move lines (set them as valid)
 
                 obj_move_line.write(cr, uid, line_draft_ids, {
-                    'journal_id': move.journal_id.id,
-                    'period_id': move.period_id.id,
                     'state': 'valid'
                 }, context, check=False)
 
@@ -1505,8 +1579,6 @@ class account_move(osv.osv):
                 # We can't validate it (it's unbalanced)
                 # Setting the lines as draft
                 obj_move_line.write(cr, uid, line_ids, {
-                    'journal_id': move.journal_id.id,
-                    'period_id': move.period_id.id,
                     'state': 'draft'
                 }, context, check=False)
         # Create analytic lines for the valid moves
@@ -1531,11 +1603,15 @@ class account_move_reconcile(osv.osv):
     _defaults = {
         'name': lambda self,cr,uid,ctx={}: self.pool.get('ir.sequence').get(cr, uid, 'account.reconcile') or '/',
     }
+
     def reconcile_partial_check(self, cr, uid, ids, type='auto', context=None):
         total = 0.0
         for rec in self.browse(cr, uid, ids, context=context):
             for line in rec.line_partial_ids:
-                total += (line.debit or 0.0) - (line.credit or 0.0)
+                if line.account_id.currency_id:
+                    total += line.amount_currency
+                else:
+                    total += (line.debit or 0.0) - (line.credit or 0.0)
         if not total:
             self.pool.get('account.move.line').write(cr, uid,
                 map(lambda x: x.id, rec.line_partial_ids),
@@ -1595,7 +1671,7 @@ class account_tax_code(osv.osv):
                        (parent_ids,) + where_params)
         res=dict(cr.fetchall())
         obj_precision = self.pool.get('decimal.precision')
-        res2 = {} 
+        res2 = {}
         for record in self.browse(cr, uid, ids, context=context):
             def _rec_get(record):
                 amount = res.get(record.id, 0.0)
@@ -1612,13 +1688,15 @@ class account_tax_code(osv.osv):
         if context.get('state', 'all') == 'all':
             move_state = ('draft', 'posted', )
         if context.get('fiscalyear_id', False):
-            fiscalyear_id = context['fiscalyear_id']
+            fiscalyear_id = [context['fiscalyear_id']]
         else:
-            fiscalyear_id = self.pool.get('account.fiscalyear').find(cr, uid, exception=False)
+            fiscalyear_id = self.pool.get('account.fiscalyear').finds(cr, uid, exception=False)
         where = ''
         where_params = ()
         if fiscalyear_id:
-            pids = map(lambda x: str(x.id), self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id).period_ids)
+            pids = []
+            for fy in fiscalyear_id:
+                pids += map(lambda x: str(x.id), self.pool.get('account.fiscalyear').browse(cr, uid, fy).period_ids)
             if pids:
                 where = ' AND line.period_id IN %s AND move.state IN %s '
                 where_params = (tuple(pids), move_state)
@@ -1764,6 +1842,9 @@ class account_tax(osv.osv):
         'type_tax_use': fields.selection([('sale','Sale'),('purchase','Purchase'),('all','All')], 'Tax Application', required=True)
 
     }
+    _sql_constraints = [
+        ('name_company_uniq', 'unique(name, company_id)', 'Tax Name must be unique per company!'),
+    ]
 
     def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80):
         """
@@ -1927,8 +2008,11 @@ class account_tax(osv.osv):
                 cur_price_unit+=amount2
         return res
 
-    def compute_all(self, cr, uid, taxes, price_unit, quantity, address_id=None, product=None, partner=None):
+    def compute_all(self, cr, uid, taxes, price_unit, quantity, address_id=None, product=None, partner=None, force_excluded=False):
         """
+        :param force_excluded: boolean used to say that we don't want to consider the value of field price_include of
+            tax. It's used in encoding by line where you don't matter if you encoded a tax with that boolean to True or
+            False
         RETURN: {
                 'total': 0.0,                # Total without taxes
                 'total_included: 0.0,        # Total with taxes
@@ -1940,10 +2024,10 @@ class account_tax(osv.osv):
         tin = []
         tex = []
         for tax in taxes:
-            if tax.price_include:
-                tin.append(tax)
-            else:
+            if not tax.price_include or force_excluded:
                 tex.append(tax)
+            else:
+                tin.append(tax)
         tin = self.compute_inv(cr, uid, tin, price_unit, quantity, address_id=address_id, product=product, partner=partner)
         for r in tin:
             totalex -= r.get('amount', 0.0)
@@ -2109,6 +2193,7 @@ class account_model(osv.osv):
         account_move_obj = self.pool.get('account.move')
         account_move_line_obj = self.pool.get('account.move.line')
         pt_obj = self.pool.get('account.payment.term')
+        period_obj = self.pool.get('account.period')
 
         if context is None:
             context = {}
@@ -2116,13 +2201,18 @@ class account_model(osv.osv):
         if datas.get('date', False):
             context.update({'date': datas['date']})
 
-        period_id = self.pool.get('account.period').find(cr, uid, dt=context.get('date', False))
-        if not period_id:
-            raise osv.except_osv(_('No period found !'), _('Unable to find a valid period !'))
-        period_id = period_id[0]
-
+        move_date = context.get('date', time.strftime('%Y-%m-%d'))
+        move_date = datetime.strptime(move_date,"%Y-%m-%d")
         for model in self.browse(cr, uid, ids, context=context):
-            entry['name'] = model.name%{'year':time.strftime('%Y'), 'month':time.strftime('%m'), 'date':time.strftime('%Y-%m')}
+            ctx = context.copy()
+            ctx.update({'company_id': model.company_id.id})
+            period_ids = period_obj.find(cr, uid, dt=context.get('date', False), context=ctx)
+            period_id = period_ids and period_ids[0] or False
+            ctx.update({'journal_id': model.journal_id.id,'period_id': period_id})
+            try:
+                entry['name'] = model.name%{'year': move_date.strftime('%Y'), 'month': move_date.strftime('%m'), 'date': move_date.strftime('%Y-%m')}
+            except:
+                raise osv.except_osv(_('Wrong model !'), _('You have a wrong expression "%(...)s" in your model !'))
             move_id = account_move_obj.create(cr, uid, {
                 'ref': entry['name'],
                 'period_id': period_id,
@@ -2143,7 +2233,7 @@ class account_model(osv.osv):
                     'analytic_account_id': analytic_account_id
                 }
 
-                date_maturity = time.strftime('%Y-%m-%d')
+                date_maturity = context.get('date',time.strftime('%Y-%m-%d'))
                 if line.date_maturity == 'partner':
                     if not line.partner_id:
                         raise osv.except_osv(_('Error !'), _("Maturity date of entry line generated by model line '%s' of model '%s' is based on partner payment term!" \
@@ -2167,9 +2257,7 @@ class account_model(osv.osv):
                     'date': context.get('date',time.strftime('%Y-%m-%d')),
                     'date_maturity': date_maturity
                 })
-                c = context.copy()
-                c.update({'journal_id': model.journal_id.id,'period_id': period_id})
-                account_move_line_obj.create(cr, uid, val, context=c)
+                account_move_line_obj.create(cr, uid, val, context=ctx)
 
         return move_ids
 
@@ -2194,8 +2282,8 @@ class account_model_line(osv.osv):
     }
     _order = 'sequence'
     _sql_constraints = [
-        ('credit_debit1', 'CHECK (credit*debit=0)',  'Wrong credit or debit value in model (Credit Or Debit Must Be "0")!'),
-        ('credit_debit2', 'CHECK (credit+debit>=0)', 'Wrong credit or debit value in model (Credit + Debit Must Be greater "0")!'),
+        ('credit_debit1', 'CHECK (credit*debit=0)',  'Wrong credit or debit value in model, they must be positive!'),
+        ('credit_debit2', 'CHECK (credit+debit>=0)', 'Wrong credit or debit value in model, they must be positive!'),
     ]
 account_model_line()
 
@@ -2316,7 +2404,7 @@ class account_account_template(osv.osv):
     _description ='Templates for Accounts'
 
     _columns = {
-        'name': fields.char('Name', size=128, required=True, select=True),
+        'name': fields.char('Name', size=256, required=True, select=True),
         'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."),
         'code': fields.char('Code', size=64, select=1),
         'type': fields.selection([
@@ -2341,6 +2429,7 @@ class account_account_template(osv.osv):
         'child_parent_ids':fields.one2many('account.account.template', 'parent_id', 'Children'),
         'tax_ids': fields.many2many('account.tax.template', 'account_account_template_tax_rel', 'account_id', 'tax_id', 'Default Taxes'),
         'nocreate': fields.boolean('Optional create', help="If checked, the new chart of accounts will not contain this by default."),
+        'chart_template_id': fields.many2one('account.chart.template', 'Chart Template'),
     }
 
     _defaults = {
@@ -2361,7 +2450,7 @@ class account_account_template(osv.osv):
     _check_recursion = check_cycle
     _constraints = [
         (_check_recursion, 'Error ! You can not create recursive account templates.', ['parent_id']),
-        (_check_type, 'Configuration Error! \nYou cannot define children to an account with internal type different of "View"! ', ['type']),
+        (_check_type, 'Configuration Error!\nYou can not define children to an account with internal type different of "View"! ', ['type']),
 
     ]
 
@@ -2377,7 +2466,7 @@ class account_account_template(osv.osv):
             res.append((record['id'],name ))
         return res
 
-    def generate_account(self, cr, uid, template_id, account_root_id, tax_template_ref, code_digits, company_id, context=None):
+    def generate_account(self, cr, uid, template_id, tax_template_ref, acc_template_ref, code_digits, company_id, context=None):
         """
         This method for generating accounts from templates.
         @param cr: A database cursor.
@@ -2387,18 +2476,20 @@ class account_account_template(osv.osv):
         @param code_digits: Digit getting from wizard.multi.charts.accounts.,this is use for account code.
         @param company_id: company_id selected from wizard.multi.charts.accounts.
         @return : return acc_template_ref for reference purpose.
-        
         """
         if context is None:
             context = {}
         obj_acc = self.pool.get('account.account')
         company_name = self.pool.get('res.company').browse(cr, uid, company_id, context=context).name
-        acc_template_ref = {}
+        template = self.pool.get('account.chart.template').browse(cr, uid, template_id, context=context)
         #deactivate the parent_store functionnality on account_account for rapidity purpose
         ctx = context.copy()
         ctx.update({'defer_parent_store_computation': True})
-        children_acc_template = self.search(cr, uid, [('parent_id','child_of', [account_root_id]),'|', ('chart_template_id','=', [template_id]),('chart_template_id','=', False), ('nocreate','!=',True)], order='id')
+        children_acc_template = self.search(cr, uid, ['|', ('chart_template_id','=', [template_id]),'&',('parent_id','child_of', [template.account_root_id.id]),('chart_template_id','=', False), ('nocreate','!=',True)], order='id')
         for account_template in self.browse(cr, uid, children_acc_template, context=context):
+            # skip the root of COA if it's not the main one
+            if (template.account_root_id.id == account_template.id) and template.parent_id:
+                continue
             tax_ids = []
             for tax in account_template.tax_ids:
                 tax_ids.append(tax_template_ref[tax.id])
@@ -2408,7 +2499,7 @@ class account_account_template(osv.osv):
             if code_main > 0 and code_main <= code_digits and account_template.type != 'view':
                 code_acc = str(code_acc) + (str('0'*(code_digits-code_main)))
             vals={
-                'name': (account_root_id == account_template.id) and company_name or account_template.name,
+                'name': (template.account_root_id.id == account_template.id) and company_name or account_template.name,
                 'currency_id': account_template.currency_id and account_template.currency_id.id or False,
                 'code': code_acc,
                 'type': account_template.type,
@@ -2444,7 +2535,7 @@ class account_add_tmpl_wizard(osv.osv_memory):
         ptids = tmpl_obj.read(cr, uid, [tids[0]['parent_id'][0]], ['code'])
         res = None
         if not ptids or not ptids[0]['code']:
-            raise osv.except_osv(_('Error !'), _('Cannot locate parent code for template account!'))
+            raise osv.except_osv(_('Error !'), _('I can not locate a parent code for the template account!'))
             res = acc_obj.search(cr, uid, [('code','=',ptids[0]['code'])])
         return res and res[0] or False
 
@@ -2504,6 +2595,41 @@ class account_tax_code_template(osv.osv):
         'notprintable': False,
     }
 
+    def generate_tax_code(self, cr, uid, tax_code_root_id, company_id, context=None):
+        '''
+        This function generates the tax codes from the templates of tax code that are children of the given one passed
+        in argument. Then it returns a dictionary with the mappping between the templates and the real objects.
+
+        :param tax_code_root_id: id of the root of all the tax code templates to process
+        :param company_id: id of the company the wizard is running for
+        :returns: dictionary with the mappping between the templates and the real objects.
+        :rtype: dict
+        '''
+        obj_tax_code_template = self.pool.get('account.tax.code.template')
+        obj_tax_code = self.pool.get('account.tax.code')
+        tax_code_template_ref = {}
+        company = self.pool.get('res.company').browse(cr, uid, company_id, context=context)
+
+        #find all the children of the tax_code_root_id
+        children_tax_code_template = obj_tax_code_template.search(cr, uid, [('parent_id','child_of',[tax_code_root_id])], order='id')
+        for tax_code_template in obj_tax_code_template.browse(cr, uid, children_tax_code_template, context=context):
+            vals = {
+                'name': (tax_code_root_id == tax_code_template.id) and company.name or tax_code_template.name,
+                'code': tax_code_template.code,
+                'info': tax_code_template.info,
+                'parent_id': tax_code_template.parent_id and ((tax_code_template.parent_id.id in tax_code_template_ref) and tax_code_template_ref[tax_code_template.parent_id.id]) or False,
+                'company_id': company_id,
+                'sign': tax_code_template.sign,
+            }
+            #check if this tax code already exists
+            rec_list = obj_tax_code.search(cr, uid, [('name', '=', vals['name']),('code', '=', vals['code']),('company_id', '=', vals['company_id'])], context=context)
+            if not rec_list:
+                #if not yet, create it
+                new_tax_code = obj_tax_code.create(cr, uid, vals)
+                #recording the new tax code to do the mapping
+                tax_code_template_ref[tax_code_template.id] = new_tax_code
+        return tax_code_template_ref
+
     def name_get(self, cr, uid, ids, context=None):
         if not ids:
             return []
@@ -2530,7 +2656,7 @@ class account_chart_template(osv.osv):
         'parent_id': fields.many2one('account.chart.template', 'Parent Chart Template'),
         'code_digits': fields.integer('# of Digits', required=True, help="No. of Digits to use for account code"), 
         'visible': fields.boolean('Can be Visible?', help="Set this to False if you don't want this template to be used actively in the wizard that generate Chart of Accounts from templates, this is useful when you want to generate accounts of this template only when loading its child template."),
-        'set_tax_complete': fields.boolean('Complete Set of Tax', help="Check this if you want to create new default Sales and Purchase taxes from selected rate instead of choosing it from list of taxes."),
+        'complete_tax_set': fields.boolean('Complete Set of Taxes', help='This boolean helps you to choose if you want to propose to the user to encode the sale and purchase rates or choose from list of taxes. This last choice assumes that the set of tax defined on this template is complete'),
         'account_root_id': fields.many2one('account.account.template', 'Root Account', domain=[('parent_id','=',False)]),
         'tax_code_root_id': fields.many2one('account.tax.code.template', 'Root Tax Code', domain=[('parent_id','=',False)]),
         'tax_template_ids': fields.one2many('account.tax.template', 'chart_template_id', 'Tax Template List', help='List of all the taxes that have to be installed by the wizard'),
@@ -2548,7 +2674,8 @@ class account_chart_template(osv.osv):
 
     _defaults = {
         'visible': True,
-        'code_digits': 6
+        'code_digits': 6,
+        'complete_tax_set': True,
     }
 
 account_chart_template()
@@ -2628,26 +2755,23 @@ class account_tax_template(osv.osv):
     }
     _order = 'sequence'
 
-    def generate_tax(self, cr, uid, tax_templates, tax_code_template_ref, company_id, context=None):
+    def _generate_tax(self, cr, uid, tax_templates, tax_code_template_ref, company_id, context=None):
         """
         This method generate taxes from templates.
-        @param cr: A database cursor.
-        @param uid: ID of the user currently logged in.
-        @param tax_templates: Tax templates.
-        @param tax_code_template_ref: Taxcode templates reference.
-        @param company_id: if tax generated from account multi wizard at that time company_id is wizard company_id field
-        or logged user company_id.
-        @param Return: 
-        {'taxes_id': New generated taxes ids, 
-         'account_dict': Used this reference value for Account Tax, 
-         'tax_template_ref': Used this reference value for Fiscal Position
-        }
+
+        :param tax_templates: list of browse record of the tax templates to process
+        :param tax_code_template_ref: Taxcode templates reference.
+        :param company_id: id of the company the wizard is running for
+        :returns:
+            {
+            'tax_template_to_tax': mapping between tax template and the newly generated taxes corresponding,
+            'account_dict': dictionary containing a to-do list with all the accounts to assign on new taxes
+            }
         """
         if context is None:
             context = {}
         res = {}
         todo_dict = {}
-        tax_template_ref = {}
         tax_template_to_tax = {}
         for tax in tax_templates:
             vals_tax = {
@@ -2657,7 +2781,7 @@ class account_tax_template(osv.osv):
                 'type': tax.type,
                 'applicable_type': tax.applicable_type,
                 'domain': tax.domain,
-                'parent_id': tax.parent_id and ((tax.parent_id.id in tax_template_ref) and tax_template_ref[tax.parent_id.id]) or False,
+                'parent_id': tax.parent_id and ((tax.parent_id.id in tax_template_to_tax) and tax_template_to_tax[tax.parent_id.id]) or False,
                 'child_depend': tax.child_depend,
                 'python_compute': tax.python_compute,
                 'python_compute_inv': tax.python_compute_inv,
@@ -2683,8 +2807,7 @@ class account_tax_template(osv.osv):
                 'account_collected_id': tax.account_collected_id and tax.account_collected_id.id or False,
                 'account_paid_id': tax.account_paid_id and tax.account_paid_id.id or False,
             }
-            tax_template_ref[tax.id] = new_tax
-        res.update({'taxes_id': tax_template_to_tax, 'account_dict': todo_dict, 'tax_template_ref': tax_template_ref})
+        res.update({'tax_template_to_tax': tax_template_to_tax, 'account_dict': todo_dict})
         return res
 
 account_tax_template()
@@ -2699,7 +2822,8 @@ class account_fiscal_position_template(osv.osv):
         'name': fields.char('Fiscal Position Template', size=64, required=True),
         'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True),
         'account_ids': fields.one2many('account.fiscal.position.account.template', 'position_id', 'Account Mapping'),
-        'tax_ids': fields.one2many('account.fiscal.position.tax.template', 'position_id', 'Tax Mapping')
+        'tax_ids': fields.one2many('account.fiscal.position.tax.template', 'position_id', 'Tax Mapping'),
+        'note': fields.text('Notes', translate=True),
     }
 
     def generate_fiscal_position(self, cr, uid, chart_temp_id, tax_template_ref, acc_template_ref, company_id, context=None):
@@ -2761,7 +2885,88 @@ class account_fiscal_position_account_template(osv.osv):
 
 account_fiscal_position_account_template()
 
-    # Multi charts of Accounts wizard
+# ---------------------------------------------------------
+# Account Financial Report
+# ---------------------------------------------------------
+
+class account_financial_report(osv.osv):
+    _name = "account.financial.report"
+    _description = "Account Report"
+
+    def _get_level(self, cr, uid, ids, field_name, arg, context=None):
+        res = {}
+        for report in self.browse(cr, uid, ids, context=context):
+            level = 0
+            if report.parent_id:
+                level = report.parent_id.level + 1
+            res[report.id] = level
+        return res
+
+    def _get_children_by_order(self, cr, uid, ids, context=None):
+        res = []
+        for id in ids:
+            res.append(id)
+            ids2 = self.search(cr, uid, [('parent_id', '=', id)], order='sequence ASC', context=context)
+            res += self._get_children_by_order(cr, uid, ids2, context=context)
+        return res
+
+    def _get_balance(self, cr, uid, ids, name, args, context=None):
+        res = {}
+        res_all = {}
+        for report in self.browse(cr, uid, ids, context=context):
+            balance = 0.0
+            if report.id in res_all:
+                balance = res_all[report.id]
+            elif report.type == 'accounts':
+                # it's the sum of balance of the linked accounts
+                for a in report.account_ids:
+                    balance += a.balance
+            elif report.type == 'account_report' and report.account_report_id:
+                # it's the amount of the linked report
+                res2 = self._get_balance(cr, uid, [report.account_report_id.id], 'balance', False, context=context)
+                res_all.update(res2)
+                for key, value in res2.items():
+                    balance += value
+            elif report.type == 'sum':
+                # it's the sum of balance of the children of this account.report
+                #for child in report.children_ids:
+                res2 = self._get_balance(cr, uid, [rec.id for rec in report.children_ids], 'balance', False, context=context)
+                res_all.update(res2)
+                for key, value in res2.items():
+                    balance += value
+            res[report.id] = balance
+            res_all[report.id] = balance
+        return res
+
+    _columns = {
+        'name': fields.char('Report Name', size=128, required=True, translate=True),
+        'parent_id': fields.many2one('account.financial.report', 'Parent'),
+        'children_ids':  fields.one2many('account.financial.report', 'parent_id', 'Account Report'),
+        'sequence': fields.integer('Sequence'),
+        'note': fields.text('Notes'),
+        'balance': fields.function(_get_balance, 'Balance'),
+        'level': fields.function(_get_level, string='Level', store=True, type='integer'),
+        'type': fields.selection([
+            ('sum','View'),
+            ('accounts','Accounts'),
+            ('account_type','Account Type'),
+            ('account_report','Report Value'),
+            ],'Type'),
+        'account_ids': fields.many2many('account.account', 'account_account_financial_report', 'report_line_id', 'account_id', 'Accounts'),
+        'display_detail': fields.boolean('Display details', help='Display every account with its balance instead of the sum.'),
+        'account_report_id':  fields.many2one('account.financial.report', 'Report Value'),
+        'account_type_ids': fields.many2many('account.account.type', 'account_account_financial_report_type', 'report_id', 'account_type_id', 'Account Types'),
+    }
+
+    _defaults = {
+        'type': 'sum',
+    }
+
+account_financial_report()
+
+# ---------------------------------------------------------
+# Account generation from template wizards
+# ---------------------------------------------------------
 
 class wizard_multi_charts_accounts(osv.osv_memory):
     """
@@ -2782,30 +2987,32 @@ class wizard_multi_charts_accounts(osv.osv_memory):
     _columns = {
         'company_id':fields.many2one('res.company', 'Company', required=True),
         'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True),
-        'bank_accounts_id': fields.one2many('account.bank.accounts.wizard', 'bank_account_id', 'Bank Accounts', required=True),
+        'bank_accounts_id': fields.one2many('account.bank.accounts.wizard', 'bank_account_id', 'Cash and Banks', required=True),
         'code_digits':fields.integer('# of Digits', required=True, help="No. of Digits to use for account code"),
         'seq_journal':fields.boolean('Separated Journal Sequences', help="Check this box if you want to use a different sequence for each created journal. Otherwise, all will use the same sequence."),
         "sale_tax": fields.many2one("account.tax.template", "Default Sales Tax"),
         "purchase_tax": fields.many2one("account.tax.template", "Default Purchase Tax"),
         'sale_tax_rate': fields.float('Sales Tax(%)'),
         'purchase_tax_rate': fields.float('Purchase Tax(%)'),
-        'complete_tax': fields.boolean('Complete Tax'),
+        'complete_tax_set': fields.boolean('Complete Set of Taxes', help='This boolean helps you to choose if you want to propose to the user to encode the sales and purchase rates or use the usual m2o fields. This last choice assumes that the set of tax defined for the chosen template is complete'),
     }
     def onchange_chart_template_id(self, cr, uid, ids, chart_template_id=False, context=None):
         res = {}
         tax_templ_obj = self.pool.get('account.tax.template')
-        res['value'] = {'complete_tax': False, 'sale_tax': False, 'purchase_tax': False, 'code_digits': 0}
+        res['value'] = {'complete_tax_set': False, 'sale_tax': False, 'purchase_tax': False}
         if chart_template_id:
             data = self.pool.get('account.chart.template').browse(cr, uid, chart_template_id, context=context)
-            complete_tax = data.set_tax_complete
-            if complete_tax:
-            # default tax is given by the lowesst sequence. For same sequence we will take the latest created as it will be the case for tax created while isntalling the generic chart of account
+            res['value'].update({'complete_tax_set': data.complete_tax_set})
+            if data.complete_tax_set:
+            # default tax is given by the lowest sequence. For same sequence we will take the latest created as it will be the case for tax created while isntalling the generic chart of account
                 sale_tax_ids = tax_templ_obj.search(cr, uid, [("chart_template_id"
                                               , "=", chart_template_id), ('type_tax_use', 'in', ('sale','all')), ('installable', '=', True)], order="sequence, id desc")
                 purchase_tax_ids = tax_templ_obj.search(cr, uid, [("chart_template_id"
                                               , "=", chart_template_id), ('type_tax_use', 'in', ('purchase','all')), ('installable', '=', True)], order="sequence, id desc")
                 res['value'].update({'sale_tax': sale_tax_ids and sale_tax_ids[0] or False, 'purchase_tax': purchase_tax_ids and purchase_tax_ids[0] or False})
-            res['value'].update({'complete_tax': complete_tax, 'code_digits': data.code_digits})
+
+            if data.code_digits:
+               res['value'].update({'code_digits': data.code_digits})
         return res
 
 
@@ -2834,7 +3041,6 @@ class wizard_multi_charts_accounts(osv.osv_memory):
                 purchase_tax_ids = tax_templ_obj.search(cr, uid, [("chart_template_id"
                                           , "=", ids[0]), ('type_tax_use', 'in', ('purchase','all')), ('installable', '=', True)], order="sequence")
                 res.update({'purchase_tax': purchase_tax_ids and purchase_tax_ids[0] or False})
-
         return res
 
     def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
@@ -2842,7 +3048,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         cmp_select = []
         acc_template_obj = self.pool.get('account.chart.template')
         company_obj = self.pool.get('res.company')
-        
+
         template_ids = acc_template_obj.search(cr, uid, [('visible', '=', True)], context=context)
         company_ids = company_obj.search(cr, uid, [], context=context)
         #display in the widget selection of companies, only the companies that haven't been configured yet (but don't care about the demo chart of accounts)
@@ -2851,7 +3057,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         unconfigured_cmp = list(set(company_ids)-set(configured_cmp))
         for field in res['fields']:
             if field == 'company_id':
-                res['fields'][field]['domain'] = unconfigured_cmp
+                res['fields'][field]['domain'] = [('id','in',unconfigured_cmp)]
                 res['fields'][field]['selection'] = [('', '')]
                 if unconfigured_cmp:
                     cmp_select = [(line.id, line.name) for line in company_obj.browse(cr, uid, unconfigured_cmp)]
@@ -2863,7 +3069,17 @@ class wizard_multi_charts_accounts(osv.osv_memory):
                     res['fields'][field]['selection'] = template_select
         return res
 
-    def generate_journals(self, cr, uid, chart_template_id, acc_template_ref, company_id, bank_jrnl_acc_list, code_digits, context=None):
+    def check_created_journals(self, cr, uid, vals_journal, company_id, context=None):
+        """
+        This method used for checking journals already created or not. If not then create new journal.
+        """
+        obj_journal = self.pool.get('account.journal')
+        rec_list = obj_journal.search(cr, uid, [('name','=', vals_journal['name']),('company_id', '=', company_id)], context=context)
+        if not rec_list:
+            obj_journal.create(cr, uid, vals_journal, context=context)
+        return True
+
+    def generate_journals(self, cr, uid, chart_template_id, acc_template_ref, company_id, context=None):
         """
         This method used for creating journals.
         @param cr: A database cursor.
@@ -2872,194 +3088,93 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         @param acc_template_ref: Account templates reference.
         @param company_id: company_id selected from wizard.multi.charts.accounts.
         """
-        
-        obj_data = self.pool.get('ir.model.data')
-        analytic_journal_obj = self.pool.get('account.analytic.journal')
-        obj_journal = self.pool.get('account.journal')
-        obj_acc = self.pool.get('account.account')
-        template = self.pool.get('account.chart.template').browse(cr, uid, chart_template_id, context=context)
-
-        data = obj_data.get_object_reference(cr, uid, 'account', 'account_sp_journal_view') 
-        view_id = data and data[1] or False
-
-        income_acc_id = acc_template_ref.get(template.property_account_income_categ.id)
-        expense_acc_id = acc_template_ref.get(template.property_account_expense_categ.id)
-        credit_acc_id = acc_template_ref.get(template.property_account_income_opening.id)
-        debit_acc_id = acc_template_ref.get(template.property_account_expense_opening.id)
-        ref_acc_bank = template.bank_account_view_id
-                
-        #Sales Journal
-        analytical_sale_ids = analytic_journal_obj.search(cr, uid, [('type','=','sale')], context=context)
-        analytical_journal_sale = analytical_sale_ids and analytical_sale_ids[0] or False
-
-        file_no = str(random.randint(1,9))
-        vals_journal = {
-            'name': _('Sales Journal-%s') %(file_no),
-            'type': 'sale',
-            'code': _('SAJ%s') %(file_no),
-            'view_id': view_id,
-            'company_id': company_id,
-            'analytic_journal_id': analytical_journal_sale,
-        }
-
-        if template.property_account_receivable:
-            vals_journal.update({
-                            'default_credit_account_id': income_acc_id,
-                            'default_debit_account_id': income_acc_id
-                               })
-        obj_journal.create(cr, uid, vals_journal, context=context)
-
-        # Purchase Journal
-        analytical_purchase_ids = analytic_journal_obj.search(cr,uid,[('type','=','purchase')], context=context)
-        analytical_journal_purchase = analytical_purchase_ids and analytical_purchase_ids[0] or False
-
-        vals_journal = {
-            'name': _('Purchase Journal-%s') %(file_no),
-            'type': 'purchase',
-            'code': _('EXJ%s') %(file_no),
-            'view_id': view_id,
-            'company_id': company_id,
-            'analytic_journal_id': analytical_journal_purchase,
-        }
+        journal_data = self._prepare_all_journals(cr, uid, chart_template_id, acc_template_ref, company_id, context=context)
+        for vals_journal in journal_data:
+            self.check_created_journals(cr, uid, vals_journal, company_id, context=context)
+        return True
 
-        if template.property_account_payable:
-            vals_journal.update({
-                            'default_credit_account_id': expense_acc_id,
-                            'default_debit_account_id': expense_acc_id
-                               })
-        obj_journal.create(cr, uid, vals_journal, context=context)
-
-        # Creating Journals Sales Refund and Purchase Refund
-        data = obj_data.get_object_reference(cr, uid, 'account', 'account_sp_refund_journal_view') 
-        view_id = data and data[1] or False
-
-        #Sales Refund Journal
-        vals_journal = {
-            'name': _('Sales Refund Journal-%s') %(file_no),
-            'type': 'sale_refund',
-            'code': _('SCNJ%s') %(file_no),
-            'view_id': view_id,
-            'analytic_journal_id': analytical_journal_sale,
-            'company_id': company_id
-        }
-        if template.property_account_receivable:
-            vals_journal.update({
-                            'default_credit_account_id': income_acc_id,
-                            'default_debit_account_id': income_acc_id
-                               })
-        obj_journal.create(cr, uid, vals_journal, context=context)
-
-        # Purchase Refund Journal
-        vals_journal = {
-            'name': _('Purchase Refund Journal-%s') %(file_no),
-            'type': 'purchase_refund',
-            'code': _('ECNJ%s') %(file_no),
-            'view_id': view_id,
-            'analytic_journal_id': analytical_journal_purchase,
-            'company_id': company_id
+    def _prepare_all_journals(self, cr, uid, chart_template_id, acc_template_ref, company_id, context=None):
+        def _get_analytic_journal(journal_type):
+            # Get the analytic journal
+            analytic_journal_ids = []
+            if journal_type in ('sale', 'sale_refund'):
+                analytical_journal_ids = analytic_journal_obj.search(cr, uid, [('type','=','sale')], context=context)
+            elif journal_type in ('purchase', 'purchase_refund'):
+                analytical_journal_ids = analytic_journal_obj.search(cr, uid, [('type','=','purchase')], context=context)
+            elif journal_type == 'general':
+                analytical_journal_ids = analytic_journal_obj.search(cr, uid, [('type', '=', 'situation')], context=context)
+            return analytic_journal_ids and analytic_journal_ids[0] or False
+
+        def _get_default_account(journal_type, type='debit'):
+            # Get the default accounts
+            default_account = False
+            if journal_type in ('sale', 'sale_refund'):
+                default_account = acc_template_ref.get(template.property_account_income_categ.id)
+            elif journal_type in ('purchase', 'purchase_refund'):
+                default_account = acc_template_ref.get(template.property_account_expense_categ.id)
+            elif journal_type == 'situation':
+                if type == 'debit':
+                    default_account = acc_template_ref.get(template.property_account_expense_opening.id)
+                else:
+                    default_account = acc_template_ref.get(template.property_account_income_opening.id)
+            return default_account
+
+        def _get_view_id(journal_type):
+            # Get the journal views
+            if journal_type in ('general', 'situation'):
+                data = obj_data.get_object_reference(cr, uid, 'account', 'account_journal_view')
+            elif journal_type in ('sale_refund', 'purchase_refund'):
+                data = obj_data.get_object_reference(cr, uid, 'account', 'account_sp_refund_journal_view') 
+            else:
+                data = obj_data.get_object_reference(cr, uid, 'account', 'account_sp_journal_view')
+            return data and data[1] or False
+
+        journal_names = {
+            'sale': _('Sales Journal'),
+            'purchase': _('Purchase Journal'),
+            'sale_refund': _('Sales Refund Journal'),
+            'purchase_refund': _('Purchase Refund Journal'),
+            'general': _('Miscellaneous Journal'),
+            'situation': _('Opening Entries Journal'),
         }
-        if template.property_account_payable:
-            vals_journal.update({
-                            'default_credit_account_id': expense_acc_id,
-                            'default_debit_account_id': expense_acc_id
-                               })
-        obj_journal.create(cr, uid, vals_journal, context=context)
-
-        # Miscellaneous Journal
-        data = obj_data.get_object_reference(cr, uid, 'account', 'account_journal_view') 
-        view_id = data and data[1] or False
-
-        analytical_miscellaneous_ids = analytic_journal_obj.search(cr, uid, [('type', '=', 'situation')], context=context)
-
-        vals_journal = {
-            'name': _('Miscellaneous Journal%s') %(file_no),
-            'type': 'general',
-            'code': _('MISC%s') %(file_no),
-            'view_id': view_id,
-            'analytic_journal_id': analytical_miscellaneous_ids and analytical_miscellaneous_ids[0] or False,
-            'company_id': company_id
+        journal_codes = {
+            'sale': _('SAJ'),
+            'purchase': _('EXJ'),
+            'sale_refund': _('SCNJ'),
+            'purchase_refund': _('ECNJ'),
+            'general': _('MISC'),
+            'situation': _('OPEJ'),
         }
-        obj_journal.create(cr, uid, vals_journal, context=context)
-
-        # Opening Entries Journal
-        if template.property_account_income_opening and template.property_account_expense_opening:
-            vals_journal = {
-                'name': _('Opening Entries Journal%s') %(file_no),
-                'type': 'situation',
-                'code': _('OPEJ%s') %(file_no),
-                'view_id': view_id,
-                'company_id': company_id,
-                'centralisation': True,
-                'default_credit_account_id': credit_acc_id,
-                'default_debit_account_id': debit_acc_id
-                }
-            obj_journal.create(cr, uid, vals_journal, context=context)
 
-        data = obj_data.get_object_reference(cr, uid, 'account', 'account_journal_bank_view_multi') 
-        view_id_cur = data and data[1] or False
-
-        data = obj_data.get_object_reference(cr, uid, 'account', 'account_journal_bank_view') 
-        view_id_cash = data and data[1] or False
+        obj_data = self.pool.get('ir.model.data')
+        analytic_journal_obj = self.pool.get('account.analytic.journal')
+        template = self.pool.get('account.chart.template').browse(cr, uid, chart_template_id, context=context)
 
-        #Create Bank journals
-        current_num = 1
-        valid = True
-        for line in bank_jrnl_acc_list:
-            #create the account_account for this bank journal
-            if not ref_acc_bank.code:
-                raise osv.except_osv(_('Configuration Error !'), _('The bank account defined on the selected chart of account hasn\'t a code.'))
-            while True:
-                new_code = str(ref_acc_bank.code.ljust(code_digits-len(str(current_num)), '0')) + str(current_num)
-                ids = obj_acc.search(cr, uid, [('code', '=', new_code), ('company_id', '=', company_id)])
-                if not ids:
-                    break
-                else:
-                    current_num += 1
-            user_type = self.pool.get('account.account.type').search(cr, uid, [('name', '=', line['account_type'])], context=context)
+        journal_data = []
+        for journal_type in ['sale', 'purchase', 'sale_refund', 'purchase_refund', 'general', 'situation']:
             vals = {
-                'name': line['acc_name'],
-                'currency_id': line['currency_id'],
-                'code': new_code,
-                'type': 'liquidity',
-                'user_type': 1,
-                'reconcile': True,
-                'parent_id': acc_template_ref[ref_acc_bank.id] or False,
-                'company_id': company_id,
-            }
-            acc_cash_id  = obj_acc.create(cr,uid,vals)
-
-            #create the bank journal
-            vals_journal = {
-                'name': vals['name'],
-                'code': _('BNK') + str(current_num),
-                'type': line['account_type'] == 'cash' and 'cash' or 'bank',
+                'type': journal_type,
+                'name': journal_names[journal_type],
+                'code': journal_codes[journal_type],
                 'company_id': company_id,
-                'analytic_journal_id': False,
-                'currency_id': False,
+                'centralisation': journal_type == 'situation',
+                'view_id': _get_view_id(journal_type),
+                'analytic_journal_id': _get_analytic_journal(journal_type),
+                'default_credit_account_id': _get_default_account(journal_type, 'credit'),
+                'default_debit_account_id': _get_default_account(journal_type, 'debit'),
             }
-            if line['currency_id']:
-                vals_journal['view_id'] = view_id_cur
-                vals_journal['currency'] = line['currency_id']
-            else:
-                vals_journal['view_id'] = view_id_cash
-            vals_journal['default_credit_account_id'] = acc_cash_id
-            vals_journal['default_debit_account_id'] = acc_cash_id
-            obj_journal.create(cr, uid, vals_journal)
-            current_num += 1
-            valid = True
-            
-        return True
+            journal_data.append(vals)
+        return journal_data
 
     def generate_properties(self, cr, uid, chart_template_id, acc_template_ref, company_id, context=None):
         """
         This method used for creating properties.
-        @param cr: A database cursor.
-        @param uid: ID of the user currently logged in.
-        @param chart_temp_id: Chart Template Id.
-        @param acc_template_ref: Account templates reference.
-        @param company_id: company_id selected from wizard.multi.charts.accounts.
+
+        :param chart_template_id: id of the current chart template for which we need to create properties
+        :param acc_template_ref: Mapping between ids of account templates and real accounts created from them
+        :param company_id: company_id selected from wizard.multi.charts.accounts.
+        :returns: True
         """
-        
         property_obj = self.pool.get('ir.property')
         field_obj = self.pool.get('ir.model.fields')
         todo_list = [
@@ -3071,147 +3186,308 @@ class wizard_multi_charts_accounts(osv.osv_memory):
             ('property_account_income','product.template','account.account'),
             ('property_reserve_and_surplus_account','res.company','account.account')
         ]
-        template_id = self.pool.get('account.chart.template').browse(cr, uid, chart_template_id, context=context)
+        template = self.pool.get('account.chart.template').browse(cr, uid, chart_template_id, context=context)
         for record in todo_list:
-            rec_list = []
-            rec_list = property_obj.search(cr, uid, [('name','=', record[0]),('company_id', '=', company_id)], context=context)
-            account = getattr(template_id, record[0])
-            field = field_obj.search(cr, uid, [('name', '=', record[0]),('model', '=', record[1]),('relation', '=', record[2])], context=context)
-            vals = {
-                'name': record[0],
-                'company_id': company_id,
-                'fields_id': field[0],
-                'value': account and 'account.account,' + str(acc_template_ref[account.id]) or False,
-            }
-
-            if rec_list:
-                #the property exist: modify it
-                property_obj.write(cr, uid, rec_list, vals, context=context)
-            else:
-                #create the property
-                property_obj.create(cr, uid, vals, context=context)
-        
+            account = getattr(template, record[0])
+            value = account and 'account.account,' + str(acc_template_ref[account.id]) or False
+            if value:
+                field = field_obj.search(cr, uid, [('name', '=', record[0]),('model', '=', record[1]),('relation', '=', record[2])], context=context)
+                vals = {
+                    'name': record[0],
+                    'company_id': company_id,
+                    'fields_id': field[0],
+                    'value': value,
+                }
+                property_ids = property_obj.search(cr, uid, [('name','=', record[0]),('company_id', '=', company_id)], context=context)
+                if property_ids:
+                    #the property exist: modify it
+                    property_obj.write(cr, uid, property_ids, vals, context=context)
+                else:
+                    #create the property
+                    property_obj.create(cr, uid, vals, context=context)
         return True
 
-    def _install_template(self, cr, uid, template_id, company_id, code_digits=None ,tax_data={}, bank_jrnl_acc_list=[], context=None):
+    def _install_template(self, cr, uid, template_id, company_id, code_digits=None, obj_wizard=None, acc_ref={}, taxes_ref={}, tax_code_ref={}, context=None):
+        '''
+        This function recursively loads the template objects and create the real objects from them.
+
+        :param template_id: id of the chart template to load
+        :param company_id: id of the company the wizard is running for
+        :param code_digits: integer that depicts the number of digits the accounts code should have in the COA
+        :param obj_wizard: the current wizard for generating the COA from the templates
+        :returns: return a tuple with a dictionary containing
+            * the mapping between the account template ids and the ids of the real accounts that have been generated
+              from them, as first item,
+            * a similar dictionary for mapping the tax templates and taxes, as second item,
+            * a last identical containing the mapping of tax code templates and tax codes
+        :rtype: tuple(dict, dict, dict)
+        '''
         template = self.pool.get('account.chart.template').browse(cr, uid, template_id, context=context)
         if template.parent_id:
-            self._install_template(cr, uid, template.parent_id.id, company_id, code_digits=code_digits, context=context)
-        return self._load_template(cr, uid, template_id, company_id, code_digits=code_digits, tax_data=tax_data, bank_jrnl_acc_list=bank_jrnl_acc_list,context=context)
-
-    def _load_template(self, cr, uid, template_id, company_id, code_digits=None, tax_data={}, bank_jrnl_acc_list=[], context=None):
+            tmp1, tmp2, tmp3 = self._install_template(cr, uid, template.parent_id.id, company_id, code_digits=code_digits, acc_ref=acc_ref, taxes_ref=taxes_ref, tax_code_ref=tax_code_ref, context=context)
+            acc_ref.update(tmp1)
+            taxes_ref.update(tmp2)
+            tax_code_ref.update(tmp3)
+        tmp1, tmp2, tmp3 = self._load_template(cr, uid, template_id, company_id, code_digits=code_digits, obj_wizard=obj_wizard, account_ref=acc_ref, taxes_ref=taxes_ref, tax_code_ref=tax_code_ref, context=context)
+        acc_ref.update(tmp1)
+        taxes_ref.update(tmp2)
+        tax_code_ref.update(tmp3)
+        return acc_ref, taxes_ref, tax_code_ref
+
+    def _load_template(self, cr, uid, template_id, company_id, code_digits=None, obj_wizard=None, account_ref={}, taxes_ref={}, tax_code_ref={}, context=None):
+        '''
+        This function generates all the objects from the templates
+
+        :param template_id: id of the chart template to load
+        :param company_id: id of the company the wizard is running for
+        :param code_digits: integer that depicts the number of digits the accounts code should have in the COA
+        :param obj_wizard: the current wizard for generating the COA from the templates
+        :returns: return a tuple with a dictionary containing
+            * the mapping between the account template ids and the ids of the real accounts that have been generated
+              from them, as first item,
+            * a similar dictionary for mapping the tax templates and taxes, as second item,
+            * a last identical containing the mapping of tax code templates and tax codes
+        :rtype: tuple(dict, dict, dict)
+        '''
         template = self.pool.get('account.chart.template').browse(cr, uid, template_id, context=context)
         obj_tax_code_template = self.pool.get('account.tax.code.template')
         obj_acc_tax = self.pool.get('account.tax')
-        obj_tax_code = self.pool.get('account.tax.code')
         obj_tax_temp = self.pool.get('account.tax.template')
         obj_acc_template = self.pool.get('account.account.template')
         obj_fiscal_position_template = self.pool.get('account.fiscal.position.template')
-        ir_values_obj = self.pool.get('ir.values')
-
-        # create tax templates and real taxes from purchase_tax_rate,sale_tax_rate fields
-        if not template.set_tax_complete and tax_data:
-            tax_dict = {'sale': tax_data['sale'], 'purchase': tax_data['purchase']}
-            for tax_type, value in tax_dict.items():
-                tax_name = tax_type == 'sale' and 'TAX Received' or 'TAX Paid'
-                if value > 0.0:
-                    tax_string = _('TAX %s%%') % (value)
-                    new_tax_code_temp = obj_tax_code_template.create(cr, uid, {'name': tax_string, 'code': tax_string}, context=context)
-                    new_paid_tax_code_temp = obj_tax_code_template.create(cr, uid, {'name': _('%s %s%%') % (tax_name, value), 'code': _('%s %s%%') % (tax_name, value)}, context=context)
-                    sales_tax_temp = obj_tax_temp.create(cr, uid, {
-                                            'name': tax_string,
-                                            'description': tax_string,
-                                            'amount': value/100,
-                                            'base_code_id': new_tax_code_temp,
-                                            'tax_code_id': new_paid_tax_code_temp,
-                                            'ref_base_code_id': new_tax_code_temp,
-                                            'ref_tax_code_id': new_paid_tax_code_temp,
-                                            'type_tax_use': tax_type,
-                                            'installable': True,
-                                            'type': 'percent',
-                                            'sequence': 0,
-                                            'chart_template_id': template_id or False,
-                                }, context=context)
 
-
-        # create all the tax code [TOCHECK: finds children of tax_code_root_id and processes]
-        tax_code_template_ref = {}
-        tax_code_root_id = template.tax_code_root_id.id
-        children_tax_code_template = obj_tax_code_template.search(cr, uid, [('parent_id','child_of',[tax_code_root_id])], order='id')
-        company_name = self.pool.get('res.company').browse(cr, uid, company_id, context=context)
-        for tax_code_template in obj_tax_code_template.browse(cr, uid, children_tax_code_template, context=context):
-            vals = {
-                'name': (tax_code_root_id == tax_code_template.id) and company_name or tax_code_template.name,
-                'code': tax_code_template.code,
-                'info': tax_code_template.info,
-                'parent_id': tax_code_template.parent_id and ((tax_code_template.parent_id.id in tax_code_template_ref) and tax_code_template_ref[tax_code_template.parent_id.id]) or False,
-                'company_id': company_id,
-                'sign': tax_code_template.sign,
-            }
-            new_tax_code = obj_tax_code.create(cr, uid, vals)
-            #recording the new tax code to do the mapping
-            tax_code_template_ref[tax_code_template.id] = new_tax_code
+        # create all the tax code.
+        tax_code_ref.update(obj_tax_code_template.generate_tax_code(cr, uid, template.tax_code_root_id.id, company_id, context=context))
 
         # Generate taxes from templates.
-        tax_template_to_tax = {}
         tax_templates = [x for x in template.tax_template_ids if x.installable]
-        taxes_ref = obj_tax_temp.generate_tax(cr, uid, tax_templates, tax_code_template_ref, company_id, context=context)
+        generated_tax_res = obj_tax_temp._generate_tax(cr, uid, tax_templates, tax_code_ref, company_id, context=context)
+        taxes_ref.update(generated_tax_res['tax_template_to_tax'])
 
         # Generating Accounts from templates.
-        acc_template_ref = obj_acc_template.generate_account(cr, uid, template_id, template.account_root_id.id, taxes_ref['tax_template_ref'], code_digits, company_id, context=context)
+        account_template_ref = obj_acc_template.generate_account(cr, uid, template_id, taxes_ref, account_ref, code_digits, company_id, context=context)
+        account_ref.update(account_template_ref)
 
         # writing account values on tax after creation of accounts
-        for key,value in taxes_ref['account_dict'].items():
+        for key,value in generated_tax_res['account_dict'].items():
             if value['account_collected_id'] or value['account_paid_id']:
                 obj_acc_tax.write(cr, uid, [key], {
-                    'account_collected_id': acc_template_ref.get(value['account_collected_id'], False),
-                    'account_paid_id': acc_template_ref.get(value['account_paid_id'], False),
+                    'account_collected_id': account_ref.get(value['account_collected_id'], False),
+                    'account_paid_id': account_ref.get(value['account_paid_id'], False),
                 })
-        
-        # Create Jourals
-        #TODO: pass template_id
-        self.generate_journals(cr, uid, template, acc_template_ref, company_id, context)
 
-        # Create Bank Journals (Can be done in the generate_journals function)
-        #TODO: Create a new function
+        # Create Journals
+        self.generate_journals(cr, uid, template_id, account_ref, company_id, context=context)
 
         # generate properties function
-        self.generate_properties(cr, uid, template_id, acc_template_ref, company_id, context=context)
+        self.generate_properties(cr, uid, template_id, account_ref, company_id, context=context)
 
         # Generate Fiscal Position , Fiscal Position Accounts and Fiscal Position Taxes from templates
-        obj_fiscal_position_template.generate_fiscal_position(cr, uid, template_id, taxes_ref['tax_template_ref'], acc_template_ref, company_id, context=context)
+        obj_fiscal_position_template.generate_fiscal_position(cr, uid, template_id, taxes_ref, account_ref, company_id, context=context)
+
+        return account_ref, taxes_ref, tax_code_ref
+
+    def _create_tax_templates_from_rates(self, cr, uid, obj_wizard, company_id, context=None):
+        '''
+        This function checks if the chosen chart template is configured as containing a full set of taxes, and if
+        it's not the case, it creates the templates for account.tax.code and for account.account.tax objects accordingly
+        to the provided sale/purchase rates.
+
+        :param obj_wizard: browse record of wizard to generate COA from templates
+        :param company_id: id of the company for wich the wizard is running
+        :return: True
+        '''
+        obj_tax_code_template = self.pool.get('account.tax.code.template')
+        obj_tax_temp = self.pool.get('account.tax.template')
+        chart_template = obj_wizard.chart_template_id
+        vals = {}
+        # create tax templates and tax code templates from purchase_tax_rate and sale_tax_rate fields
+        if not chart_template.complete_tax_set:
+            tax_data = {
+                'sale': obj_wizard.sale_tax_rate,
+                'purchase': obj_wizard.purchase_tax_rate,
+            }
+
+            for tax_type, value in tax_data.items():
+                # don't consider cases where entered value in rates are lower than 0
+                if value >= 0.0:
+                    #create the tax code templates for base and tax
+                    base_code_vals = {
+                        'name': (tax_type == 'sale' and _('Taxable Sales at %s') or _('Taxable Purchases at %s')) % value,
+                        'code': (tax_type == 'sale' and _('BASE-S-%s') or _('BASE-P-%s')) %value,
+                        'parent_id': chart_template.tax_code_root_id.id,
+                        'company_id': company_id,
+                    }
+                    new_base_code_id = obj_tax_code_template.create(cr, uid, base_code_vals, context=context)
+                    tax_code_vals = {
+                        'name': (tax_type == 'sale' and _('Tax Received at %s') or _('Tax Paid at %s')) % value,
+                        'code': (tax_type == 'sale' and _('TAX-S-%s') or _('TAX-P-%s')) %value,
+                        'parent_id': chart_template.tax_code_root_id.id,
+                        'company_id': company_id,
+                    }
+                    new_tax_code_id = obj_tax_code_template.create(cr, uid, tax_code_vals, context=context)
+                    #create the tax
+                    tax_template_id = obj_tax_temp.create(cr, uid, {
+                                            'name': _('Tax %s%%') % value,
+                                            'amount': value/100,
+                                            'base_code_id': new_base_code_id,
+                                            'tax_code_id': new_tax_code_id,
+                                            'ref_base_code_id': new_base_code_id,
+                                            'ref_tax_code_id': new_tax_code_id,
+                                            'type_tax_use': tax_type,
+                                            'installable': True,
+                                            'type': 'percent',
+                                            'sequence': 0,
+                                            'chart_template_id': chart_template.id or False,
+                    }, context=context)
+                    #record this new tax_template as default for this chart template
+                    field_name = tax_type == 'sale' and 'sale_tax' or 'purchase_tax'
+                    vals[field_name] = tax_template_id
+        self.write(cr, uid, obj_wizard.id, vals, context=context)
+        return True
+
+    def execute(self, cr, uid, ids, context=None):
+        '''
+        This function is called at the confirmation of the wizard to generate the COA from the templates. It will read
+        all the provided information to create the accounts, the banks, the journals, the taxes, the tax codes, the
+        accounting properties... accordingly for the chosen company.
+        '''
+        ir_values_obj = self.pool.get('ir.values')
+        obj_wizard = self.browse(cr, uid, ids[0])
+        company_id = obj_wizard.company_id.id
+        # If the floats for sale/purchase rates have been filled, create templates from them
+        self._create_tax_templates_from_rates(cr, uid, obj_wizard, company_id, context=context)
+
+        # Install all the templates objects and generate the real objects
+        acc_template_ref, taxes_ref, tax_code_ref = self._install_template(cr, uid, obj_wizard.chart_template_id.id, company_id, code_digits=obj_wizard.code_digits, obj_wizard=obj_wizard, context=context)
 
         # write values of default taxes for product
-        if tax_data:
-            if tax_data['sale_tax'] and taxes_ref['taxes_id']:
-                ir_values_obj.set(cr, uid, key='default', key2=False, name="taxes_id", company=company_id,
-                                models =[('product.product',False)], value=[taxes_ref['taxes_id'][tax_data['sale_tax']]])
-            if tax_data['purchase_tax'] and taxes_ref['taxes_id']:
+        if obj_wizard.sale_tax and taxes_ref:
+            ir_values_obj.set(cr, uid, key='default', key2=False, name="taxes_id", company=company_id,
+                                models =[('product.product',False)], value=[taxes_ref[obj_wizard.sale_tax.id]])
+        if obj_wizard.purchase_tax and taxes_ref:
                 ir_values_obj.set(cr, uid, key='default', key2=False, name="supplier_taxes_id", company=company_id,
-                                models =[('product.product',False)], value=[taxes_ref['taxes_id'][tax_data['purchase_tax']]])
+                                models =[('product.product',False)], value=[taxes_ref[obj_wizard.purchase_tax.id]])
+
+        # Create Bank journals
+        self._create_bank_journals_from_o2m(cr, uid, obj_wizard, company_id, acc_template_ref, context=context)
         return True
 
-    def execute(self, cr, uid, ids, context=None):
-        obj_tax_temp = self.pool.get('account.tax.template')
-        obj_multi = self.browse(cr, uid, ids[0])
-        company_id = obj_multi.company_id.id
-        bank_jrnl_acc_list = []
-        tax_data = {
-                    'sale': obj_multi.sale_tax_rate, 
-                    'purchase': obj_multi.purchase_tax_rate, 
-                    'sale_tax': obj_multi.complete_tax and obj_multi.sale_tax.id or False, 
-                    'purchase_tax': obj_multi.complete_tax and obj_multi.purchase_tax.id or False, 
-                     }
-        if obj_multi.bank_accounts_id:
-            for acc in obj_multi.bank_accounts_id:
-                bank_jrnl_acc_list.append({
-                            'acc_name': acc.acc_name,
-                            'account_type': acc.account_type,
-                            'currency_id': acc.currency_id.id,
-                            })
-        self._install_template(cr, uid, obj_multi.chart_template_id.id, company_id, code_digits=obj_multi.code_digits, tax_data=tax_data, bank_jrnl_acc_list = bank_jrnl_acc_list, context=context)
+    def _prepare_bank_journal(self, cr, uid, line, current_num, default_account_id, company_id, context=None):
+        '''
+        This function prepares the value to use for the creation of a bank journal created through the wizard of 
+        generating COA from templates.
+
+        :param line: dictionary containing the values encoded by the user related to his bank account
+        :param current_num: integer corresponding to a counter of the already created bank journals through this wizard.
+        :param default_account_id: id of the default debit.credit account created before for this journal.
+        :param company_id: id of the company for which the wizard is running
+        :return: mapping of field names and values
+        :rtype: dict
+        '''
+        obj_data = self.pool.get('ir.model.data')
+        # Get the id of journal views
+        tmp = obj_data.get_object_reference(cr, uid, 'account', 'account_journal_bank_view_multi')
+        view_id_cur = tmp and tmp[1] or False
+        tmp = obj_data.get_object_reference(cr, uid, 'account', 'account_journal_bank_view')
+        view_id_cash = tmp and tmp[1] or False
+        vals = {
+                'name': line['acc_name'],
+                'code': _('BNK') + str(current_num),
+                'type': line['account_type'] == 'cash' and 'cash' or 'bank',
+                'company_id': company_id,
+                'analytic_journal_id': False,
+                'currency': False,
+                'default_credit_account_id': default_account_id,
+                'default_debit_account_id': default_account_id,
+        }
+        if line['currency_id']:
+            vals['view_id'] = view_id_cur
+            vals['currency'] = line['currency_id']
+        else:
+            vals['view_id'] = view_id_cash
+        return vals
+
+    def _prepare_bank_account(self, cr, uid, line, new_code, acc_template_ref, ref_acc_bank, company_id, context=None):
+        '''
+        This function prepares the value to use for the creation of the default debit and credit accounts of a
+        bank journal created through the wizard of generating COA from templates.
+
+        :param line: dictionary containing the values encoded by the user related to his bank account
+        :param new_code: integer corresponding to the next available number to use as account code
+        :param acc_template_ref: the dictionary containing the mapping between the ids of account templates and the ids
+            of the accounts that have been generated from them.
+        :param ref_acc_bank: browse record of the account template set as root of all bank accounts for the chosen
+            template
+        :param company_id: id of the company for which the wizard is running
+        :return: mapping of field names and values
+        :rtype: dict
+        '''
+        obj_data = self.pool.get('ir.model.data')
 
-        return {}
+        # Get the id of the user types fr-or cash and bank
+        tmp = obj_data.get_object_reference(cr, uid, 'account', 'data_account_type_cash')
+        cash_type = tmp and tmp[1] or False
+        tmp = obj_data.get_object_reference(cr, uid, 'account', 'data_account_type_bank')
+        bank_type = tmp and tmp[1] or False
+        return {
+                'name': line['acc_name'],
+                'currency_id': line['currency_id'],
+                'code': new_code,
+                'type': 'liquidity',
+                'user_type': line['account_type'] == 'cash' and cash_type or bank_type,
+                'parent_id': acc_template_ref[ref_acc_bank.id] or False,
+                'company_id': company_id,
+        }
+
+    def _create_bank_journals_from_o2m(self, cr, uid, obj_wizard, company_id, acc_template_ref, context=None):
+        '''
+        This function creates bank journals and its accounts for each line encoded in the field bank_accounts_id of the
+        wizard.
+
+        :param obj_wizard: the current wizard that generates the COA from the templates.
+        :param company_id: the id of the company for which the wizard is running.
+        :param acc_template_ref: the dictionary containing the mapping between the ids of account templates and the ids
+            of the accounts that have been generated from them.
+        :return: True
+        '''
+        obj_acc = self.pool.get('account.account')
+        obj_journal = self.pool.get('account.journal')
+        code_digits = obj_wizard.code_digits
+
+        # Build a list with all the data to process
+        journal_data = []
+        if obj_wizard.bank_accounts_id:
+            for acc in obj_wizard.bank_accounts_id:
+                vals = {
+                    'acc_name': acc.acc_name,
+                    'account_type': acc.account_type,
+                    'currency_id': acc.currency_id.id,
+                }
+                journal_data.append(vals)
+        ref_acc_bank = obj_wizard.chart_template_id.bank_account_view_id
+        if journal_data and not ref_acc_bank.code:
+            raise osv.except_osv(_('Configuration Error !'), _('The bank account defined on the selected chart of accounts hasn\'t a code.'))
+
+        current_num = 1
+        for line in journal_data:
+            # Seek the next available number for the account code
+            while True:
+                new_code = str(ref_acc_bank.code.ljust(code_digits-len(str(current_num)), '0')) + str(current_num)
+                ids = obj_acc.search(cr, uid, [('code', '=', new_code), ('company_id', '=', company_id)])
+                if not ids:
+                    break
+                else:
+                    current_num += 1
+            # Create the default debit/credit accounts for this bank journal
+            vals = self._prepare_bank_account(cr, uid, line, new_code, acc_template_ref, ref_acc_bank, company_id, context=context)
+            default_account_id  = obj_acc.create(cr, uid, vals, context=context)
+
+            #create the bank journal
+            vals_journal = self._prepare_bank_journal(cr, uid, line, current_num, default_account_id, company_id, context=context)
+            obj_journal.create(cr, uid, vals_journal)
+            current_num += 1
+        return True
 
 wizard_multi_charts_accounts()