[FIX] typo on statement name
[odoo/odoo.git] / addons / account / account.py
index 342c2ef..280d413 100644 (file)
@@ -130,8 +130,45 @@ account_payment_term_line()
 class account_account_type(osv.osv):
     _name = "account.account.type"
     _description = "Account Type"
+
+    def _get_current_report_type(self, cr, uid, ids, name, arg, context=None):
+        obj_data = self.pool.get('ir.model.data')
+        obj_financial_report = self.pool.get('account.financial.report') 
+        res = {}
+        financial_report_ref = {
+            'asset': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_assets0')[1], context=context),
+            'liability': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_liability0')[1], context=context),
+            'income': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_income0')[1], context=context),
+            'expense': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_expense0')[1], context=context),
+        }
+        for record in self.browse(cr, uid, ids, context=context):
+            res[record.id] = 'none'
+            for key, financial_report in financial_report_ref.items():
+                list_ids = [x.id for x in financial_report.account_type_ids]
+                if record.id in list_ids:
+                    res[record.id] = key
+        return res
+
+    def _save_report_type(self, cr, uid, account_type_id, field_name, field_value, arg, context=None):
+        obj_data = self.pool.get('ir.model.data')
+        obj_financial_report = self.pool.get('account.financial.report') 
+        #unlink if it exists somewhere in the financial reports related to BS or PL
+        financial_report_ref = {
+            'asset': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_assets0')[1], context=context),
+            'liability': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_liability0')[1], context=context),
+            'income': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_income0')[1], context=context),
+            'expense': obj_financial_report.browse(cr, uid, obj_data.get_object_reference(cr, uid, 'account','account_financial_report_expense0')[1], context=context),
+        }
+        for key, financial_report in financial_report_ref.items():
+            list_ids = [x.id for x in financial_report.account_type_ids]
+            if account_type_id in list_ids:
+                obj_financial_report.write(cr, uid, [financial_report.id], {'account_type_ids': [(3, account_type_id)]})
+        #write it in the good place
+        if field_value != 'none':
+            return obj_financial_report.write(cr, uid, [financial_report_ref[field_value].id], {'account_type_ids': [(4, account_type_id)]})
+
     _columns = {
-        'name': fields.char('Account Type', size=64, required=True),
+        'name': fields.char('Account Type', size=64, required=True, translate=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.
 
@@ -139,19 +176,16 @@ 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, '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 (Asset Accounts)'),
-            ('liability','Balance Sheet (Liability Accounts)')
-        ],'P&L / BS Category', select=True, readonly=False, help="This field is used to generate legal reports: profit and loss, balance sheet.", required=True),
+        'report_type': fields.function(_get_current_report_type, fnct_inv=_save_report_type, type='selection', string='P&L / BS Category', 
+            selection= [('none','/'),
+                        ('income', _('Profit & Loss (Income account)')),
+                        ('expense', _('Profit & Loss (Expense account)')),
+                        ('asset', _('Balance Sheet (Asset account)')),
+                        ('liability', _('Balance Sheet (Liability account)'))], help="This field is used to generate legal reports: profit and loss, balance sheet.", required=True),
         'note': fields.text('Description'),
     }
     _defaults = {
         'close_method': 'none',
-        'sign': 1,
         'report_type': 'none',
     }
     _order = "code"
@@ -422,6 +456,7 @@ class account_account(osv.osv):
         'user_type': fields.many2one('account.account.type', 'Account Type', required=True,
             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."),
+        'financial_report_ids': fields.many2many('account.financial.report', 'account_account_financial_report', 'account_id', 'report_line_id', 'Financial Reports'),
         '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'),
@@ -771,7 +806,9 @@ class account_journal(osv.osv):
 
     def create(self, cr, uid, vals, context=None):
         if not 'sequence_id' in vals or not vals['sequence_id']:
-            vals.update({'sequence_id': self.create_sequence(cr, uid, vals, context)})
+            # if we have the right to create a journal, we should be able to
+            # create it's sequence.
+            vals.update({'sequence_id': self.create_sequence(cr, 1, vals, context)})
         return super(account_journal, self).create(cr, uid, vals, context)
 
     def name_get(self, cr, user, ids, context=None):
@@ -2422,6 +2459,7 @@ class account_account_template(osv.osv):
         '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."),
+        'financial_report_ids': fields.many2many('account.financial.report', 'account_template_financial_report', 'account_template_id', 'report_line_id', 'Financial Reports'),
         'reconcile': fields.boolean('Allow Reconciliation', help="Check this option if you want the user to reconcile entries in this account."),
         'shortcut': fields.char('Shortcut', size=12),
         'note': fields.text('Note'),
