I have customizing a module in odoo 8 .But When I create invoices I got below error .How to override amount_all method in odoo 8
additional_discount/invoice.py", line 19, in _amount_all
return self._amount_all_generic(account_invoice, *args, **kwargs)
File "/home/ubuntu-libu/odoo/addons/additional_discount/common.py", line 27, in _amount_all_generic
res = super(cls, self)._amount_all(cr, uid, ids, field_name, arg, context)
AttributeError: 'super' object has no attribute '_amount_all'
This is my Full code-----------------------------------------------------
================
.xml-------------------
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="view_order_additional_discount" model="ir.ui.view">
<field name="name">sale.order.form</field>
<field name="model">sale.order</field>
<field name="type">form</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<field name="amount_untaxed" position="after">
<field name="add_disc" colspan="2"/>
<!-- <field name="add_disc_amt" colspan="2"/> -->
<field name="amount_net" sum="Net Amount" colspan="2"/>
</field>
</field>
</record>
<record id="purchase_order_form_add_discount" model="ir.ui.view">
<field name="name">purchase.order.form</field>
<field name="model">purchase.order</field>
<field name="type">form</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<field name="amount_untaxed" position="after">
<field name="add_disc" colspan="2"/>
<!-- <field name="add_disc_amt" colspan="2"/> -->
<field name="amount_net" sum="Net Amount" colspan="2"/>
</field>
</field>
</record>
<record id="invoice_form_add_discount" model="ir.ui.view">
<field name="name">account.invoice.form</field>
<field name="model">account.invoice</field>
<field name="type">form</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<field name="amount_untaxed" position="after">
<field name="add_disc" />
<!-- <field name="add_disc_amt" /> -->
<field name="amount_net" sum="Net Amount"/>
</field>
</field>
</record>
<record id="invoice_supplier_form_add_discount" model="ir.ui.view">
<field name="name">account.invoice.supplier.form</field>
<field name="model">account.invoice</field>
<field name="type">form</field>
<field name="inherit_id" ref="account.invoice_supplier_form"/>
<field name="priority">2</field>
<field name="arch" type="xml">
<field name="amount_untaxed" position="after">
<field name="add_disc" />
<!-- <field name="add_disc_amt" /> -->
<field name="amount_net" sum="Net Amount"/>
</field>
</field>
</record>
</data>
</openerp>
===================
************init.py**************
import sale
import purchase
import invoice
===========================================================
*************common.py ***********
from osv import osv
from tools.translate import _
class AdditionalDiscountable(object):
_line_column = 'order_line'
_tax_column = 'tax_id'
def record_currency(self, record):
"""Return currency browse record from a browse record.
Default implementation is for sale/purchase order.
"""
return record.pricelist_id.currency_id
def _amount_all_generic(self, cls, cr, uid, ids, field_name, arg,
context=None):
"""Generic overload of the base method to add discount infos
This is a generic version that needs to be passed the caller class (for
super).
For now it can be applied to sale.order, purchase.order and
account.invoice, using the methods and attrs of AdditionalDiscountable
"""
cur_obj = self.pool.get('res.currency')
res = super(cls, self)._amount_all(cr, uid, ids, field_name, arg, context)
for record in self.browse(cr, uid, ids, context=context):
# Taxes are applied line by line, we cannot apply a
# discount on taxes that are not proportional
if not all(t.type == 'percent'
for line in getattr(record, self._line_column)
for t in getattr(line, self._tax_column)):
raise osv.except_osv(_('Discount error'),
_('Unable (for now) to compute a global '
'discount with non percent-type taxes'))
o_res = res[record.id]
cur = self.record_currency(record)
def cur_round(value):
"""Round value according to currency."""
return cur_obj.round(cr, uid, cur, value)
# add discount
amount_untaxed = sum(line.price_subtotal
for line in getattr(record, self._line_column))
add_disc = record.add_disc
add_disc_amt = cur_round(amount_untaxed * add_disc / 100)
o_res['add_disc_amt'] = add_disc_amt
o_res['amount_net'] = o_res['amount_untaxed'] - add_disc_amt
# we apply a discount on the tax as well.
# We might have rounding issue
o_res['amount_tax'] = cur_round(
o_res['amount_tax'] * (100.0 - (add_disc or 0.0))/100.0)
o_res['amount_total'] = o_res['amount_net'] + o_res['amount_tax']
return res
====================
****************invoice.py*************
import openerp.addons.decimal_precision as dp
from openerp.osv import fields, osv
from common import AdditionalDiscountable
from openerp.tools.translate import _
class account_invoice(AdditionalDiscountable, osv.Model):
_inherit = "account.invoice"
_description = 'Invoice'
_line_column = 'invoice_line'
_tax_column = 'invoice_line_tax_id'
def record_currency(self, record):
"""Return currency browse record from an invoice record (override)."""
return record.currency_id
def _amount_all(self, *args, **kwargs):
return self._amount_all_generic(account_invoice, *args, **kwargs)
def _get_invoice_line(self, cr, uid, ids, context=None):
"""copy pasted from account_invoice"""
result = {}
for line in self.pool.get('account.invoice.line').browse(cr, uid, ids, context=context):
result[line.invoice_id.id] = True
return result.keys()
def _get_invoice_tax(self, cr, uid, ids, context=None):
"""copy pasted from account_invoice"""
result = {}
for tax in self.pool.get('account.invoice.tax').browse(cr, uid, ids, context=context):
result[tax.invoice_id.id] = True
return result.keys()
_columns={
'add_disc':fields.float('Additional Discount(-)',digits=(4,2),readonly=True, states={'draft':[('readonly',False)]}),
'add_disc_amt': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Additional Disc Amt',
store =True,multi='sums', help="The additional discount on untaxed amount."),
'amount_net': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Net Amount',
store = True,multi='sums', help="The amount after additional discount."),
'amount_untaxed': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Untaxed',
store={
'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line', 'add_disc'], 20),
'account.invoice.tax': (_get_invoice_tax, None, 20),
'account.invoice.line': (_get_invoice_line, ['price_unit','invoice_line_tax_id','quantity','discount','invoice_id'], 20),
},
multi='all'),
'amount_tax': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Tax',
store={
'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line', 'add_disc'], 20),
'account.invoice.tax': (_get_invoice_tax, None, 20),
'account.invoice.line': (_get_invoice_line, ['price_unit','invoice_line_tax_id','quantity','discount','invoice_id'], 20),
},
multi='all'),
'amount_total': fields.function(_amount_all, digits_compute=dp.get_precision('Account'), string='Total',
store={
'account.invoice': (lambda self, cr, uid, ids, c={}: ids, ['invoice_line', 'add_disc'], 20),
'account.invoice.tax': (_get_invoice_tax, None, 20),
'account.invoice.line': (_get_invoice_line, ['price_unit','invoice_line_tax_id','quantity','discount','invoice_id'], 20),
},
multi='all'),
}
_defaults={
'add_disc': 0.0,
}
class account_invoice_tax(osv.Model):
_inherit = 'account.invoice.tax'
def compute(self, cr, uid, invoice_id, context=None):
tax_grouped = super(account_invoice_tax, self).compute(cr, uid, invoice_id, context)
tax_pool = self.pool.get('account.tax')
cur_pool = self.pool.get('res.currency')
tax_ids = set([key[0] for key in tax_grouped])
taxes = tax_pool.browse(cr, uid, tax_ids)
if taxes and not all(t.type == 'percent' for t in taxes):
raise osv.except_osv(_('Discount error'),
_('Unable (for now) to compute a global '
'discount with non percent-type taxes'))
invoice = self.pool.get('account.invoice').browse(cr, uid, invoice_id, context=context)
add_disc = invoice.add_disc
cur = invoice.currency_id
for line in tax_grouped:
for key in ('tax_amount', 'base_amount', 'amount', 'base'): #FIXME?
val = tax_grouped[line][key]
tax_grouped[line][key] = cur_pool.round(cr, uid, cur, val * (1.0 - add_disc / 100.0))
print tax_grouped
return tax_grouped
============================
********************purchase.py**********
from openerp.osv import osv, fields
import openerp.addons.decimal_precision as dp
from openerp.tools.translate import _
from common import AdditionalDiscountable
class purchase_order(AdditionalDiscountable, osv.osv):
_inherit = "purchase.order"
_description = "Purchase Order"
_tax_column = 'taxes_id'
_line_column = 'order_line'
def _amount_all(self, *args, **kwargs):
return self._amount_all_generic(purchase_order, *args, **kwargs)
_columns={
'add_disc': fields.float('Additional Discount(-)', digits=(4,2),
states={'confirmed': [('readonly',True)],
'approved': [('readonly',True)],
'done': [('readonly',True)]}),
'add_disc_amt': fields.function(_amount_all, method=True, store=True, multi='sums',
digits_compute= dp.get_precision('Sale Price'),
string='Additional Disc Amt',
help="The additional discount on untaxed amount."),
'amount_net': fields.function(_amount_all, method=True, store=True, multi='sums',
digits_compute= dp.get_precision('Sale Price'),
string='Net Amount',
help="The amount after additional discount."),
'amount_untaxed': fields.function(_amount_all, method=True, store=True, multi="sums",
digits_compute= dp.get_precision('Purchase Price'),
string='Untaxed Amount',
help="The amount without tax"),
'amount_tax': fields.function(_amount_all, method=True, store=True, multi="sums",
digits_compute= dp.get_precision('Purchase Price'),
string='Taxes',
help="The tax amount"),
'amount_total': fields.function(_amount_all, method=True, store=True, multi="sums",
digits_compute= dp.get_precision('Purchase Price'),
string='Total',
help="The total amount"),
}
_defaults={
'add_disc': 0.0,
}
def action_invoice_create(self, cr, uid, ids, context=None):
"""Add a discount in the invoice after creation, and recompute the total
"""
inv_obj = self.pool.get('account.invoice')
for order in self.browse(cr, uid, ids, context):
# create the invoice
inv_id = super(purchase_order, self).action_invoice_create(cr, uid, ids, context)
# modify the invoice
inv_obj.write(cr, uid, [inv_id], {'add_disc': order.add_disc or 0.0}, context)
inv_obj.button_compute(cr, uid, [inv_id], context=context, set_total=True)
res = inv_id
return res
********sale.py*****************
from openerp.osv import fields, osv
import openerp.addons.decimal_precision as dp
from openerp.tools.translate import _
from common import AdditionalDiscountable
class sale_order(AdditionalDiscountable, osv.osv):
_inherit = 'sale.order'
_tax_column = 'tax_id'
_line_column = 'order_line'
def _amount_all(self, *args, **kwargs):
return self._amount_all_generic(sale_order, *args, **kwargs)
_columns = {
'add_disc':fields.float('Additional Discount(-)',digits=(4,2), readonly=True, states={'draft': [('readonly', False)]}),
'add_disc_amt': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Additional Disc Amt',
store =True,multi='sums', help="The additional discount on untaxed amount."),
'amount_untaxed': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Untaxed Amount',
store = True,multi='sums', help="The amount without tax."),
'amount_net': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Net Amount',
store = True,multi='sums', help="The amount after additional discount."),
'amount_tax': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Taxes',
store = True,multi='sums', help="The tax amount."),
'amount_total': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Sale Price'), string='Total',
store = True,multi='sums', help="The total amount."),
}
_defaults={
'add_disc': 0.0,
}
def _make_invoice(self, cr, uid, order, lines, context=None):
"""Add a discount in the invoice after creation, and recompute the total
"""
inv_obj = self.pool.get('account.invoice')
# create the invoice
inv_id = super(sale_order, self)._make_invoice(cr, uid, order, lines, context)
# modify the invoice
inv_obj.write(cr, uid, [inv_id], {'add_disc': order.add_disc or 0.0}, context)
inv_obj.button_compute(cr, uid, [inv_id])
return inv_id
please provide your code for class = AdditionalDiscountable
Hi Atchutan I update my question with AdditionalDiscountable class
what is the use of _line_column and _tax_column? and why is the AdditionalDiscountable class not inheriting osv.Model or osv.AbstractModel? You could use the example of mail_thread available in MAIL module and use osv.AbstractModel.
Try to set class AdditionalDiscountable(osv.AbstractModel) and inherit this module in account.invoice and other related modules thus making this class generic.