How to get computed field value in search orm in odoo - 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).

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.

calculate new price_unit in sale order line

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.

Conditional If Statement: If value in row starts with letter in string … set another column with some corresponding value

I have the 'Field_Type' column filled with strings and I want to derive the values in the 'Units' column using an if statement.
So Units shows the desired result. Essentially I want to call out what type of activity is occurring.
I tried to do this using my code below but it won't run (please see screen shot below for error). Any help is greatly appreciated!
create_table['Units'] = pd.np.where(create_table['Field_Name'].str.startswith("W"), "MW",
pd.np.where(create_table['Field_Name'].str.contains("R"), "MVar",
pd.np.where(create_table['Field_Name'].str.contains("V"), "Per Unit")))```
ValueError: either both or neither of x and y should be given
You can write a function to define your conditionals, then use apply on the dataframe and pass the funtion
def unit_mapper(row):
if row['Field_Type'].startswith('W'):
return 'MW'
elif 'R' in row['Field_Type']:
return 'MVar'
elif 'V' in row['Field_Type']:
return 'Per Unit'
else:
return 'N/A'
And then
create_table['Units'] = create_table.apply(unit_mapper, axis=1)
In your text you talk about Field_Type but you are using Field_Name in your example. Which one is good ?
You want to do something like:
create_table[create_table['Field_Type'].str.startwith('W'), 'Units'] = 'MW'
create_table[create_table['Field_Type'].str.startwith('R'), 'Units'] = 'MVar'
create_table[create_table['Field_Type'].str.startwith('V'), 'Units'] = 'Per Unit'

How to auto fill a field by previous record value?

In my customized module,there is a field called closing_balance of type float.closing balance is calculated by total_credit - total_debit.I want to auto fill the field opening_balance of type float by the value of closing_balance when that particular employee creating next record.
You need to override default_get method of that object.
def default_get(self, cr, uid, fields, context=None):
if context is None:
context = {}
res = super(hr_expense_expense, self).default_get(cr, uid, fields, context=context)
#here is your logic
opening_balance = 111 #do calculation as per your requirements
#update opening balance field
res.update({'openning_balance_field_name': opening_balance})
return res

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.