@@ -2429,7 +2467,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'),
+        'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', help="This optional field allow you to link an account template to a specific chart template that may differ from the one its root parent belongs to. This allow you to define chart templates that extend another and complete it with few new accounts (You don't need to define the whole structure that is common to both several times)."),
     }
 
     _defaults = {
@@ -2466,26 +2504,27 @@ class account_account_template(osv.osv):
             res.append((record['id'],name ))
         return res
 
-    def generate_account(self, cr, uid, template_id, tax_template_ref, acc_template_ref, code_digits, company_id, context=None):
+    def generate_account(self, cr, uid, chart_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.
-        @param uid: ID of the user currently logged in.
-        @param account_root_id: Root account id getting from current template.
-        @param tax_template_ref: Taxes templates reference for write taxes_id in account_account.
-        @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.
+
+        :param chart_template_id: id of the chart template chosen in the wizard
+        :param tax_template_ref: Taxes templates reference for write taxes_id in account_account.
+        :paramacc_template_ref: dictionary with the mappping between the account templates and the real accounts.
+        :param code_digits: number of digits got from wizard.multi.charts.accounts, this is use for account code.
+        :param company_id: company_id selected from wizard.multi.charts.accounts.
+        :returns: return acc_template_ref for reference purpose.
+        :rtype: dict
         """
         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
-        template = self.pool.get('account.chart.template').browse(cr, uid, template_id, context=context)
+        template = self.pool.get('account.chart.template').browse(cr, uid, chart_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, ['|', ('chart_template_id','=', [template_id]),'&',('parent_id','child_of', [template.account_root_id.id]),('chart_template_id','=', False), ('nocreate','!=',True)], order='id')
+        children_acc_template = self.search(cr, uid, ['|', ('chart_template_id','=', [chart_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:
@@ -2507,6 +2546,7 @@ class account_account_template(osv.osv):
                 'reconcile': account_template.reconcile,
                 'shortcut': account_template.shortcut,
                 'note': account_template.note,
+                'financial_report_ids': account_template.financial_report_ids and [(6,0,[x.id for x in account_template.financial_report_ids])] or False,
                 'parent_id': account_template.parent_id and ((account_template.parent_id.id in acc_template_ref) and acc_template_ref[account_template.parent_id.id]) or False,
                 'tax_ids': [(6,0,tax_ids)],
                 'company_id': company_id,
@@ -2719,7 +2759,6 @@ class account_tax_template(osv.osv):
         'description': fields.char('Internal Name', size=32),
         'type_tax_use': fields.selection([('sale','Sale'),('purchase','Purchase'),('all','All')], 'Tax Use In', required=True,),
         'price_include': fields.boolean('Tax Included in Price', help="Check this if the price you use on the product and invoices includes this tax."),
-        'installable': fields.boolean('Should be Installed', help="Set this to False if you do not want to create real tax object from this template.")
     }
 
     def name_get(self, cr, uid, ids, context=None):
@@ -2751,7 +2790,6 @@ class account_tax_template(osv.osv):
         'include_base_amount': False,
         'type_tax_use': 'all',
         'price_include': 0,
-        'installable': True
     }
     _order = 'sequence'
 
@@ -2828,13 +2866,13 @@ class account_fiscal_position_template(osv.osv):
 
     def generate_fiscal_position(self, cr, uid, chart_temp_id, tax_template_ref, acc_template_ref, company_id, context=None):
         """
-        This method generate Fiscal Position , Fiscal Position Accounts and Fiscal Position Taxes from templates.
-        @param cr: A database cursor.
-        @param uid: ID of the user currently logged in.
-        @param chart_temp_id: Chart Template Id.
-        @param taxes_ids: Taxes templates reference for generating account.fiscal.position.tax.
-        @param acc_template_ref: Account templates reference for generating account.fiscal.position.account.
-        @param company_id: company_id selected from wizard.multi.charts.accounts.
+        This method generate Fiscal Position, Fiscal Position Accounts and Fiscal Position Taxes from templates.
+
+        :param chart_temp_id: Chart Template Id.
+        :param taxes_ids: Taxes templates reference for generating account.fiscal.position.tax.
+        :param acc_template_ref: Account templates reference for generating account.fiscal.position.account.
+        :param company_id: company_id selected from wizard.multi.charts.accounts.
+        :returns: True
         """
         if context is None:
             context = {}
@@ -2856,7 +2894,7 @@ class account_fiscal_position_template(osv.osv):
                     'account_dest_id': acc_template_ref[acc.account_dest_id.id],
                     'position_id': new_fp
                 })
-        return {}
+        return True
 
 account_fiscal_position_template()
 
@@ -2911,6 +2949,7 @@ class account_financial_report(osv.osv):
         return res
 
     def _get_balance(self, cr, uid, ids, name, args, context=None):
+        account_obj = self.pool.get('account.account')
         res = {}
         res_all = {}
         for report in self.browse(cr, uid, ids, context=context):
@@ -2921,6 +2960,12 @@ class account_financial_report(osv.osv):
                 # it's the sum of balance of the linked accounts
                 for a in report.account_ids:
                     balance += a.balance
+            elif report.type == 'account_type':
+                # it's the sum of balance of the leaf accounts with such an account type
+                report_types = [x.id for x in report.account_type_ids]
+                account_ids = account_obj.search(cr, uid, [('user_type','in', report_types), ('type','!=','view')], context=context)
+                for a in account_obj.browse(cr, uid, account_ids, context=context):
+                    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)
@@ -2943,7 +2988,6 @@ class account_financial_report(osv.osv):
         '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([
@@ -2953,13 +2997,20 @@ class account_financial_report(osv.osv):
             ('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.'),
+        'display_detail': fields.selection([
+            ('no_detail','No detail'),
+            ('detail_flat','Display children flat'),
+            ('detail_with_hierarchy','Display children with hierarchy')
+            ], 'Display details'),
         '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'),
+        '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.'),
     }
 
     _defaults = {
         'type': 'sum',
+        'display_detail': 'detail_flat',
+        'sign': 1,
     }
 
 account_financial_report()
@@ -2990,7 +3041,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         '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"),
+        "sale_tax": fields.many2one("account.tax.template", "Default Sale 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(%)'),
@@ -3006,9 +3057,9 @@ class wizard_multi_charts_accounts(osv.osv_memory):
             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")
+                                              , "=", chart_template_id), ('type_tax_use', 'in', ('sale','all'))], 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")
+                                              , "=", chart_template_id), ('type_tax_use', 'in', ('purchase','all'))], 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})
 
             if data.code_digits:
@@ -3035,11 +3086,11 @@ class wizard_multi_charts_accounts(osv.osv_memory):
                 res.update({'chart_template_id': ids[0]})
             if 'sale_tax' in fields:
                 sale_tax_ids = tax_templ_obj.search(cr, uid, [("chart_template_id"
-                                              , "=", ids[0]), ('type_tax_use', 'in', ('sale','all')), ('installable', '=', True)], order="sequence")
+                                              , "=", ids[0]), ('type_tax_use', 'in', ('sale','all'))], order="sequence")
                 res.update({'sale_tax': sale_tax_ids and sale_tax_ids[0] or False})
             if 'purchase_tax' in fields:
                 purchase_tax_ids = tax_templ_obj.search(cr, uid, [("chart_template_id"
-                                          , "=", ids[0]), ('type_tax_use', 'in', ('purchase','all')), ('installable', '=', True)], order="sequence")
+                                          , "=", ids[0]), ('type_tax_use', 'in', ('purchase','all'))], order="sequence")
                 res.update({'purchase_tax': purchase_tax_ids and purchase_tax_ids[0] or False})
         return res
 
@@ -3049,7 +3100,6 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         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)
         cr.execute("SELECT company_id FROM account_account WHERE active = 't' AND account_account.parent_id IS NULL AND name != %s", ("Chart For Automated Tests",))
@@ -3062,11 +3112,6 @@ class wizard_multi_charts_accounts(osv.osv_memory):
                 if unconfigured_cmp:
                     cmp_select = [(line.id, line.name) for line in company_obj.browse(cr, uid, unconfigured_cmp)]
                     res['fields'][field]['selection'] = cmp_select
-            if field == 'chart_template_id':
-                res['fields'][field]['selection'] = [('', '')]
-                if template_ids:
-                    template_select = [(template.id, template.name) for template in acc_template_obj.browse(cr, uid, template_ids)]
-                    res['fields'][field]['selection'] = template_select
         return res
 
     def check_created_journals(self, cr, uid, vals_journal, company_id, context=None):
@@ -3081,12 +3126,12 @@ class wizard_multi_charts_accounts(osv.osv_memory):
 
     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.
-        @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.
+        This method is used for creating journals.
+
+        :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.
+        :returns: True
         """
         journal_data = self._prepare_all_journals(cr, uid, chart_template_id, acc_template_ref, company_id, context=context)
         for vals_journal in journal_data:
@@ -3215,6 +3260,9 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         :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
+        :param acc_ref: Mapping between ids of account templates and real accounts created from them
+        :param taxes_ref: Mapping between ids of tax templates and real taxes created from them
+        :param tax_code_ref: Mapping between ids of tax code templates and real tax codes created from them
         :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,
@@ -3242,6 +3290,9 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         :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
+        :param acc_ref: Mapping between ids of account templates and real accounts created from them
+        :param taxes_ref: Mapping between ids of tax templates and real taxes created from them
+        :param tax_code_ref: Mapping between ids of tax code templates and real tax codes created from them
         :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,
@@ -3260,7 +3311,7 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         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_templates = [x for x in template.tax_template_ids if x.installable]
+        tax_templates = [x for x in template.tax_template_ids]
         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'])
 
@@ -3291,7 +3342,8 @@ class wizard_multi_charts_accounts(osv.osv_memory):
         '''
         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.
+        to the provided sale/purchase rates. Then it saves the new tax templates as default taxes to use for this chart
+        template.
 
         :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
@@ -3335,7 +3387,6 @@ class wizard_multi_charts_accounts(osv.osv_memory):
                                             '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,