Calling onchange method on product from values - odoo

I created invoice already and now I want to create invoice lines. but first, I want to call _onchange_product_id() method on the product that I'm adding to account_inv_line that I would receive all values from that product. how can I do this? onchange_inv_line_fields always returns None
for key, value in csv_info.iteritems():
account_invoice = {
'partner_id': value['partner_id'],
'number': value['number'],
'date_invoice': value['date_invoice'],
}
invocie = acc_inv_obj.with_context(type='in_invoice').create(account_invoice)
for value_line in csv_info[key]['invoice_line']:
account_inv_line = {
'product_id': value_line['product_id'],
'price_unit': value_line['price_unit'],
'quantity': value_line['quantity'],
}
inv_line = self.env['account.invoice.line'].create(account_inv_line)
onchange_inv_line_fields = inv_line._onchange_product_id()

To call onchange method we need to create temp_lines like this:
temp_line = self.env['account.invoice.line'].new(account_inv_line)
temp_line._onchange_product_id()
account_inv_line.update(temp_line._convert_to_write(temp_line._cache))
invocie.invoice_line_ids.create(account_inv_line)

Related

How to get a product's multiple locations in odoo?

I want to get a product's location and display it on a custom report table:
and on the "Warehouse" cell it should be all the product's location, so if that product has multiple it should be displayed there. Just for clarification this is the location I'm talking about:
In order to put that there I tried this code:
class StockInventoryValuationReport(models.TransientModel):
_name = 'report.stock.inventory.valuation.report'
_description = 'Stock Inventory Valuation Report'
location_id = fields.Many2one('stock.location')
# filter domain wizard
#api.multi
def _compute_results(self):
self.ensure_one()
stockquant_obj = self.env['stock.quant'].search([("location_id", "=", self.location_id.id)])
print(stockquant_obj.location_id)
line = {
'name': product.name,
'reference': product.default_code,
'barcode': product.barcode,
'qty_at_date': product.qty_at_date,
'uom_id': product.uom_id,
'currency_id': product.currency_id,
'cost_currency_id': product.cost_currency_id,
'standard_price': standard_price,
'stock_value': product.qty_at_date * standard_price,
'cost_method': product.cost_method,
'taxes_id': product.taxes_id,
'location_id': stockquant_obj.location_id,
}
if product.qty_at_date != 0:
self.results += ReportLine.new(line)
but when I'm printing stockquant_obj.location_id it is an empty recordset basically its not finding any locations. Can someone please hint me on anything?
I actually managed to get the product's locations using this code:
class StockInventoryValuationReport(models.TransientModel):
_name = 'report.stock.inventory.valuation.report'
_description = 'Stock Inventory Valuation Report'
location_id = fields.Many2one('stock.location')
# filter domain wizard
#api.multi
def _compute_results(self):
self.ensure_one()
stockquant_obj = self.env['stock.quant'].search([("location_id", "=", self.location_id.id)])
for xyz in stockquant_obj:
line = {
'name': product.name,
'reference': product.default_code,
'barcode': product.barcode,
'qty_at_date': product.qty_at_date,
'uom_id': product.uom_id,
'currency_id': product.currency_id,
'cost_currency_id': product.cost_currency_id,
'standard_price': standard_price,
'stock_value': product.qty_at_date * standard_price,
'cost_method': product.cost_method,
'taxes_id': product.taxes_id,
'location_id': xyz.location_id,
}
if product.qty_at_date != 0:
self.results += ReportLine.new(line)
I debugged further discovering that now stock.quant() could get some record-set but odoo was expecting a singleton when on my old code was stockquant_obj.location_id so since I have seen from other people that the solution to singleton is a for loop and for that reason I added it.
The problem with this is that now not only the warehouse would be added but the same product would repeat as times as long the recordset is. How can I dodge this? How to tell python that I only need to loop through stockquant_obj and xyz should be inside the line variable?

Add values on One2many field onchange

I'm trying to add values in my one2many field onchange.
I tried using the [(0,0, {values})] but nothing happened. Any idea on how to implement it?
custom_line_ids = fields.One2many('mrp.production', 'product_id', 'Custom Line')
#api.onchange('product_id')
def add_custom_line_ids(self):
mrp = self.env['mrp.productions'].search([])
result = []
vals = {
'sequence': self.sequence,
'name': self.name,
'product_id': self.product_id,
'date_planned_start': self.date_planned_start,
'state': self.state,
}
self.update({'custom_line_ids':[(0, 0, vals)]})
Actually you are using update method, which only update the model's value but not yet stored on database. You should use write method instead.
You need to return the value in onchange. This would work:
custom_line_ids = fields.One2many('mrp.production', 'product_id', 'Custom Line')
#api.onchange('product_id')
def add_custom_line_ids(self):
vals = {}
mrp_ids = self.env['mrp.productions'].search([])
if mrp_ids:
for mrp in mrp_ids:
vals['custom_line_ids']=[(0,0,{
'date': mrp.date,
})]
return {'value': vals}

