save into another table - odoo

oI select same field from mo.queue and I want save it into the procurement.order table
My code looks as follows:
def action_ship_create(self, cr, uid, ids, id_queue, context=None):
queue_obj = self.pool.get('mo.queue'). browse (cr, uid, id_queue, context=context)
mo_name = queue_obj.name
query_param = (mo_name)
cr.execute("select origin,create_date,product_uos_qty,product_qty,name,city from mo_queue",(query_param,))
ads = cr.fetchone()
name = ads and ads [0] or None
print "======================"
print name
print "======================"
val = { 'origin': name,
}
print "======================"
print val
print "======================"
return {'value': val }
proc_id = self.pool.get('procurement.order').create(cr, uid, {
'origin':origin,
})
proc_ids.append(proc_id)
The result of the print is:
print name = SO013
print val = {'origin': u'SO013'}
But the data is not inserted into the procurement.order table.

your code me look like this after return statement is does not executes anything do put cdeo before return and your code need lot of tuning, like do not use SQL Injection it is not good idea.
def action_ship_create(self, cr, uid, ids, id_queue, context=None):
queue_obj = self.pool.get('mo.queue'). browse (cr, uid, id_queue, context=context)
queue_model = self.poo.get(queue_obj.name)
procurement_pool = self.pool.get('procurement.order')
qsids = queue_model.search(cr, uid, )
for record in queue_model.browse(cr, uid, qsids):
if record.origin:
#this will crate a new record the table procurement.order so
#field values may be not enough so you can update logic
#and If you want to update record value you need a proc ids and you can do it.
procurement_pool.create(cr, uid, {'origin':record.origin})
return {'value': {'origin': record.origin}}
Hope this will help you let me know i I am missing.
Thank You

Related

Assign default value to a Many2one field for specific user group in odoo

I am assigning a default value to analytic distribution field in account.invoice.line by below code
def _get_default_account(self, cr, uid, context=None):
res = self.pool.get('account.analytic.plan.instance').search(cr, uid, [('code','=','LAL')], context=context)
return res and res[0] or False
_defaults = {
'analytics_id': _get_default_account,
}
but now i want to set default value for specific group of user. I want to set one value for a group and other value for other group. Means I want to set two different default values for different users.
Someone please give me some idea about it. I'll be very thankful...
Easiest way to approach that is using has_group method. You should do it like:
if self.env['res.users'].has_group('base.group1'):
res = self.pool.get('account.analytic.plan.instance').search(cr, uid, [('code','=','LAL')], context=context)
return res and res[0] or False
elif self.env['res.users'].has_group('base.group2'):
res = self.pool.get('account.analytic.plan.instance').search(cr, uid, [('code','=','SAS')], context=context)
return res and res[0] or False
And so on and so forth.

OpenERP 7 : How to trigger a auto version increase function after click save

how could i trigger a function after i click save in OpenERP 7?
In my custom module, i wish to auto increase the "version_number" parameter where every time the user click save it will trigger a function to execute the logic of "ver=ver+1" and write back to the "version_number" fields. How could i do that?
I tried use "def write()" but not sure exactly how it could be done. Appreciate your kind help. Thanks!
You need to override write method.
def write(self, cr, uid, ids, vals, context=None):
res = super(your_model, self).write(cr, uid, ids, vals, context)
self._increment_version(cr, uid, ids)
return res
def _increment_version(self, cr, uid, ids):
for record in self.browse(cr, uid, ids):
cr.execute('update table_name set version_number=%s where id=%s' % (record.version_number + 1, record.id))
Here is the write method work for me
def write(self, cr, uid, ids, vals, context=None):
res = super(your_model, self).write(cr, uid, ids, vals, context)
self._increment_version(cr, uid, ids)
return res
def _increment_version(self, cr, uid, ids):
res = {}
reads = self.read(cr, uid, ids, ['version'], context=context)
ver_num = reads.get('version')
ver_id = reads.get('id')
if ver_num:
cr.execute('update table_name set version_number=%s where id=%s' % (ver_num + 1, ver_id))
return res
you are right you should use write function as.
_columns={...,
'ver':fields.integer(),
...}
def write(self, cr, uid, ids, vals, context=None)
vals['ver']= trigger_func()
return self.super(your_class_name).write(cr, uid, vals, context)
EDIT
It looks like my answer was not clear enough sorry if I didn't check the comments at the time. But because the problem and solutions are the same in newer versions of odoo/openerp, I am adding more description here.
The trigger_func must not write any value to the db (no self.write or self.some_field=some_value). It should simply return the new value for version.
def trigger_func(self):
return self.ver + 1
for newer version of Odoo (V8+), use the same format for trigger function and:
#api.multi
def write(self,vals):
vals['ver'] = self.trigger_func()
return super(YourClassName, self).write(vals)
Please note that this will set the same version for all records, You should use self.ensure_one() at the beginning of the trigger_func if you plan to change versions record by record. If you want a solution that works for multi writes (which I do recommend change your code to avoid it) you can use this slower code:
#api.multi
def write(self,vals):
if len(self)>1:
for rec in self:
rec.write(vals)
return self
else:
vals['ver'] = self.trigger_func()
return super(YourClassName, self).write(vals)
Another solution if you want to add version number to all models, would be patching the Abstract class and adding an auto increase magic field but it looks very overkill for this purpose.
Anyway, I think the direct use of the cursor should be the last resort.

