diff --git a/addons/account/account.py b/addons/account/account.py index caf1d68c45d..571ea40698d 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -1862,8 +1862,10 @@ class account_tax(osv.osv): 'applicable_type': fields.selection( [('true','Always'), ('code','Given by Python Code')], 'Applicability', required=True, help="If not applicable (computed through a Python code), the tax won't appear on the invoice."), 'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."), - 'account_collected_id':fields.many2one('account.account', 'Invoice Tax Account'), - 'account_paid_id':fields.many2one('account.account', 'Refund Tax Account'), + 'account_collected_id':fields.many2one('account.account', 'Invoice Tax Account', help="Set the account that will be set by default on invoice tax lines for invoices. Leave empty to use the expense account."), + 'account_paid_id':fields.many2one('account.account', 'Refund Tax Account', help="Set the account that will be set by default on invoice tax lines for refunds. Leave empty to use the expense account."), + 'account_analytic_collected_id':fields.many2one('account.analytic.account', 'Invoice Tax Analytic Account', help="Set the analytic account that will be used by default on the invoice tax lines for invoices. Leave empty if you don't want to use an analytic account on the invoice tax lines by default."), + 'account_analytic_paid_id':fields.many2one('account.analytic.account', 'Refund Tax Analytic Account', help="Set the analytic account that will be used by default on the invoice tax lines for refunds. Leave empty if you don't want to use an analytic account on the invoice tax lines by default."), 'parent_id':fields.many2one('account.tax', 'Parent Tax Account', select=True), 'child_ids':fields.one2many('account.tax', 'parent_id', 'Child Tax Accounts'), 'child_depend':fields.boolean('Tax on Children', help="Set if the tax computation is based on the computation of child taxes rather than on the total amount."), @@ -2001,6 +2003,8 @@ class account_tax(osv.osv): 'name':tax.description and tax.description + " - " + tax.name or tax.name, 'account_collected_id':tax.account_collected_id.id, 'account_paid_id':tax.account_paid_id.id, + 'account_analytic_collected_id': tax.account_analytic_collected_id.id, + 'account_analytic_paid_id': tax.account_analytic_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, @@ -2066,7 +2070,20 @@ class account_tax(osv.osv): 'taxes': [] # List of taxes, see compute for the format } """ + + # By default, for each tax, tax amount will first be computed + # and rounded at the 'Account' decimal precision for each + # PO/SO/invoice line and then these rounded amounts will be + # summed, leading to the total amount for that tax. But, if the + # company has tax_calculation_rounding_method = round_globally, + # we still follow the same method, but we use a much larger + # precision when we round the tax amount for each line (we use + # the 'Account' decimal precision + 5), and that way it's like + # rounding after the sum of the tax amounts of each line precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account') + tax_compute_precision = precision + if taxes and taxes[0].company_id.tax_calculation_rounding_method == 'round_globally': + tax_compute_precision += 5 totalin = totalex = round(price_unit * quantity, precision) tin = [] tex = [] @@ -2075,7 +2092,7 @@ class account_tax(osv.osv): tex.append(tax) else: tin.append(tax) - tin = self.compute_inv(cr, uid, tin, price_unit, quantity, product=product, partner=partner) + tin = self.compute_inv(cr, uid, tin, price_unit, quantity, product=product, partner=partner, precision=tax_compute_precision) for r in tin: totalex -= r.get('amount', 0.0) totlex_qty = 0.0 @@ -2083,7 +2100,7 @@ class account_tax(osv.osv): totlex_qty = totalex/quantity except: pass - tex = self._compute(cr, uid, tex, totlex_qty, quantity,product=product, partner=partner) + tex = self._compute(cr, uid, tex, totlex_qty, quantity, product=product, partner=partner, precision=tax_compute_precision) for r in tex: totalin += r.get('amount', 0.0) return { @@ -2096,7 +2113,7 @@ class account_tax(osv.osv): _logger.warning("Deprecated, use compute_all(...)['taxes'] instead of compute(...) to manage prices with tax included") return self._compute(cr, uid, taxes, price_unit, quantity, product, partner) - def _compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None): + def _compute(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, precision=None): """ Compute tax values for given PRICE_UNIT, QUANTITY and a buyer/seller ADDRESS_ID. @@ -2105,14 +2122,15 @@ class account_tax(osv.osv): tax = {'name':'', 'amount':0.0, 'account_collected_id':1, 'account_paid_id':2} one tax for each tax id in IDS and their children """ + if not precision: + precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account') res = self._unit_compute(cr, uid, taxes, price_unit, product, partner, quantity) total = 0.0 - precision_pool = self.pool.get('decimal.precision') for r in res: if r.get('balance',False): - r['amount'] = round(r.get('balance', 0.0) * quantity, precision_pool.precision_get(cr, uid, 'Account')) - total + r['amount'] = round(r.get('balance', 0.0) * quantity, precision) - total else: - r['amount'] = round(r.get('amount', 0.0) * quantity, precision_pool.precision_get(cr, uid, 'Account')) + r['amount'] = round(r.get('amount', 0.0) * quantity, precision) total += r['amount'] return res @@ -2160,6 +2178,8 @@ class account_tax(osv.osv): 'amount': amount, 'account_collected_id': tax.account_collected_id.id, 'account_paid_id': tax.account_paid_id.id, + 'account_analytic_collected_id': tax.account_analytic_collected_id.id, + 'account_analytic_paid_id': tax.account_analytic_paid_id.id, 'base_code_id': tax.base_code_id.id, 'ref_base_code_id': tax.ref_base_code_id.id, 'sequence': tax.sequence, @@ -2188,7 +2208,7 @@ class account_tax(osv.osv): r['todo'] = 0 return res - def compute_inv(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None): + def compute_inv(self, cr, uid, taxes, price_unit, quantity, product=None, partner=None, precision=None): """ Compute tax values for given PRICE_UNIT, QUANTITY and a buyer/seller ADDRESS_ID. Price Unit is a VAT included price @@ -2198,15 +2218,15 @@ class account_tax(osv.osv): tax = {'name':'', 'amount':0.0, 'account_collected_id':1, 'account_paid_id':2} one tax for each tax id in IDS and their children """ + if not precision: + precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account') res = self._unit_compute_inv(cr, uid, taxes, price_unit, product, partner=None) total = 0.0 - obj_precision = self.pool.get('decimal.precision') for r in res: - prec = obj_precision.precision_get(cr, uid, 'Account') if r.get('balance',False): - r['amount'] = round(r['balance'] * quantity, prec) - total + r['amount'] = round(r['balance'] * quantity, precision) - total else: - r['amount'] = round(r['amount'] * quantity, prec) + r['amount'] = round(r['amount'] * quantity, precision) total += r['amount'] return res diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 280b813380f..06de5a3e43e 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -34,8 +34,8 @@ class account_analytic_line(osv.osv): 'journal_id': fields.many2one('account.analytic.journal', 'Analytic Journal', required=True, ondelete='restrict', select=True), 'code': fields.char('Code', size=8), 'ref': fields.char('Ref.', size=64), - 'currency_id': fields.related('move_id', 'currency_id', type='many2one', relation='res.currency', string='Account currency', store=True, help="The related account currency if not equal to the company one.", readonly=True), - 'amount_currency': fields.related('move_id', 'amount_currency', type='float', string='Amount currency', store=True, help="The amount expressed in the related account currency if not equal to the company one.", readonly=True), + 'currency_id': fields.related('move_id', 'currency_id', type='many2one', relation='res.currency', string='Account Currency', store=True, help="The related account currency if not equal to the company one.", readonly=True), + 'amount_currency': fields.related('move_id', 'amount_currency', type='float', string='Amount Currency', store=True, help="The amount expressed in the related account currency if not equal to the company one.", readonly=True), } _defaults = { diff --git a/addons/account/account_bank.py b/addons/account/account_bank.py index cbc5a966f79..ef146128a67 100644 --- a/addons/account/account_bank.py +++ b/addons/account/account_bank.py @@ -43,6 +43,12 @@ class bank(osv.osv): "Return the name to use when creating a bank journal" return (bank.bank_name or '') + ' ' + bank.acc_number + def _prepare_name_get(self, cr, uid, bank_type_obj, bank_obj, context=None): + """Add ability to have %(currency_name)s in the format_layout of + res.partner.bank.type""" + bank_obj._data[bank_obj.id]['currency_name'] = bank_obj.currency_id and bank_obj.currency_id.name or '' + return super(bank, self)._prepare_name_get(cr, uid, bank_type_obj, bank_obj, context=context) + def post_write(self, cr, uid, ids, context={}): if isinstance(ids, (int, long)): ids = [ids] diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index c6011979f8d..6a0a29cb2fe 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -195,7 +195,7 @@ class account_invoice(osv.osv): 'number': fields.related('move_id','name', type='char', readonly=True, size=64, relation='account.move', store=True, string='Number'), 'internal_number': fields.char('Invoice Number', size=32, readonly=True, help="Unique number of the invoice, computed automatically when the invoice is created."), 'reference': fields.char('Invoice Reference', size=64, help="The partner reference of this invoice."), - 'reference_type': fields.selection(_get_reference_type, 'Reference Type', + 'reference_type': fields.selection(_get_reference_type, 'Payment Reference', required=True, readonly=True, states={'draft':[('readonly',False)]}), 'comment': fields.text('Additional Information'), @@ -756,7 +756,7 @@ class account_invoice(osv.osv): for tax in inv.tax_line: if tax.manual: continue - key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id) + key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id, tax.account_analytic_id.id) tax_key.append(key) if not key in compute_taxes: raise osv.except_osv(_('Warning !'), _('Global taxes defined, but they are not in invoice lines !')) @@ -1345,7 +1345,7 @@ class account_invoice_line(osv.osv): _name = "account.invoice.line" _description = "Invoice Line" _columns = { - 'name': fields.char('Description', size=256, required=True), + 'name': fields.text('Description', required=True), 'origin': fields.char('Source', size=256, help="Reference of the document that produced this invoice."), 'invoice_id': fields.many2one('account.invoice', 'Invoice Reference', ondelete='cascade', select=True), 'uos_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null'), @@ -1357,7 +1357,6 @@ class account_invoice_line(osv.osv): 'quantity': fields.float('Quantity', required=True), 'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Account')), 'invoice_line_tax_id': fields.many2many('account.tax', 'account_invoice_line_tax', 'invoice_line_id', 'tax_id', 'Taxes', domain=[('parent_id','=',False)]), - 'note': fields.text('Notes'), 'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account'), 'company_id': fields.related('invoice_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True), 'partner_id': fields.related('invoice_id','partner_id',type='many2one',relation='res.partner',string='Partner',store=True) @@ -1430,7 +1429,8 @@ class account_invoice_line(osv.osv): domain = {} result['uos_id'] = res.uom_id.id or uom or False - result['note'] = res.description + if res.description: + result['name'] += '\n'+res.description if result['uos_id']: res2 = res.uom_id.category_id.id if res2: @@ -1524,7 +1524,7 @@ class account_invoice_line(osv.osv): def move_line_get_item(self, cr, uid, line, context=None): return { 'type':'src', - 'name': line.name[:64], + 'name': line.name.split('\n')[0][:64], 'price_unit':line.price_unit, 'quantity':line.quantity, 'price':line.price_subtotal, @@ -1578,6 +1578,7 @@ class account_invoice_tax(osv.osv): 'invoice_id': fields.many2one('account.invoice', 'Invoice Line', ondelete='cascade', select=True), 'name': fields.char('Tax Description', size=64, required=True), 'account_id': fields.many2one('account.account', 'Tax Account', required=True, domain=[('type','<>','view'),('type','<>','income'), ('type', '<>', 'closed')]), + 'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'), 'base': fields.float('Base', digits_compute=dp.get_precision('Account')), 'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')), 'manual': fields.boolean('Manual'), @@ -1648,14 +1649,16 @@ class account_invoice_tax(osv.osv): val['base_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['base'] * tax['base_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False) val['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['amount'] * tax['tax_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False) val['account_id'] = tax['account_collected_id'] or line.account_id.id + val['account_analytic_id'] = tax['account_analytic_collected_id'] else: val['base_code_id'] = tax['ref_base_code_id'] val['tax_code_id'] = tax['ref_tax_code_id'] val['base_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['base'] * tax['ref_base_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False) val['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['amount'] * tax['ref_tax_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False) val['account_id'] = tax['account_paid_id'] or line.account_id.id + val['account_analytic_id'] = tax['account_analytic_paid_id'] - key = (val['tax_code_id'], val['base_code_id'], val['account_id']) + key = (val['tax_code_id'], val['base_code_id'], val['account_id'], val['account_analytic_id']) if not key in tax_grouped: tax_grouped[key] = val else: @@ -1687,7 +1690,8 @@ class account_invoice_tax(osv.osv): 'price': t['amount'] or 0.0, 'account_id': t['account_id'], 'tax_code_id': t['tax_code_id'], - 'tax_amount': t['tax_amount'] + 'tax_amount': t['tax_amount'], + 'account_analytic_id': t['account_analytic_id'], }) return res diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index 7121094641c..211a40f030f 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -50,24 +50,27 @@ form
- - - -
@@ -209,47 +210,54 @@ - + +
- - - - - - - - - - - - - -
- - - - + + - - - + +
-
- +
@@ -304,27 +312,18 @@