calculate new price_unit in sale order line - odoo

I have created a new custom module to include width and lenght of a product as attributes with custom values, and I need to update the price_unit of the sales order line with the current unit price multiplied by the (lenght*witdh) value, so I can have the price per surface unit in the product card, and the price per total surface in the sales order line.
I use the product configurator and this is my code:
from odoo import models, fields, api
# import pymsgbox
class aurea_calculated_field_line(models.Model):
_inherit = 'sale.order.line'
field_superficie = fields.Float('Superficie')
field_alto = fields.Integer('Alto')
field_ancho = fields.Integer('Ancho')
#api.onchange('field_alto', 'field_ancho', 'product_uom_qty', 'quantity')
def _value_pc5(self):
for record in self:
record.field_superficie = record.field_ancho * record.field_alto
self.price_unit = float(self.field_superficie) * self.product_id.lst_price
#api.onchange('product_id')
def _value_pc4(self):
if not self.product_custom_attribute_value_ids and not self.product_no_variant_attribute_value_ids:
return ""
for pacv in self.product_custom_attribute_value_ids:
if pacv.custom_product_template_attribute_value_id.display_name == 'Largo: Largo':
self.field_alto = pacv.custom_value
if pacv.custom_product_template_attribute_value_id.display_name == 'Ancho: Ancho':
self.field_ancho = pacv.custom_value
It works fine, but the problem is when I change the product quantity the unit price is reset to the product pricelist price.
Any suggestions?
Thanks in advance

I looked at this a bit. I didn't reproduce the problem but here is something you probably can work with.
In Odoo13 source code in file addons/sale/models/sale.py on line 1614 is a method which causes behavior you have problem with:
#api.onchange('product_uom', 'product_uom_qty')
def product_uom_change(self):
if not self.product_uom or not self.product_id:
self.price_unit = 0.0
return
if self.order_id.pricelist_id and self.order_id.partner_id:
product = self.product_id.with_context(
lang=self.order_id.partner_id.lang,
partner=self.order_id.partner_id,
quantity=self.product_uom_qty,
date=self.order_id.date_order,
pricelist=self.order_id.pricelist_id.id,
uom=self.product_uom.id,
fiscal_position=self.env.context.get('fiscal_position')
)
self.price_unit = self.env['account.tax']._fix_tax_included_price_company(self._get_display_price(product), product.taxes_id, self.tax_id, self.company_id)
This re-calculates unit price when product quantity is changed. You'd have to overwrite this method in your code. Easiest way would be add this to your aurea_calculated_field_line-class.
def product_uom_change(self):
return
But this needs a lot of testing to make sure that some other feature does not break because of this.

Related

copying field custom from purchase order line to stock move in odoo

I am using odoo 13. I have a custom field weight in Purchase order line.
I want to copying the value of this field to custom field in stock move.
I know that to transfer the value of the field from sale order to stock move I can do it in the following way.
class StockMoveLine(models.Model):
_inherit = 'stock.move'
weight = fields.Float(
compute='_compute_weight' )
def _compute_weight(self):
for move in self:
if not (move.picking_id and move.picking_id.group_id):
continue
picking = move.picking_id
sale_order = self.env['sale.order'].sudo().search([
('procurement_group_id', '=', picking.group_id.id)], limit=1)
# print(picking)
if sale_order:
for line in sale_order.order_line:
if line.product_id.id != move.product_id.id:
continue
move.update({
'weight': line.weight,
})
continue
else:
# move.update({
# 'weight': move.weight,
# })
However I find myself stuck in the else to pass the field from purchase to stock move
You can use the purchase_line_id field on stock.move which is link to purchase.order.line
Code - PoL Reference in Stock Move
If you're inheriting stock.move, then change your model name to class StockMove(models.Model): instead of class StockMoveLine(models.Model):.
Try using #api.depends on your compute function.

xero sdk: line item unit price rounding to 2 decimal place

