There is a subtotal (price_subtotal) field in Quotation Order Line.
I have added a new field extra_discount.
I have tried this code but to no avail.
#api.depends('product_uom_qty', 'price_unit', 'extra_discount')
def compute_all(self):
for record in self:
record.price_subtotal = (record.product_uom_qty * record.price_unit) - record.extra_discount
It does nothing to the subtotal.
So, how do I make this happen?
I would try to override the computation method behind the field sale.order.line.price_subtotal.
But i'm not sure if api.depends() extensions (adding one more recomputation trigger field) are working as expected.
But it should look something like that:
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
extra_discount = fields.Float()
#api.depends('product_uom_qty', 'discount', 'price_unit',
'tax_id', 'extra_discount')
def _compute_amount(self):
"""
Compute the amounts of the SO line.
Fully overridden to add field extra_discount to the
formula and triggers.
"""
for line in self:
price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
# new: substract extra_discount
price -= line.extra_discount
taxes = line.tax_id.compute_all(price, line.order_id.currency_id, line.product_uom_qty, product=line.product_id, partner=line.order_id.partner_shipping_id)
line.update({
'price_tax': sum(t.get('amount', 0.0) for t in taxes.get('taxes', [])),
'price_total': taxes['total_included'],
'price_subtotal': taxes['total_excluded'],
})
if self.env.context.get('import_file', False) and not self.env.user.user_has_groups('account.group_account_manager'):
line.tax_id.invalidate_cache(['invoice_repartition_line_ids'], [line.tax_id.id])
Related
I have this 2 fields which is I want to calculate using compute
_columns = {
'feb_target':fields.float('Februari Target'),
'apr_target':fields.float('April Target'),
'ytd':fields.float('YTD', compute='_computeytd'),
}
#api.depends('feb_target', 'apr_target')
def _computeytd(self):
for record in self:
record.ytd = record.feb_target + record.apr_target
But the result is 0.
What should I do? Thank you
Wow that took me back to my beginnings.
Old API fields defined in _columns should use fields.function for computed fields. But i prefer to use the "new" API when possible. And your code looks like fully done by yourself, so it is possible.
from odoo import api, fields, models
class YourClass(models.Model):
feb_target = fields.Float('Februari Target')
apr_target = fields.Float('April Target')
ytd = fields.Float('YTD', compute='_compute_ytd')
#api.multi
#api.depends('feb_target', 'apr_target')
def _compute_ytd(self):
for record in self:
record.ytd = record.feb_target + record.apr_target
I have extended the product.template with following fields:
length = fields.Integer("Length", default=0)
length_float = fields.Float("Float", default=0.0)
Additionally I have extended the product.packaging model with this fields and an onchange method:
product_id_ref = fields.Many2one('product.product', string="Product Reference")
length = fields.Integer('Length')
length_float = fields.Float('Length_Float')
#api.onchange("product_id_ref")
def _onchange_product(self):
if self.product_id_ref:
self.length_float = self.product_id_ref.length_float
self.length = self.product_id_ref.length
Interestingly the FLOAT field length_float is changed as expected and shown in the view. The INTEGER field is not changed.
Something more suprising is that if I change the order of the onchange method
#api.onchange("product_id_ref")
def _onchange_product(self):
if self.product_id_ref:
self.length = self.product_id_ref.length
self.length_float = self.product_id_ref.length_float
NO value is changed!
How could that be?? Does anyone have an idea?
Thanks!
It came out that the problem was the 'length' field itself. This name leads to problems on the javascript side. Renaming leads to the desired result.
I'm inherit purchase.order.line and try change value in field. For product_qty I can change value but for price_unit I can't change value.
My custom .py file:
class PurchaseOrderLine(models.Model):
_inherit = 'purchase.order.line'
#api.onchange('product_id')
def my_fucn(self):
for rec in self:
rec.product_qty = 10 #WORKING
rec.price_unit = 1 #NOT WORKING
Maybe is problem because in original purcahase.py odoo file also have #api.onchange('product_id').
Any solution?
You can't predict which onchange method will be triggered first or last, but the original onchange method for product_id changes in purchase.order.line is setting the price_unit field, but not the product_qty field.
So it seems your method is called before the other one, because price_unit is overwritten. You can check that by debugging both methods.
What to do now? I would prefer the extension of the original method:
#api.onchange('product_id')
def the_original_method(self):
res = super(PurchaseOrderLine, self).the_original_method()
# your logic here
return res
In your case a product_qty change will trigger another onchange event. Always have in mind, that field changes can trigger onchange events and field recomputations.
Try to extend both methods:
#api.onchange('product_id')
def onchange_product_id(self):
res = super(PurchaseOrderLine, self).onchange_product_id()
# your logic here
for rec in self:
rec.product_qty = 10 # will trigger _onchange_quantity() on return
return res
#api.onchange('product_qty', 'product_uom')
def _onchange_quantity(self):
res = super(PurchaseOrderLine, self)._onchange_quantity()
# your logic here
for rec in self:
rec.price_unit = 1.0
return res
I create a custom field in account.invoice.line .
I added the field in account.invoice.tax
I override the prepare invoice function like this
cost_center_id is Many2one field
def _prepare_tax_line_vals(self, line, tax):
res = super(AccountInvoice, self)._prepare_tax_line_vals(line, tax)
if not res.get('cost_center_id') and line.cost_center_id:
res['cost_center_id'] = line.cost_center_id.id
return res
I print the cost_center values here the value is printed here.
But in account.invoice.tax the values is not there.
How to solve this issue??
I added the part number field in product template model
partnumber = fields.Char(
'Part Number', compute='_compute_partnumber',
inverse='_set_partnumber', store=True)
I write the function like internal reference code
#api.depends('product_variant_ids', 'product_variant_ids.partnumber')
def _compute_partnumber(self):
unique_variants = self.filtered(lambda template: len(template.product_variant_ids) == 1)
for template in unique_variants:
template.partnumber = template.product_variant_ids.partnumber
for template in (self - unique_variants):
template.partnumber = ''
#api.one
def _set_partnumber(self):
if len(self.product_variant_ids) == 1:
self.product_variant_ids.partnumber = self.partnumber
I successfully added part number in product form.I used above methods for name get(to get part number in product description)
My problem is the part number could not saved in create method.
the field only saved in edit mode.
As "dccdany" already said in his comment, the creation order is a bit tricky on templates. You can see it in the code. First the template will be created. The partnumber won't be set, because there is no variant existing at that point.
After template creation, the variants will be created (one line later) without partnumber, so there will be no partnumber after template creation.
What can you do? Just overwrite product.template create(), like:
#api.model
def create(self, vals):
template = super(ProductTemplate, self).create(vals)
if 'partnumber' in vals and len(template.product_varient_ids) == 1:
template.partnumber = vals.get('partnumber')
return template