I am currently having difficulty implementing a feature in my module that totals the amount of taxes from order lines. My module has an order line section (much like that in the sales module), which allows several products to be added and their prices to be displayed next to them. See how I added this feature here. At the bottom, I have a subtotal footer which displays three fields: amount_untaxed, amount_tax, and amount_total. The tax calculation works correctly (stored in amount_tax), but I cannot display the amount of taxes in that footer. Here is the relevant code:
models.py
# -*- coding: utf-8 -*-
from odoo import models, fields, api
from odoo.addons import decimal_precision as dp
class mymodule(models.Model):
_name = 'mymodule.mymodule'
_description = 'My Module'
currency_id = fields.Many2one('res.currency', string='Currency')
operations = fields.One2many('mymodule.line', 'mymodule_id', 'Order Lines')
amount_untaxed = fields.Monetary(string='Untaxed Amount',
default=0,
compute='_compute_untaxed',
currency_field='currency_id')
amount_tax = fields.Monetary(string='Taxes',
default=0,
compute='_compute_taxes',
currency_field='currency_id')
amount_total = fields.Monetary(string='Total',
default=0,
compute='_compute_total',
currency_field='currency_id')
# Sum all prices into untaxed total
@api.depends('operations.price')
def _compute_untaxed(self):
for record in self:
record.amount_untaxed = sum(line.price for line in record.operations)
# Sum all prices into taxed total
@api.depends('operations.total')
def _compute_total(self):
for record in self:
record.amount_total = sum(line.total for line in record.operations)
# Sum all taxes
@api.depends('operations.taxes')
def _compute_taxes(self):
for record in self:
record.amount_tax = sum(line.taxes for line in record.operations)
class mymodule_line(models.Model):
_name = 'mymodule.line'
_description = 'Order Line'
mymodule_id = fields.Many2one('mymodule.mymodule')
product_id = fields.Many2one('product.template',
string='Product',
required=False) # Product name
tax_id = fields.Many2many('account.tax',
string='Taxes',
store=False) # Product default taxes
taxes = fields.Float(string='Taxes', readonly=False)
price = fields.Float(string='Price')
total = fields.Float(string='Total', readonly=False)
# Display default values based on product selected
@api.onchange('product_id')
def _onchange_product_id(self):
self.price = self.product_id.lst_price
self.tax_id = self.product_id.taxes_id
# Compute total and tax amount for selected product
@api.onchange('price', 'tax_id')
@api.depends('total', 'tax_id.amount', 'price', 'taxes')
def _compute_total(self):
self.taxes = (0.01 * self.tax_id.amount * self.price)
self.total = self.taxes + self.price
views.xml
<record id="mymodule.form" model="ir.ui.view">
<field name="name">My Module Form</field>
<field name="model">mymodule.mymodule</field>
<field name="arch" type="xml">
<form>
<sheet>
<notebook>
<!-- Order Lines -->
<page string="Operations">
<group class="oe_subtotal_footer oe_right" colspan="2" name="sale_total">
<field name="amount_untaxed"/>
<field name="amount_tax"/>
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
</div>
<field name="amount_total" nolabel="1" class="oe_subtotal_footer_separator"/>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
What is interesting is if I change the following line as such, adding the compute argument, the amount of taxes will display properly.
taxes = fields.Float(string='Taxes', readonly=False, compute='_compute_total')
However, if I add more than one product in the order lines and then try to save the record, I get a singleton error.
ValueError: Expected singleton: mymodule.line(346, 347)
Adding the @api.one decorator above my _compute_total function then allows me to save the record, but the tax calculation disappears once it is saved.
Here is an image of what my subtotal footer should look like for reference: Subtotal Footer
I appreciate your help!