I've migrated a module which can create stock.inventory movements, by uploading csv's.
It's functioning quite good, but sometimes, when I upload certain csv's, it throws me this error:
Odoo
Odoo Server Error
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 648, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 685, in dispatch
result = self._call_function(**self.params)
File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 321, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/openerp/service/model.py", line 118, in wrapper
return f(dbname, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 314, in checked_call
result = self.endpoint(*a, **kw)
File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 964, in __call__
return self.method(*args, **kw)
File "/usr/lib/python2.7/dist-packages/openerp/http.py", line 514, in response_wrap
response = f(*args, **kw)
File "/usr/lib/python2.7/dist-packages/openerp/addons/web/controllers/main.py", line 892, in call_button
action = self._call_kw(model, method, args, {})
File "/usr/lib/python2.7/dist-packages/openerp/addons/web/controllers/main.py", line 880, in _call_kw
return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/openerp/api.py", line 250, in wrapper
return old_api(self, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/openerp/api.py", line 421, in old_api
result = new_api(recs, *args, **kwargs)
File "/usr/lib/python2.7/dist-packages/openerp/api.py", line 425, in new_api
result = [method(rec, *args, **kwargs) for rec in self]
File "/usr/lib/python2.7/dist-packages/openerp/custom_addons/stock_inventory_import/wizard/import_inventory.py", line 85, in action_import
val['location_id'] = prod_location.id
AttributeError: 'int' object has no attribute 'id'
The code is this:
#api.one
def action_import(self):
"""Load Inventory data from the CSV file."""
ctx = self._context
stloc_obj = self.env['stock.location']
inventory_obj = self.env['stock.inventory']
inv_imporline_obj = self.env['stock.inventory.import.line']
product_obj = self.env['product.product']
if 'active_id' in ctx:
inventory = inventory_obj.browse(ctx['active_id'])
if not self.data:
raise exceptions.Warning(_("You need to select a file!"))
# Decode the file data
data = base64.b64decode(self.data)
file_input = cStringIO.StringIO(data)
file_input.seek(0)
location = self.location
reader_info = []
if self.delimeter:
delimeter = str(self.delimeter)
else:
delimeter = ','
reader = csv.reader(file_input, delimiter=delimeter,
lineterminator='\r\n')
try:
reader_info.extend(reader)
except Exception:
raise exceptions.Warning(_("Not a valid file!"))
keys = reader_info[0]
# check if keys exist
if not isinstance(keys, list) or ('code' not in keys or
'quantity' not in keys):
raise exceptions.Warning(
_("Not 'code' or 'quantity' keys found"))
del reader_info[0]
values = {}
actual_date = fields.Date.today()
inv_name = self.name + ' - ' + actual_date
inventory.write({'name': inv_name,
'date': fields.Datetime.now(),
'imported': True, 'state': 'confirm'})
for i in range(len(reader_info)):
val = {}
field = reader_info[i]
values = dict(zip(keys, field))
prod_location = location.id
if 'location' in values and values['location']:
locat_lst = stloc_obj.search([('name', '=',
values['location'])])
if locat_lst:
prod_location = locat_lst[0]
prod_lst = product_obj.search([('default_code', '=',
values['code'])])
if prod_lst:
val['product'] = prod_lst[0].id
if 'lot' in values and values['lot']:
val['lot'] = values['lot']
val['code'] = values['code']
val['quantity'] = values['quantity']
val['location_id'] = prod_location.id
val['inventory_id'] = inventory.id
val['fail'] = True
val['fail_reason'] = _('No processed')
inv_imporline_obj.create(val)
And the csv's look like this:
id product_id reference code combinacion avanzadastock location quantity qty
2780 Piloto trasero Recambio Ecológico Original M0002780 gsx 600 f 600 1988-1991/4316/A8I 1
This error appears from time to time, often it just works without problems, but some other times throws this error.
It is exactly on location column.
I have csv's with more than 5k items, so it's difficult for me to track the error.
Is this csv related? Or it is a matter of code?
Issue is your logic
prod_location = location.id
Then the following if statement is never entered, and you move to
val['location_id'] = prod_location.id
And the error is thrown
Yes correct. Some location don't exist on the system. That's it throws error. To avoid such error, you can use following trick.
prod_location = self.location and self.location.id or False
Means if system has location then prod_location variable set value with id of location otherwise False
NOTE:
In model declaration, location_id field set with required=False otherwise you can not create record with location_id=False It will give you integrity error.
Actually the problem was the csv content
Because some locations don't exist on the system, then it throws out that error.
So, need to check for locations that do exist before continuing with the process.
Thank You.
Related
I'm inheriting res.partner model, this is a migration from v8 to v10 community.
The offending methods look like this:
#api.depends('company_id')
def _get_country_code(self):
"""
Return the country code of the user company. If not exists, return XX.
"""
#context = dict(self._context or {})
for partner in self:
user_company = self.env['res.company'].browse(self.company_id)
#NOTE: replace code name with your real field name where you want to see value
partner.code = user_company.partner_id and user_company.partner_id.country_id \
and user_company.partner_id.country_id.code or 'XX'
#api.multi
def _get_uid_country(self):
""" Return a dictionary of key ids as invoices, and value the country code
of the user company.
"""
res = {}.fromkeys(self._get_country_code())
return res
Now very time I click on a client, or supplier (res.partner), it throws me this:
Traceback (most recent call last):
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 638, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 675, in dispatch
result = self._call_function(**self.params)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 331, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/service/model.py", line 119, in wrapper
return f(dbname, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 324, in checked_call
result = self.endpoint(*a, **kw)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 933, in __call__
return self.method(*args, **kw)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 504, in response_wrap
response = f(*args, **kw)
File "/home/kristian/odoov10/odoo-10.0rc1c-20161005/odoo/addons/web/controllers/main.py", line 862, in call_kw
return self._call_kw(model, method, args, kwargs)
File "/home/kristian/odoov10/odoo-10.0rc1c-20161005/odoo/addons/web/controllers/main.py", line 854, in _call_kw
return call_kw(request.env[model], method, args, kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/api.py", line 681, in call_kw
return call_kw_multi(method, model, args, kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/api.py", line 672, in call_kw_multi
result = method(recs, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/models.py", line 2995, in read
values[name] = field.convert_to_read(record[name], record, use_name_get)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/models.py", line 5171, in __getitem__
return self._fields[key].__get__(self, type(self))
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 860, in __get__
self.determine_value(record)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 969, in determine_value
self.compute_value(recs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 924, in compute_value
self._compute_value(records)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 916, in _compute_value
getattr(records, self.compute)()
File "/home/kristian/odoov10/gilda/l10n_ve_fiscal_requirements/model/partner.py", line 90, in _get_uid_country
res = {}.fromkeys(self._get_country_code()) #ids, cr, uid, context=context)
File "/home/kristian/odoov10/gilda/l10n_ve_fiscal_requirements/model/partner.py", line 68, in _get_country_code
user_company = self.env['res.company'].browse(self.company_id)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 854, in __get__
record.ensure_one()
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/models.py", line 4783, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.partner(1, 33, 8, 18, 22, 23)
I think it has to do with this line user_company = self.env['res.company'].browse(self.company_id) but I'm not 100% sure.
Any ideas?
EDIT
Old API original methods:
def _get_country_code(self, cr, uid, context=None):
"""
Return the country code of the user company. If not exists, return XX.
"""
context = context or {}
user_company = self.pool.get('res.users').browse(
cr, uid, uid, context=context).company_id
return user_company.partner_id and user_company.partner_id.country_id \
and user_company.partner_id.country_id.code or 'XX'
def _get_uid_country(self, cr, uid, ids, field_name, args, context=None):
""" Return a dictionary of key ids as invoices, and value the country code
of the user company.
"""
context = context or {}
res = {}.fromkeys(ids, self._get_country_code(cr, uid,
context=context))
return res
I've tried to shorten it a bit:
uid_country = fields.Char(
string="Country Code of Current User",
compute="_get_uid_country")
#api.multi
#api.depends('company_id') # there should be a better trigger field
def _get_uid_country(self):
""" Compute country code by current users company """
country_code = self.env.user.company_id.partner_id.country_id.code or 'XX'
for partner in self:
partner.update({'uid_country': country_code})
This should be enough. Seems to me, that there is no real trigger field and the computed field will be computed every time a partner is called. But it should work.
You can try replacing this line:
user_company = self.env['res.company'].browse(self.company_id)
with this
user_company = self.env['res.company'].browse(partner.company_id)
and then let us know
When you use #api.multi self is a RecordSet :
RecordSet can have 0 or 1 or more records when you use self.getSomeThing this works if the RecordSet have one record, but if it have more than one an exception is raised because it will not know witch record you want to ask.
so if you use #api.multi try to always to loop the recordSet.
#api.depends is also like #api.multi the self is a RecordSet.
for rec in self :
rec.getSomeThing
or use #api.one here the self is always one Record but is not recommanded because it call the getSomeThing according to the number of records in your view, so for form view it's not a problem because it has only one but for tree view you can imagine.
You should try the _get_uid_country function as:
for record in self.browse():
result = {}.fromkeys(record._get_country_code(), False)
I have this method:
#api.multi
def new_open_window(self, list_ids, xml_id, module):
""" Generate new window at view form or tree
"""
mod_obj = self.env['ir.model.data']
act_obj = self.env['ir.actions.act_window']
result = mod_obj._get_id(module, xml_id)
imd_id = mod_obj.browse(result)['res_id']
result = act_obj.browse(imd_id)
result['res_id']
return result
Right now, I click on a button which call this function like this return self.new_open_window([inv_id], 'action_invoice_tree1', 'account') the complete method looks like this:
#api.multi
def create_invoice(self):
""" Create a invoice refund
"""
#context = context or {}
wizard_brw = self.browse()
inv_id = self._context.get('active_id')
for wizard in wizard_brw:
if not wizard.sure:
raise UserError(
_("Validation error!"),
_("Please confirm that you know what you're doing by"
" checking the option bellow!"))
if (wizard.invoice_id and wizard.invoice_id.company_id.jour_id and
wizard.invoice_id and wizard.invoice_id.company_id.acc_id):
inv_id = self.action_invoice_create(wizard,
wizard.invoice_id)
else:
raise UserError(
_('Validation error!'),
_("You must go to the company form and configure a journal"
" and an account for damaged invoices"))
return self.new_open_window([inv_id], 'action_invoice_tree1', 'account')
But it doesn't loads anything, before the method new_open_window looked like this:
#api.multi
def new_open_window(self, list_ids, xml_id, module): #cr, uid, ids, list_ids, xml_id, module, context=None
""" Generate new window at view form or tree
"""
mod_obj = self.env['ir.model.data']
act_obj = self.env['ir.actions.act_window']
result = mod_obj._get_id(module, xml_id) #cr, uid was first
imd_id = mod_obj.browse(result)['res_id']#['res_id'] #cr, uid were first was read() before #(result, ['res_id'])
result = act_obj.browse(imd_id) # cr, uid were first was read() before
result['res_id'] = list_ids
return result
But list_ids was throwing me this:
Traceback (most recent call last):
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 638, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 675, in dispatch
result = self._call_function(**self.params)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 331, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/service/model.py", line 119, in wrapper
return f(dbname, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 324, in checked_call
result = self.endpoint(*a, **kw)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 933, in __call__
return self.method(*args, **kw)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 504, in response_wrap
response = f(*args, **kw)
File "/home/kristian/odoov10/odoo-10.0rc1c-20161005/odoo/addons/web/controllers/main.py", line 866, in call_button
action = self._call_kw(model, method, args, {})
File "/home/kristian/odoov10/odoo-10.0rc1c-20161005/odoo/addons/web/controllers/main.py", line 854, in _call_kw
return call_kw(request.env[model], method, args, kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/api.py", line 681, in call_kw
return call_kw_multi(method, model, args, kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/api.py", line 672, in call_kw_multi
result = method(recs, *args, **kwargs)
File "/home/kristian/odoov10/gilda/l10n_ve_fiscal_requirements/wizard/wizard_invoice_nro_ctrl.py", line 139, in create_invoice
return self.new_open_window([inv_id], 'action_invoice_tree1', 'account')
File "/home/kristian/odoov10/gilda/l10n_ve_fiscal_requirements/wizard/wizard_invoice_nro_ctrl.py", line 114, in new_open_window
result['res_id'] = list_ids
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/models.py", line 5180, in __setitem__
return self._fields[key].__set__(self, value)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 878, in __set__
value = self.convert_to_cache(value, record)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/fields.py", line 1109, in convert_to_cache
return int(value or 0)
TypeError: int() argument must be a string or a number, not 'list'
The problem was this line result['res_id'] = list_ids , but now it doesn't throw any error but it doesn't work, it just stay on the same window and doesn't rewrite any invoice.
The method which creates the invoice which comes first before these two functions now looks like this:
#api.multi
def action_invoice_create(self, wizard_brw, inv_brw): #cr, uid, ids, wizard_brw, inv_brw, context=None
"""
If the invoice has control number, this function is responsible for
passing the bill to damaged paper
#param wizard_brw: nothing for now
#param inv_brw: damaged paper
"""
invoice_line_obj = self.env['account.invoice.line']
invoice_obj = self.env['account.invoice']
acc_mv_obj = self.env['account.move']
acc_mv_l_obj = self.env['account.move.line']
tax_obj = self.env['account.invoice.tax']
invoice = {}
if inv_brw.nro_ctrl:
invoice.update({
'name': 'PAPELANULADO_NRO_CTRL_%s' % (
inv_brw.nro_ctrl and inv_brw.nro_ctrl or ''),
'state': 'paid',
'tax_line': [],
})
else:
raise UserError(
_('Validation error!'),
_("You can run this process just if the invoice have Control"
" Number, please verify the invoice and try again."))
inv_brw.write(invoice)
inv_brw.invoice_line_ids.write({
'quantity' : 0.0,
'invoice_line_tax_id' : [],
'price_unit' : 0.0
})
taxes = self.env['account.tax'].search([])
invoice_taxes = tax_obj.search(
[('invoice_id', '=', inv_brw and inv_brw.id)]).unlink()
move = inv_brw.move_id
if move: #if move_id:
move.button_cancel()
move.ref = 'Damanged Paper'
move.line_ids.unlink()
return inv_brw.id
Any ideas?
EDIT
This is the original new_open_window method:
def new_open_window(self, cr, uid, ids, list_ids, xml_id, module,
context=None):
""" Generate new window at view form or tree
"""
mod_obj = self.pool.get('ir.model.data')
act_obj = self.pool.get('ir.actions.act_window')
result = mod_obj._get_id(cr, uid, module, xml_id)
imd_id = mod_obj.read(cr, uid, result, ['res_id'])['res_id']
result = act_obj.read(cr, uid, imd_id)
result['res_id'] = list_ids
return result
I would migrate the method like:
#api.multi
def new_open_window(list_ids, xml_id, module)
""" Generate new window at view form or tree """
action = self.env.ref("{}.{}".format(module, xml_id))
result = action.read()[0]
if isinstance(list_ids, (list, tuple)):
result['domain'] = [('id', 'in', list_ids)]
else:
result['res_id'] = list_ids
return result
ref will get the record of the action. read is a multi record method and will return a list of dictionaries. At the end i have added #Charif's interesting hint.
The problem is here :
result['res_id'] = list_ids
I think that res_id should be an integer not a list like you are giving, if you want to show it in form view only then you need to pass only one id in res_id. but if you want to pass more that record then use domain not res_id.
result['domain'] = [('id', 'in' , list_ids)]
this way only the records that muches the domain will be shown
res_id is used when you need to edit a record only one record if you want more use domain
I've inherited res.partner class, and I have these two methods:
jour_id = fields.Many2one('account.journal', string='Journal', required=False,
help="Default journal for damaged invoices")
acc_id = fields.Many2one('account.account', string='Account',
help="Default account used for invoices and lines from damaged invoices")
printer_fiscal = fields.Boolean(string='Manages fiscal printer',
help='Indicates that the company can operate a fiscal printer')
#api.model
def create(self, vals):
""" To create a new record,
adds a Boolean field to true
indicates that the partner is a company
"""
#if context is None:
#context = {}
ctx = self._context.copy()
ctx.update({'create_company': True})
return super(ResCompany, self).create(vals)
#api.model
def write(self, values):
""" To write a new record,
adds a Boolean field to true
indicates that the partner is a company
"""
#if context is None:
#context = {}
ctx = self._context.copy()
ctx.update({'create_company': True})
return super(ResCompany, self).write(values)
These two fields, are updated or created by these two functions create and write.
But when I try any of these, by editing the company, it throws me this:
Traceback (most recent call last):
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 638, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 675, in dispatch
result = self._call_function(**self.params)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 331, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/service/model.py", line 119, in wrapper
return f(dbname, *args, **kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 324, in checked_call
result = self.endpoint(*a, **kw)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 933, in __call__
return self.method(*args, **kw)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/http.py", line 504, in response_wrap
response = f(*args, **kw)
File "/home/kristian/odoov10/odoo-10.0rc1c-20161005/odoo/addons/web/controllers/main.py", line 862, in call_kw
return self._call_kw(model, method, args, kwargs)
File "/home/kristian/odoov10/odoo-10.0rc1c-20161005/odoo/addons/web/controllers/main.py", line 854, in _call_kw
return call_kw(request.env[model], method, args, kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/api.py", line 679, in call_kw
return call_kw_model(method, model, args, kwargs)
File "/home/kristian/.virtualenvs/odoov10/lib/python2.7/site-packages/odoo-10.0rc1c_20161005-py2.7.egg/odoo/api.py", line 664, in call_kw_model
result = method(recs, *args, **kwargs)
TypeError: write() got an unexpected keyword argument 'context'
I think it's because of this ctx = self._context.copy() but I've seen other methods on v10 which have it declared this way, I don't know if I should remove it.
Any ideas on this?
You need to use #api.multi decorator in write method.
#api.multi
def write(self, values):
""" To write a new record,
adds a Boolean field to true
indicates that the partner is a company
"""
#if context is None:
#context = {}
ctx = dict(self._context or {})
ctx.update({'create_company': True})
return super(ResCompany, self.with_context(ctx)).write(values)
Here 'Self' is a recordset you can't use #api.one in write method.
You can find difference between 2 decorators from below link.
When to use api.one and api.multi in odoo | openerp?
I'm migrating an Odoo v8 module, which is used to upload .csv's into stock.inventory model.
I've fixed a few things, but I still have some bugs on it, like this method:
#api.one
def action_import(self):
"""Load Inventory data from the CSV file."""
ctx = self._context
stloc_obj = self.env['stock.location']
inventory_obj = self.env['stock.inventory']
inv_imporline_obj = self.env['stock.inventory.import.line']
product_obj = self.env['product.product']
if 'active_id' in ctx:
inventory = inventory_obj.browse(ctx['active_id'])
if not self.data:
raise exceptions.Warning(_("You need to select a file!"))
# Decode the file data
data = base64.b64decode(self.data)
file_input = cStringIO.StringIO(data)
file_input.seek(0)
location = self.location
reader_info = []
if self.delimeter:
delimeter = str(self.delimeter)
else:
delimeter = ','
reader = csv.reader(file_input, delimiter=delimeter,
lineterminator='\r\n')
try:
reader_info.extend(reader)
except Exception:
raise exceptions.Warning(_("Not a valid file!"))
keys = reader_info[0]
# check if keys exist
if not isinstance(keys, list) or ('code' not in keys or
'quantity' not in keys):
raise exceptions.Warning(
_("Not 'code' or 'quantity' keys found"))
del reader_info[0]
values = {}
actual_date = fields.Date.today()
inv_name = self.name + ' - ' + actual_date
inventory.write({'name': inv_name,
'date': fields.Datetime.now(),
'imported': True, 'state': 'confirm'})
for i in range(len(reader_info)):
val = {}
field = reader_info[i]
values = dict(zip(keys, field))
prod_location = location.id
if 'location' in values and values['location']:
locat_lst = stloc_obj.search([('name', '=',
values['location'])])
if locat_lst:
prod_location = locat_lst[0]
prod_lst = product_obj.search([('default_code', '=',
values['code'])])
if prod_lst:
val['product'] = prod_lst[0].id
if 'lot' in values and values['lot']:
val['lot'] = values['lot']
val['code'] = values['code']
val['quantity'] = values['quantity']
val['location_id'] = prod_location
val['inventory_id'] = inventory.id
val['fail'] = True
val['fail_reason'] = _('No processed')
inv_imporline_obj.create(val)
Everytime, I click on the button which calls for this function, to upload the csv file it throws me this:
2016-11-02 23:18:38,659 16865 ERROR moto_backup openerp.http: Exception during JSON request handling.
Traceback (most recent call last):
File "/home/kristian/odoov9/odoo-9.0/openerp/http.py", line 648, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/home/kristian/odoov9/odoo-9.0/openerp/http.py", line 685, in dispatch
result = self._call_function(**self.params)
File "/home/kristian/odoov9/odoo-9.0/openerp/http.py", line 321, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/service/model.py", line 118, in wrapper
return f(dbname, *args, **kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/http.py", line 314, in checked_call
result = self.endpoint(*a, **kw)
File "/home/kristian/odoov9/odoo-9.0/openerp/http.py", line 964, in call
return self.method(*args, **kw)
File "/home/kristian/odoov9/odoo-9.0/openerp/http.py", line 514, in response_wrap
response = f(*args, **kw)
File "/home/kristian/odoov9/odoo-9.0/addons/web/controllers/main.py", line 892, in call_button
action = self._call_kw(model, method, args, {})
File "/home/kristian/odoov9/odoo-9.0/addons/web/controllers/main.py", line 880, in _call_kw
return getattr(request.registry.get(model), method)(request.cr, request.uid, *args, **kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/api.py", line 250, in wrapper
return old_api(self, *args, **kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/api.py", line 421, in old_api
result = new_api(recs, *args, **kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/api.py", line 425, in new_api
result = [method(rec, *args, **kwargs) for rec in self]
File "/home/kristian/odoov9/motostion_addons/odoomrp-wip-9.0/stock_inventory_import/wizard/import_inventory.py", line 89, in action_import
inv_imporline_obj.create(val)
File "/home/kristian/odoov9/odoo-9.0/openerp/api.py", line 248, in wrapper
return new_api(self, *args, **kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/models.py", line 4157, in create
record = self.browse(self._create(old_vals))
File "/home/kristian/odoov9/odoo-9.0/openerp/api.py", line 248, in wrapper
return new_api(self, *args, **kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/api.py", line 490, in new_api
result = method(self._model, cr, uid, *args, **old_kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/models.py", line 4301, in _create
tuple([u[2] for u in updates if len(u) > 2])
File "/home/kristian/odoov9/odoo-9.0/openerp/sql_db.py", line 141, in wrapper
return f(self, *args, **kwargs)
File "/home/kristian/odoov9/odoo-9.0/openerp/sql_db.py", line 220, in execute
res = self._obj.execute(query, params)
ProgrammingError: can't adapt type 'stock.location'
I guess the is something with the new api that I'm missing,
Please, any ideas about this?
A little mistake, you're trying to pass the stock.location object you got directly from your search query instead of the id
Change this line
if locat_lst:
prod_location = locat_lst[0]
to
if locat_lst:
prod_location = locat_lst[0].id
I have problrem with my code.
class SiteTrip(models.Model):
_name = 'vips_vc.site_trip'
name = fields.Char()
session_ids = fields.One2many('vips_vc.session', 'site_trip_id', string='Session ID', index=True)
url_prevouse_ids = fields.Many2one('vips_vc.url_list', string='Prevouse URL', index=True)
url_current_ids = fields.Many2one('vips_vc.url_list', string='Current URL', index=True)
class URLList(models.Model):
_name = 'vips_vc.url_list'
name = fields.Char(string="URL", required=True)
url_parametes = fields.Char(string="URL parameters")
target_session_id = fields.One2many('vips_vc.session', 'target_url_ids', string='Target URL')
site_trip_prevouse_id = fields.One2many('vips_vc.site_trip', 'url_prevouse_ids', string='Prevouse URL')
site_trip_current_id = fields.One2many('vips_vc.site_trip', 'url_current_ids', string='Current URL')
remote_sites_id = fields.One2many('vips_vc.remote_sites', 'site_url_ids', string='Remote site page with URL')
remote_sites_target_url_id = fields.One2many('vips_vc.remote_sites', 'target_url_ids', string='URL on remote site page')
My controller:
def register_trip(self, currentURLid, prevouseURLid, sessionID):
currentURLid = int(currentURLid)
prevouseURLid = int(prevouseURLid)
result = None
### something
_logger.info("CREATE -----> session_ids: %r url_prevouse_ids: %r url_current_ids: %r",
sessionID, prevouseURLid, currentURLid)
result = table.create({'session_ids': sessionID, 'url_prevouse_ids': prevouseURLid,
'url_current_ids': currentURLid})
### something
return result.id
And error is:
2016-08-04 17:20:52,931 24261 INFO odoov8 openerp.addons.vips_vc.controllers: CREATE -----> session_ids: 59 url_prevouse_ids: 8 url_current_ids: 1
2016-08-04 17:20:52,938 24261 ERROR odoov8 openerp.http: Exception during JSON request handling.
Traceback (most recent call last):
File "/home/skif/odoo/openerp/http.py", line 540, in _handle_exception
return super(JsonRequest, self)._handle_exception(exception)
File "/home/skif/odoo/openerp/http.py", line 577, in dispatch
result = self._call_function(**self.params)
File "/home/skif/odoo/openerp/http.py", line 313, in _call_function
return checked_call(self.db, *args, **kwargs)
File "/home/skif/odoo/openerp/service/model.py", line 118, in wrapper
return f(dbname, *args, **kwargs)
File "/home/skif/odoo/openerp/http.py", line 310, in checked_call
return self.endpoint(*a, **kw)
File "/home/skif/odoo/openerp/http.py", line 806, in __call__
return self.method(*args, **kw)
File "/home/skif/odoo/openerp/http.py", line 406, in response_wrap
response = f(*args, **kw)
File "/home/skif/odoo/my-modules/vips_vc/controllers.py", line 194, in register_session
self.register_trip(currentURLid, prevouseURLid, sessionID)
File "/home/skif/odoo/my-modules/vips_vc/controllers.py", line 375, in register_trip
'url_current_ids': currentURLid})
File "/home/skif/odoo/openerp/api.py", line 266, in wrapper
return new_api(self, *args, **kwargs)
File "/home/skif/odoo/openerp/models.py", line 4094, in create
record = self.browse(self._create(old_vals))
File "/home/skif/odoo/openerp/api.py", line 266, in wrapper
return new_api(self, *args, **kwargs)
File "/home/skif/odoo/openerp/api.py", line 508, in new_api
result = method(self._model, cr, uid, *args, **old_kwargs)
File "/home/skif/odoo/openerp/models.py", line 4279, in _create
result += self._columns[field].set(cr, self, id_new, field, vals[field], user, rel_context) or []
File "/home/skif/odoo/openerp/osv/fields.py", line 795, in set
for act in values:
TypeError: 'int' object is not iterable
As you see when I'm trying to add record in vips_vc.site_trip i receive error. And error only for currentURLid. It has integer value. prevouseURLid has integer value too. prevouseURLid and currentURLid have similar relation One2Many/Many2One.
prevouseURLid is working. currentURLid isn't.
In this line I checked all param(logger output):
2016-08-04 17:20:52,931 24261 INFO odoov8 openerp.addons.vips_vc.controllers: CREATE -----> session_ids: 59 url_prevouse_ids: 8 url_current_ids: 1
url_prevouse_ids and url_current_ids have type is integer. They have defined value. They have similar relation. And insert url_current_ids return error.
Why is it happening?
Tomorrow all worked fine !
I did not touch relation. I did not touch type of variables...
UPD: After all manipulation I have this: If i'm trying to create record with any param (sessionID, prevouseURLid, currentURLid) I receiving same error: TypeError: 'int' object is not iterable
I found error.
I don't know how it working early...
result = table.create({'session_ids': sessionID, 'url_prevouse_ids': prevouseURLid,
'url_current_ids': currentURLid})
Here present ID record from other tables(models). When I removed all data (module was remove and install again).
After that step by step i check all data what received variables and stored in DB. I founded that vips_vc.url_list and vips_vc.session had not data.
after that i placed such code after create all records:
_logger.info(".....> Commit record ID %r", result.id)
table.env.cr.commit()
I have no idea why it code work early without commit().