How to creat records in odoo tree view onclick button?

please help
I need when I click Enregistrer Button to create those fields in the tree view on the bottom
for this example, I have quantity equal 12 so I need 12 lines to be created on the tree view with the values on the wizard view
the wizard code :
class LinesWizard(models.Model):
_name = 'bons.wizard'
w_contrat_name = fields.Many2one('contrat.contrat', string='Contrat')
w_contrat_line = fields.Many2one('contrat.lignes', string='Ligne contrat')
w_product_name = fields.Many2one('product.product', string='Produit')
w_po_number = fields.Char(string='Numero PO')
w_qtt = fields.Float('quantite', related='w_contrat_line.quantity')
w_prix = fields.Float(string='Prix unitaire', related='w_contrat_line.unit_price')
#api.onchange('w_contrat_name')
def on_change_contrat_name(self):
if self.w_contrat_name:
self.w_contrat_line = False
return {'domain': {'w_contrat_line' : [('ligne_ids', '=', self.w_contrat_name.id)]}}
else:
return {'domain': {'w_contrat_line': []}}
In your function for the Enregistrer button, you can use below code to get the active sale.order ID.
session_id = self.env['sale.order'].browse(self._context.get('active_id'))
Then in the same function, simply create and add your rows.
session_id.write({
'your_tree_ids': [(0, False,
{
'w_contrat_name': self.w_contrat_name,
'w_product_name': self.w_product_name,
'etc': 'etc...'}
)] * int(self.w_qtt) # assuming rows to be added are the same, create a list of w_qtt quantity of (0, _, values), since your qty is a float, need to convert to int first
})

How to display external information on Odoo 11?

I'm working on Weather application using Odoo11, I have a Python script that fetches weather information from this API: https://openweathermap.org/api
The script works fine but I have no idea how to integrate it with Odoo.
Can you give guidelines about how to achieve this, for example how to show this information in a form view, tree or Kanban?
Any example will be very helpful for me.
If you only want to show some text that´s always updated you can use a computed field
from odoo import api
weather = fields.Text( # this can be an image or any other field type
string='Weather',
compute='_compute_weather'
)
#api.depends() # leave this empty, so this is executed always when the view with this field is loaded
def _compute_weather(self):
for record in self:
# retrieve the weather information here
record.weather = weather_information # assign the weather information to the variable
Show it in a form view as any other field
<field name="weather" />
Note: If you want to store the information on the database you can just create a button or a atomate task, for instance, to store or update the values in the fields (without compute method).
Note2: Check the source code of the user_weather_map module from Cybrosis, it may be helpful
You can use the module User Weather Notification.
This module uses external API.
def get_weather(self, user_id):
rec = self.env['user.weather.map.config'].search([('user_id', '=', user_id)], limit=1)
if rec:
weather_path = 'http://api.openweathermap.org/data/2.5/weather?'
if rec.u_longitude and rec.u_latitude:
params = urllib.urlencode(
{'lat': rec.u_latitude, 'lon': rec.u_longitude, 'APPID': rec.appid})
elif rec.city:
params = urllib.urlencode(
{'q': rec.city, 'APPID': rec.appid})
else:
return {
'issue': 'localization'
}
url = weather_path + params
try:
f = urllib.urlopen(url)
except Exception:
f = False
if f:
ret = f.read().decode('utf-8')
result = json.loads(ret)
if result:
if "cod" in result.keys():
if result['cod'] == 200:
city = False
city2 = False
if "name" in result.keys():
city = result['name']
if not city:
if rec.method == 'address':
city = rec.city
if rec.method == 'address':
city2 = rec.city
temp = pytemperature.k2c(result['main']['temp'])
min_temp = pytemperature.k2c(result['main']['temp_min'])
max_temp = pytemperature.k2c(result['main']['temp_max'])
weather_rec = self.search([('user_id', '=', rec.user_id.id)])
now_utc = datetime.now(timezone('UTC'))
user_list = self.env['res.users'].search([('id', '=', user_id)])
if user_list.partner_id.tz:
tz = pytz.timezone(user_list.partner_id.tz)
now_pacific = now_utc.astimezone(timezone(str(tz)))
current_time = now_pacific.strftime('%d %B %Y, %I:%M%p')
vals = {
'date_weather_update': current_time,
'name': city,
'city': city2,
'user_id': user_id,
'weather': result['weather'][0]['main'],
'description': result['weather'][0]['description'],
'temp': temp,
'pressure': result['main']['pressure'],
'humidity': result['main']['humidity'],
'min_temp': min_temp,
'max_temp': max_temp,
}
if weather_rec:
weather_rec.write(vals)
return {
'issue': ''
}
else:
weather_rec.create(vals)
return {
'issue': ''
}
else:
return {
'issue': 'timezone'
}
else:
return {
'issue': 'localization'
}
else:
return {
'issue': 'bad_request'
}
else:
return {
'issue': 'internet'
}
else:
return {
'issue': 'config'
}
This is the code that I use in that module. you can just convert it into odoo11.
Thank you.

