diff --git a/addons/account/__init__.py b/addons/account/__init__.py index a243b94c2da..98f7a7d5134 100644 --- a/addons/account/__init__.py +++ b/addons/account/__init__.py @@ -29,6 +29,7 @@ import account_bank import account_cash_statement import account_move_line import account_analytic_line +import account_financial_report import wizard import report import product diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index e01dbc70f07..0cd5231ef26 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -69,6 +69,7 @@ module named account_voucher. 'wizard/account_period_close_view.xml', 'account_view.xml', 'account_report.xml', + 'account_financial_report_data.xml', 'wizard/account_report_common_view.xml', 'wizard/account_invoice_refund_view.xml', 'wizard/account_fiscalyear_close_state.xml', @@ -104,7 +105,6 @@ module named account_voucher. 'account_invoice_view.xml', 'partner_view.xml', 'data/account_data.xml', - 'data/data_financial_report.xml', 'data/data_account_type.xml', 'account_invoice_workflow.xml', 'project/project_view.xml', diff --git a/addons/account/account.py b/addons/account/account.py index a73fb3d5d1c..a9b03208d0b 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -620,7 +620,7 @@ class account_account(osv.osv): if method == 'write': 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 can not remove an account containing journal items!. ')) + 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) @@ -660,7 +660,7 @@ class account_account(osv.osv): # Allow the write if the value is the same for i in [i['company_id'][0] for i in self.read(cr,uid,ids,['company_id'])]: if vals['company_id']!=i: - raise osv.except_osv(_('Warning !'), _('You cannot modify Company of account as its related record exist in Entry Lines')) + raise osv.except_osv(_('Warning !'), _('You cannot modify the company as its related to existing journal items.')) if 'active' in vals and not vals['active']: self._check_moves(cr, uid, ids, "write", context=context) if 'type' in vals.keys(): @@ -959,7 +959,7 @@ class account_fiscalyear(osv.osv): 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.')) + raise osv.except_osv(_('Error !'), _('No fiscal year defined for this date !\nPlease create one from the configuration of the accounting menu.')) else: return [] return ids @@ -2443,7 +2443,7 @@ class account_account_template(osv.osv): _columns = { '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), + 'code': fields.char('Code', size=64, required=True, select=1), 'type': fields.selection([ ('receivable','Receivable'), ('payable','Payable'), @@ -2591,8 +2591,8 @@ class account_add_tmpl_wizard(osv.osv_memory): context = {} acc_obj = self.pool.get('account.account') tmpl_obj = self.pool.get('account.account.template') - data = self.read(cr, uid, ids) - company_id = acc_obj.read(cr, uid, [data[0]['cparent_id']], ['company_id'])[0]['company_id'][0] + data = self.read(cr, uid, ids)[0] + company_id = acc_obj.read(cr, uid, [data['cparent_id'][0]], ['company_id'])[0]['company_id'][0] account_template = tmpl_obj.browse(cr, uid, context['tmpl_ids']) vals = { 'name': account_template.name, @@ -2603,7 +2603,7 @@ class account_add_tmpl_wizard(osv.osv_memory): 'reconcile': account_template.reconcile, 'shortcut': account_template.shortcut, 'note': account_template.note, - 'parent_id': data[0]['cparent_id'], + 'parent_id': data['cparent_id'][0], 'company_id': company_id, } acc_obj.create(cr, uid, vals) @@ -2923,98 +2923,6 @@ class account_fiscal_position_account_template(osv.osv): account_fiscal_position_account_template() -# --------------------------------------------------------- -# 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): - account_obj = self.pool.get('account.account') - 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_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) - 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'), - '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.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() - # --------------------------------------------------------- # Account generation from template wizards # --------------------------------------------------------- @@ -3047,6 +2955,9 @@ class wizard_multi_charts_accounts(osv.osv_memory): 'purchase_tax_rate': fields.float('Purchase 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_tax_rate(self, cr, uid, ids, rate=False, context=None): + return {'value': {'purchase_tax_rate': rate or False}} + 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') @@ -3066,15 +2977,12 @@ class wizard_multi_charts_accounts(osv.osv_memory): res['value'].update({'code_digits': data.code_digits}) return res - def default_get(self, cr, uid, fields, context=None): res = super(wizard_multi_charts_accounts, self).default_get(cr, uid, fields, context=context) tax_templ_obj = self.pool.get('account.tax.template') if 'bank_accounts_id' in fields: - res.update({'bank_accounts_id': [{'acc_name': _('Current'), 'account_type': 'bank'}, - {'acc_name': _('Deposit'), 'account_type': 'bank'}, - {'acc_name': _('Cash'), 'account_type': 'cash'}]}) + res.update({'bank_accounts_id': [{'acc_name': _('Cash'), 'account_type': 'cash'}]}) if 'company_id' in fields: res.update({'company_id': self.pool.get('res.users').browse(cr, uid, [uid], context=context)[0].company_id.id}) if 'seq_journal' in fields: @@ -3092,6 +3000,10 @@ 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'))], order="sequence") res.update({'purchase_tax': purchase_tax_ids and purchase_tax_ids[0] or False}) + res.update({ + 'purchase_tax_rate': 15.0, + 'sale_tax_rate': 15.0, + }) return res def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): @@ -3141,14 +3053,14 @@ class wizard_multi_charts_accounts(osv.osv_memory): 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 = [] + data = False if journal_type in ('sale', 'sale_refund'): - analytical_journal_ids = analytic_journal_obj.search(cr, uid, [('type','=','sale')], context=context) + data = obj_data.get_object_reference(cr, uid, 'account', 'analytic_journal_sale') elif journal_type in ('purchase', 'purchase_refund'): - analytical_journal_ids = analytic_journal_obj.search(cr, uid, [('type','=','purchase')], context=context) + pass 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 + pass + return data and data[1] or False def _get_default_account(journal_type, type='debit'): # Get the default accounts @@ -3355,46 +3267,12 @@ class wizard_multi_charts_accounts(osv.osv_memory): 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, - '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) + if obj_wizard.sale_tax: + value = obj_wizard.sale_tax_rate + obj_tax_temp.write(cr, uid, [obj_wizard.sale_tax.id], {'amount': value/100.0, 'name': _('Tax %.2f%%') % value}) + if obj_wizard.purchase_tax: + value = obj_wizard.purchase_tax_rate + obj_tax_temp.write(cr, uid, [obj_wizard.purchase_tax.id], {'amount': value/100.0, 'name': _('Purchase Tax %.2f%%') % value}) return True def execute(self, cr, uid, ids, context=None): @@ -3445,14 +3323,28 @@ class wizard_multi_charts_accounts(osv.osv_memory): :rtype: dict ''' obj_data = self.pool.get('ir.model.data') + obj_journal = self.pool.get('account.journal') # 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 + + # we need to loop again to find next number for journal code + # because we can't rely on the value current_num as, + # its possible that we already have bank journals created (e.g. by the creation of res.partner.bank) + # and the next number for account code might have been already used before for journal + journal_count = 0 + while True: + journal_code = _('BNK') + str(current_num + journal_count) + ids = obj_journal.search(cr, uid, [('code', '=', journal_code), ('company_id', '=', company_id)], context=context) + if not ids: + break + journal_count += 1 + vals = { 'name': line['acc_name'], - 'code': _('BNK') + str(current_num), + 'code': journal_code, 'type': line['account_type'] == 'cash' and 'cash' or 'bank', 'company_id': company_id, 'analytic_journal_id': False, diff --git a/addons/account/account_bank.py b/addons/account/account_bank.py index 02270b94186..54cba015f8e 100644 --- a/addons/account/account_bank.py +++ b/addons/account/account_bank.py @@ -68,7 +68,6 @@ class bank(osv.osv): name = self._prepare_name(bank) acc = { 'name': name, - 'currency_id': bank.company_id.currency_id.id, 'code': new_code, 'type': 'liquidity', 'user_type': ref_acc_bank_temp.user_type.id, diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 7bb6f3e5761..bd31b01a41d 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -297,7 +297,7 @@ class account_bank_statement(osv.osv): context=context): if line.state <> 'valid': raise osv.except_osv(_('Error !'), - _('Journal Item "%s" is not valid') % line.name) + _('Journal item "%s" is not valid.') % line.name) # Bank statements will not consider boolean on journal entry_posted account_move_obj.post(cr, uid, [move_id], context=context) @@ -352,7 +352,7 @@ class account_bank_statement(osv.osv): for st_line in st.line_ids: if st_line.analytic_account_id: if not st.journal_id.analytic_journal_id: - raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (st.journal_id.name,)) + raise osv.except_osv(_('No Analytic Journal !'),_("You have to assign an analytic journal on the '%s' journal!") % (st.journal_id.name,)) if not st_line.amount: continue st_line_number = self.get_next_st_line_number(cr, uid, st_number, st_line, context) diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py index ebc97fe8a84..226e78ccef6 100644 --- a/addons/account/account_cash_statement.py +++ b/addons/account/account_cash_statement.py @@ -311,7 +311,7 @@ class account_cash_statement(osv.osv): if journal_type == 'bank': return super(account_cash_statement, self).balance_check(cr, uid, cash_id, journal_type, context) if not self._equal_balance(cr, uid, cash_id, context): - raise osv.except_osv(_('Error !'), _('The closing balance should be the same than the computed balance !')) + raise osv.except_osv(_('Error !'), _('The closing balance should be the same than the computed balance!')) return True def statement_close(self, cr, uid, ids, journal_type='bank', context=None): diff --git a/addons/account/account_financial_report.py b/addons/account/account_financial_report.py new file mode 100644 index 00000000000..4ee8ac3d74b --- /dev/null +++ b/addons/account/account_financial_report.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import time +from datetime import datetime +from dateutil.relativedelta import relativedelta +from operator import itemgetter + +import netsvc +import pooler +from osv import fields, osv +import decimal_precision as dp +from tools.translate import _ + +# --------------------------------------------------------- +# 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): + account_obj = self.pool.get('account.account') + 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_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) + 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'), + '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.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() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/data/data_financial_report.xml b/addons/account/account_financial_report_data.xml similarity index 100% rename from addons/account/data/data_financial_report.xml rename to addons/account/account_financial_report_data.xml diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 6fcc211bd84..9772984bc3b 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -68,7 +68,7 @@ class account_invoice(osv.osv): tt = type2journal.get(type_inv, 'sale') result = self.pool.get('account.analytic.journal').search(cr, uid, [('type','=',tt)], context=context) if not result: - raise osv.except_osv(_('No Analytic Journal !'),_("You must define an analytic journal of type '%s' !") % (tt,)) + raise osv.except_osv(_('No Analytic Journal !'),_("You must define an analytic journal of type '%s'!") % (tt,)) return result[0] def _get_type(self, cr, uid, context=None): @@ -261,7 +261,7 @@ class account_invoice(osv.osv): 'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account', help='Bank Account Number, Company bank account if Invoice is customer or supplier refund, otherwise Partner bank account number.', readonly=True, states={'draft':[('readonly',False)]}), 'move_lines':fields.function(_get_lines, type='many2many', relation='account.move.line', string='Entry Lines'), - 'residual': fields.function(_amount_residual, digits_compute=dp.get_precision('Account'), string='To Pay', + 'residual': fields.function(_amount_residual, digits_compute=dp.get_precision('Account'), string='Balance', store={ 'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line','move_id'], 50), 'account.invoice.tax': (_get_invoice_tax, None, 50), @@ -414,7 +414,7 @@ class account_invoice(osv.osv): pay_res_id = pay_line_data and pay_line_data[0].get('value_reference',False) and int(pay_line_data[0]['value_reference'].split(',')[1]) or False if not rec_res_id and not pay_res_id: raise osv.except_osv(_('Configuration Error !'), - _('Can not find account chart for this company, Please Create account.')) + _('Can not find a chart of accounts for this company, you should create one.')) account_obj = self.pool.get('account.account') rec_obj_acc = account_obj.browse(cr, uid, [rec_res_id]) pay_obj_acc = account_obj.browse(cr, uid, [pay_res_id]) @@ -481,7 +481,7 @@ class account_invoice(osv.osv): pterm_list.sort() res = {'value':{'date_due': pterm_list[-1]}} else: - raise osv.except_osv(_('Data Insufficient !'), _('The Payment Term of Supplier does not have Payment Term Lines(Computation) defined !')) + raise osv.except_osv(_('Data Insufficient !'), _('The payment term of supplier does not have a payment term line!')) return res def onchange_invoice_line(self, cr, uid, ids, lines): @@ -514,7 +514,7 @@ class account_invoice(osv.osv): pay_res_id = pay_line_data and pay_line_data[0].get('value_reference',False) and int(pay_line_data[0]['value_reference'].split(',')[1]) or False if not rec_res_id and not pay_res_id: raise osv.except_osv(_('Configuration Error !'), - _('Can not find account chart for this company, Please Create account.')) + _('Can not find a chart of account, you should create one from the configuration of the accounting menu.')) if type in ('out_invoice', 'out_refund'): acc_id = rec_res_id else: @@ -529,7 +529,7 @@ class account_invoice(osv.osv): result_id = account_obj.search(cr, uid, [('name','=',line.account_id.name),('company_id','=',company_id)]) if not result_id: raise osv.except_osv(_('Configuration Error !'), - _('Can not find account chart for this company in invoice line account, Please Create account.')) + _('Can not find a chart of account, you should create one from the configuration of the accounting menu.')) inv_line_obj.write(cr, uid, [line.id], {'account_id': result_id[-1]}) else: if invoice_line: @@ -730,13 +730,13 @@ class account_invoice(osv.osv): key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id) tax_key.append(key) if not key in compute_taxes: - raise osv.except_osv(_('Warning !'), _('Global taxes defined, but are not in invoice lines !')) + raise osv.except_osv(_('Warning !'), _('Global taxes defined, but they are not in invoice lines !')) base = compute_taxes[key]['base'] if abs(base - tax.base) > inv.company_id.currency_id.rounding: - raise osv.except_osv(_('Warning !'), _('Tax base different !\nClick on compute to update tax base')) + raise osv.except_osv(_('Warning !'), _('Tax base different!\nClick on compute to update the tax base.')) for key in compute_taxes: if not key in tax_key: - raise osv.except_osv(_('Warning !'), _('Taxes missing !')) + raise osv.except_osv(_('Warning !'), _('Taxes are missing!\nClick on compute button.')) def compute_invoice_totals(self, cr, uid, inv, company_currency, ref, invoice_move_lines): total = 0 @@ -794,34 +794,39 @@ class account_invoice(osv.osv): line.append((0,0,val)) return line - def action_move_create(self, cr, uid, ids, *args): + def action_move_create(self, cr, uid, ids, context=None): """Creates invoice related analytics and financial move lines""" ait_obj = self.pool.get('account.invoice.tax') cur_obj = self.pool.get('res.currency') period_obj = self.pool.get('account.period') - context = {} - for inv in self.browse(cr, uid, ids): + payment_term_obj = self.pool.get('account.payment.term') + journal_obj = self.pool.get('account.journal') + move_obj = self.pool.get('account.move') + if context is None: + context = {} + for inv in self.browse(cr, uid, ids, context=context): if not inv.journal_id.sequence_id: - raise osv.except_osv(_('Error !'), _('Please define sequence on invoice journal')) + raise osv.except_osv(_('Error !'), _('Please define sequence on the journal related to this invoice.')) if not inv.invoice_line: raise osv.except_osv(_('No Invoice Lines !'), _('Please create some invoice lines.')) if inv.move_id: continue - + + ctx = context.copy() + ctx.update({'lang': inv.partner_id.lang}) if not inv.date_invoice: - self.write(cr, uid, [inv.id], {'date_invoice':time.strftime('%Y-%m-%d')}) + self.write(cr, uid, [inv.id], {'date_invoice':time.strftime('%Y-%m-%d')}, context=ctx) company_currency = inv.company_id.currency_id.id # create the analytical lines # one move line per invoice line - iml = self._get_analytic_lines(cr, uid, inv.id) + iml = self._get_analytic_lines(cr, uid, inv.id, context=ctx) # check if taxes are all computed - ctx = context.copy() - ctx.update({'lang': inv.partner_id.lang}) compute_taxes = ait_obj.compute(cr, uid, inv.id, context=ctx) self.check_tax_lines(cr, uid, inv, compute_taxes, ait_obj) - if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0): - raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe real total does not match the computed total.')) + # I disabled the check_total feature + #if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0): + # raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe real total does not match the computed total.')) if inv.payment_term: total_fixed = total_percent = 0 @@ -832,7 +837,7 @@ class account_invoice(osv.osv): total_percent += line.value_amount total_fixed = (total_fixed * 100) / (inv.amount_total or 1.0) if (total_fixed + total_percent) > 100: - raise osv.except_osv(_('Error !'), _("Can not create the invoice !\nThe related payment term is probably misconfigured as it gives a computed amount greater than the total invoiced amount.")) + raise osv.except_osv(_('Error !'), _("Can not create the invoice !\nThe related payment term is probably misconfigured as it gives a computed amount greater than the total invoiced amount. The latest line of your payment term must be of type 'balance' to avoid rounding issues.")) # one move line per tax line iml += ait_obj.move_line_get(cr, uid, inv.id) @@ -859,8 +864,8 @@ class account_invoice(osv.osv): name = inv['name'] or '/' totlines = False if inv.payment_term: - totlines = self.pool.get('account.payment.term').compute(cr, - uid, inv.payment_term.id, total, inv.date_invoice or False) + totlines = payment_term_obj.compute(cr, + uid, inv.payment_term.id, total, inv.date_invoice or False, context=ctx) if totlines: res_amount_currency = total_currency i = 0 @@ -906,12 +911,12 @@ class account_invoice(osv.osv): date = inv.date_invoice or time.strftime('%Y-%m-%d') part = inv.partner_id.id - line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part, date, context={})),iml) + line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part, date, context=ctx)),iml) line = self.group_lines(cr, uid, iml, line, inv) journal_id = inv.journal_id.id - journal = self.pool.get('account.journal').browse(cr, uid, journal_id) + journal = journal_obj.browse(cr, uid, journal_id, context=ctx) if journal.centralisation: raise osv.except_osv(_('UserError'), _('You cannot create an invoice on a centralised journal. Uncheck the centralised counterpart box in the related journal from the configuration menu.')) @@ -935,13 +940,14 @@ class account_invoice(osv.osv): for i in line: i[2]['period_id'] = period_id - move_id = self.pool.get('account.move').create(cr, uid, move, context=context) - new_move_name = self.pool.get('account.move').browse(cr, uid, move_id).name + move_id = move_obj.create(cr, uid, move, context=ctx) + new_move_name = move_obj.browse(cr, uid, move_id, context=ctx).name # make the invoice point to that move - self.write(cr, uid, [inv.id], {'move_id': move_id,'period_id':period_id, 'move_name':new_move_name}) + self.write(cr, uid, [inv.id], {'move_id': move_id,'period_id':period_id, 'move_name':new_move_name}, context=ctx) # Pass invoice in context in method post: used if you want to get the same # account move reference when creating the same invoice after a cancelled one: - self.pool.get('account.move').post(cr, uid, [move_id], context={'invoice':inv}) + ctx.update({'invoice':inv}) + move_obj.post(cr, uid, [move_id], context=ctx) self._log_event(cr, uid, ids) return True @@ -1262,7 +1268,7 @@ class account_invoice_line(osv.osv): def _price_unit_default(self, cr, uid, context=None): if context is None: context = {} - if 'check_total' in context: + if context.get('check_total', False): t = context['check_total'] for l in context.get('invoice_line', {}): if isinstance(l, (list, tuple)) and len(l) >= 3 and l[2]: diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 55d27e2e842..41e5aff24c8 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -152,8 +152,8 @@ - +