I have posted invoice in xero & passing data in 4 decimal points of unit price but xero is converting it into 2 decimal points, so i am getting total amount issue due to rounding...
Through API I know unitdp=4 have to pass but how to do same thing with sdks?
LineItem qboln = new LineItem();
qboln.Description = "Desc"
qboln.Quantity = 3385;
qboln.UnitAmount = 0.7550;
qboln.AccountCode = code;
qboln.TaxType = "INPUT";
qboln.TaxAmount = 0.678;
inv.LineItems.Add(qboln);
so here xero is rounding unit price into 0.76 so I am getting total amount issue that is different with my original invoice.
Please tell me how to solve it ?

How to get computed field value in search orm in odoo

I have defined a computed field with compute method in odoo 10 and now i want to get its value in search orm but its value remain False, and when I tried store=True its value not being changed.
if anyone has solution please let me know, I'll highly thankful.
My code is:
balance_amount = fields.Float(string="Balance Amount", compute='_compute_loan_amount')
#api.one
def _compute_loan_amount(self):
total_paid = 0.0
for loan in self:
for line in loan.loan_lines:
if line.paid:
total_paid += line.amount
balance_amount = loan.loan_amount - total_paid
self.total_amount = loan.loan_amount
self.balance_amount = balance_amount
self.total_paid_amount = total_paid
when i use search_countbelow:
loan_count = self.env['hr.loan'].search_count([('employee_id', '=', values['employee_id']), ('state', '=', 'approve'),
('balance_amount', '!=', 0)])
it always get count value even balance_amount equals to Zero
There are some things you have to do here.
Define recomputation dependencies and either use #api.multi and a for loop over self or use api.one and skip a for loop. If i understand your compute methode correct:
#api.multi
#api.depends('loan_lines.paid', 'loan_lines.amount', 'loan_amount')
def _compute_loan_amount(self):
for loan in self:
total_paid = 0.0
for line in loan.loan_lines:
if line.paid:
total_paid += line.amount
balance_amount = loan.loan_amount - total_paid
loan.total_amount = loan.loan_amount # ???
loan.balance_amount = balance_amount
loan.total_paid_amount = total_paid
Try to use a float rounding with e.g. 2 decimals, because floats can produce values like 0.000000000000000002 and that would break your search.
You either have to store the value or have to define a search method. Second approach is more difficult (in my experience).

Is it possible to compute many2many field values without storing them?

I want to create a virtual Many2many field for informational purpose only. Is it possible to compute and populate Many2many field without storing the generated virtual records?
Yes, It is possible to create Virtual Many2many field for informational purpose. Please see the below sample code,
#api.one
#api.depends(
'move_id.line_id.account_id',
'move_id.line_id.reconcile_id.line_id',
'move_id.line_id.reconcile_partial_id.line_partial_ids',
)
def _compute_move_lines(self):
# Give Journal Items related to the payment reconciled to this invoice.
# Return partial and total payments related to the selected invoice.
self.move_lines = self.env['account.move.line']
if not self.move_id:
return
data_lines = self.move_id.line_id.filtered(lambda l: l.account_id == self.account_id)
partial_lines = self.env['account.move.line']
for data_line in data_lines:
if data_line.reconcile_id:
lines = data_line.reconcile_id.line_id
elif data_line.reconcile_partial_id:
lines = data_line.reconcile_partial_id.line_partial_ids
else:
lines = self.env['account.move.line']
partial_lines += data_line
self.move_lines = lines - partial_lines
move_lines = fields.Many2many('account.move.line', string='Entry Lines',
compute='_compute_move_lines')
You can see above example in /addons/account/account_invoice.py file in the odoo addons.

View helper to sum line item amounts

I have a view helper that totals the items inside line items. Each order can have many line items. Each line item has different sizes inside it (the fields). For this below I'm curious how to sum up a certain field for multiple line items.
def total_items(order)
xxs = order.lineitems.xxs.sum
return xxs
end
This is what I have but doesn't work when there are multiple line items for an order, how can I properly write it?
It is not very obvious what you are asking, but I think what you want is something like this:
def total_items(order)
order.lineitems.inject(0) { |total, line_item| total + line_item.xxs }
end
What this method does, is similar to this:
def total_items(order)
total = 0;
order.lineitems.each do |line_item|
total += line_item.xxs
end
total
end
By the way, in Ruby the return keyword is optional.