openerp function field not working - OpenERP v7

I am having issues with getting a function field to display a string returned by a function in a custom module I am using to extend the stock.picking.out form. Ideally I would like to have a specific string from a field stored in the database displayed but that's an issue for another time because I can't even get a generic string to display..
Here is my field definition within my custom class:
_columns = {
'my_field_name': fields.function(_my_func, type='char', string='description', store=True, method=True, readonly=True),
}
Here is my definition for '_my_func':
def _my_func(self, cr, uid, ids, field_name, arg, context=None):
str="some string to be displayed"
return str
Here is the XML for the field:
<field name="my_field_name" string="Here is my string:" class="oe_inline"/>
I have searched the OpenERP dev book as well as their forums and these forums, and believe I have followed all of the proper syntax for this field so any help is greatly appreciated.
You need to improve your function/method like,
def _my_func(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for rec in self.browse(cr, uid, ids, context=context):
res[rec.id] = 'Some string'
return res
while writing functional field(up to v7) make sure you return a dictionary like
{17: "some string"}
if you have multiple field it can be like
{17: {'field_one': 'value 1', 'field_two': 'value 1'}}
EDIT:
Also In _columns please remove readonly=True like
_columns = {
'my_field_name': fields.function(_my_func, type='char', string='description', store=True, method=True),
}
Hope this helps.
Just you must have to improve your function login
you can do some things like this.
def _my_func(self, cr, uid, ids, field_name, arg, context=None)
v={}
if field_name:
v['my_field_name'] = " some string to be displayed "
return {'value': v}
Then finally your function logic working like a charm.
I hope this should helpful for you :)
Try following,
def _my_func(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for obj in self.browse(cr, uid, ids, context=context):
###Set your string here
str="some string to be displayed"
res[obj.id]['my_field_name'] = str
return res
If you are a little confused with OpenERP v7, you always can try with Odoo(OpenERP v8) It's much more easiest to work.
from openerp import models, fields,api
class my_class(models.Model):
_name="my.class"
my_field_name=fields.Text(string="description", compute=_my_func, store=True, readonly=True)
def _my_func(self):
self.my_field_name = "some string to be displayed"
I hope this can help you!
try this,
def _my_func(self, cr, uid, ids, field_name, arg, context=None):
result = {}
for record in self.browse(cr, uid, ids):
str="some string to be displayed"
result[record.id] = str
return result
and if you use store = True on a functional-field then it will be accessed for the first time and it will store the result in database, and from next time it wont be called.
To access functional field every time for store = True , refer sale.py [amount_total] field. We have to write some addtional code
You can give like this also :
without using browse method..
def _my_func(self, cr, uid, ids, field_name, arg, context=None):
result = {}
str="some string to be displayed"
result[ids[0]] = str
return result
Make sure, in model field type should be char/text.

Odoo IndexError: list assignment index out of range

I just create a module. After adding values and got the problem IndexError: list assignment index out of range. How to fix it. Re Edit code please.
Here is my code:
class calculator(osv.osv):
_name = 'calculator.calculator'
def get_total(self, cr, uid, ids, field_name, arg, context):
res = []
perfos = self.browse(cr, uid, ids, context)
for perfo in perfos:
res[perfo.id] = perfo.p + perfo.b
return res
_columns = {
'p':fields.selection(((1,'Outstanding'), (2,'Well Above Expectations'), (3,'As Expected'), (4,'Below Expectations'), (5,'VeryPoor'), (0,'N/A')),'title'),
'b':fields.selection(((1,'Outstanding'), (2,'Well Above Expectations'), (3,'As Expected'), (4,'Below Expectations'), (5,'Very Poor'), (0,'N/A')),'title'),
'total' : fields.function(get_total, method=True, string='Total Mark'),
}
You need to return a dictionary of dictionary for functional fields. You defined res as list and tried to assign as the dictionary. res[perfo.id] is considered as list and index value perfo.id is not found in the res list. That is what the error says. Now the code will be
class calculator(osv.osv):
_name = 'calculator.calculator'
def get_total(self, cr, uid, ids, field_name, arg, context):
res = {}
for perfos in self.browse(cr, uid, ids, context):
res[perfos.id] = perfos.p + perfos.b
return res
_columns = {
'p':fields.selection(((1,'Outstanding'), (2,'Well Above Expectations'), (3,'As Expected'), (4,'Below Expectations'), (5,'VeryPoor'), (0,'N/A')),'title'),
'b':fields.selection(((1,'Outstanding'), (2,'Well Above Expectations'), (3,'As Expected'), (4,'Below Expectations'), (5,'Very Poor'), (0,'N/A')),'title'),
'total' : fields.function(get_total, method=True, string='Total Mark'),
}
For the above code you probably get this js error Error: [_.sprintf] expecting number but found string
I don't get the point adding up two selection fields. The key will get added up like 1+1 in a unicode format.
This following code will give you the basic idea of functional fields.
class calculator(osv.osv):
_name = 'calculator.calculator'
def get_total(self, cr, uid, ids, field_name, arg, context):
res = {}
for perfos in self.browse(cr, uid, ids, context):
res[perfos.id] = perfos.p + perfos.b
return res
_columns = {
'p':fields.integer('A'),
'b':fields.integer('B'),
'total' : fields.function(get_total, method=True, string='Total Mark'),
}
You may need to look at
How to set store trigger for computed fields in Odoo 8?
Function field is not working in OpenERP

Openerpv7: Numbeing in OrderLine

I'm using OpenERP v7 and requesting this below output in Purchase order line window
PO0001 PO0002 PO0003
Line Line Line
10 10 10
20 20 20
30 30
My code:
<field name="order_line" context="{'order_id':active_id}">
_columns={
'sequence':fields.integer('Sequence', store=True),
}
_defaults = {
lambda obj, cr, uid, context: obj._default_sequence(cr, uid, context)
}
def _default_sequence(self, cr, uid, context=None):
if context is None:
context = {}
max_sequence = 0
if context.get('order_id'):
order_line = self.search(cr, uid, [('order_id', '=', context['order_id'])])
if order_line:
max_sequence = max([line['sequence'] for line in self.read(cr, uid, order_line, ['sequence'])])
return max_sequence + 10
But im getting this kind of output . Any advice would be greatful.
PO0001 PO0002 PO0003
Line Line Line
10 10 10
10 10 10
10 10
Anyone could help me to achive the required output.
I think you are doing wrong. A record will be created only after you click on any button action(button other than adding the lines) for the first time for the record. Then only you will be able to make the search. I hope default will get the context even if we don't specify context. Still not getting the context, then try by following the answer given by Andrei Boyanov.Also please understand that field names like active, state, sequence etc have some super powers in openerp. For example if a table have a field "sequence", then the table's tree view will have a drag and drop functionality and if we do the drag and drop functionality, then a new sequence for each record in the table will be automatically calculated and saved.
So my opinion is not to use the sequence field. Use any other field name. Then write a on_change method to your one2many field and pass the one2many field name as the attribute to the on_change method. Then in the on_change method check what all values are coming when you add a new line. If the new line's value is in the format (0,0,dictionary_with_fields_as_keys_and_its_values_as_values).Then to this dictionary add the sequence_number with the value.For example:
<field name="order_line" on_change="onchange_line(order_line)">
def onchange_line(self, cr, uid, ids, lines,context=None):
result = {}
result['value'] = {}
#do the proper checking
count_dict = {}
count = 10
had_seq = 0
for index,line in enumerate(lines):
if line[0] == 0:
count_dict[index] = count
count +=10
else:
had_seq +=1
#seqnece_no is the new sequence field defined
for k in count_dict:
if had_seq:
lines[k][2]['sequence_no'] = had_seq*10 + count_dict[k]
else:
lines[k][2]['sequence_no'] = count_dict[k]
result['value'].update({'order_line':lines})
return result
Please try it.
How do you execute _default_sequence(...) ? I suppose you intend to invoke it trough the _defaults dictionary. In this case correct it as follow:
_defaults = {
'sequence': lambda obj, cr, uid, context: obj._default_sequence(cr, uid, context)
}
In your code you omitted the key sequence. In fact what you defined is not a dictionary but a set with one element - the lambda function.
Better, you can define it just like this:
_defaults = {
'sequence': _default_sequence
}
change your Python file by
def _default_sequence(self, cr, uid, context=None):
if not context: context = {}
max_sequence = 0
if context.get('order_id'):
order_line = self.search(cr, uid, [('order_id', '=', context['order_id'])])
if order_line:
max_sequence = max([line['sequence'] for line in self.read(cr, uid, order_line, ['sequence'])])
return max_sequence + 10
_columns={
'sequence':fields.integer('Sequence'),
}
_defaults = {
'sequence': _default_sequence
}
No need to put store=True in the integer field, it will always store value in the database.