Odoo: Two selection fields, second selection depends on the first selected value

I have a model with two selection fields. In the first selection field the user chooses a project, and in second the user chooses a tranche, depends on the selected first field. (for one project, we have many tranche)
I use this declaration to my function:
#api.multi
#api.onchange('project')
def _get_tranche(self):
print res
return res`
If I'll print in console the result of returned value is correct, and I have exactly what I search, but in the view, the second field value does not displays computed values to choose after setting the second field value.
Is there any method to make it work properly?
This is my code:
#api.model
def _get_project(self):
values = {'$top' : 100,
'$filter' : "'name==:1&&parent==null'",
'$params' : '\'["*"]\'' }
response = requests.get('http://localhost:8081/rest/Project/name',
auth=('admin', 'admin'),
params=values)
data = response.json()
res = []
for record in data['__ENTITIES']:
res.append((record['__KEY'], record['name']))
return res
#property
def ret_value(self):
return self.project
#api.multi
#api.onchange('project')
def _get_tranche(self):
if self.ret_value == False:
return []
values = {'$top' : 100,
'$filter' : "'parent.ID==:1'",
'$params' : '\'[' + self.ret_value + ']\'' }
response = requests.get('http://localhost:8081/rest/Project/name',
auth=('admin', 'admin'),
params=values)
data = response.json()
res = []
for record in data['__ENTITIES']:
res.append((record['__KEY'], record['name']))
print res
return res
_columns = {
'name': fields.char("Name", required=True),
'description' : fields.text(),
'project' :fields.selection(selection=_get_project, string="Project"),
'tranche' : fields.selection(selection=_get_tranche, string="Tranche"),
}
NB: a tranche is a project with parent_id (not null) = id of a project, I need do the following: when I select a project X from the first field selection "project", I can select the tranches of this project (project with parent_id=X) from the second field selection "tranche" what I can't understand is the result of print in the console is correct, but in the view the field tranche is empty??!!
Now I am trying this:
_columns = {
'name': fields.char("Name", required=True),
'description' : fields.text(),
'project' :fields.selection(selection=_get_project, string="Project"),
'tranche' : fields.selection(selection=_get_tranche,
string="Tranche", compute='_return_tranche'),
}
#api.depends('project')
def _return_tranche(self):
if self.ret_value == False:
self.tranche = []
return
values = {'$top' : 100,
'$filter' : "'parent.ID==:1'",
'$params' : '\'[' + self.ret_value + ']\'' }
response = requests.get('http://localhost:8081/rest/Project/name',
auth=('admin', 'admin'),
params=values)
data = response.json()
res = []
for record in data['__ENTITIES']:
res.append((str(record['__KEY']),str(record['name'])))
print res
self.tranche = res
return
#api.model
def _get_tranche(self):
values = {'$top' : 100,
'$filter' : "'name==:1&&parent!=null'",
'$params' : '\'["*"]\'' }
response = requests.get('http://localhost:8081/rest/Project/name',
auth=('admin', 'admin'),
params=values)
data = response.json()
res = []
for record in data['__ENTITIES']:
res.append((record['__KEY'], record['name']))
return res
But I get this error
File "/opt/odoo/odoo/openerp/fields.py", line 1529, in convert_to_cache
raise ValueError("Wrong value for %s: %r" % (self, value))
ValueError: Wrong value for crm.lead.tranche: [('6', 'Tranche I'), ('7', 'Tranche II'), ('8', 'Tranche III')]
Help me please...