Related
I want to show total numbers of record on screen. For this i have write query language for function and i get desire result on Ubuntu 14.04 command line screen by printing that value from python code. But when i return this value in function then it shows me error pop-up message "TypeError: 'int' object is not iterable". So, anyone can give me proper solution for this problem. My python code for function and field is below.
Python code:
def get_count(self, cr, uid, ids, sequence, arg, context=None):
cr.execute('SELECT count(*) from sun_helpdesk')
u_data = cr.fetchall()
print "cr:", u_data
print "res:",int(u_data[0][0])
return int(u_data[0][0])
_columns = {
'sequence': fields.function(get_count, method=True, string='Total Tickets', type='integer'),
}
XML code:
In XML this field added simply.
Result on the Ubuntu Screen is:
cr: [(101L,)]
res: 101
new_values = dict(values)
TypeError: 'int' object is not iterable
You need to return a dict which its keys are ids, for example:
def get_count(self, cr, uid, ids, sequence, arg, context=None):
res = {}
cr.execute('SELECT count(*) from sun_helpdesk')
u_data = cr.fetchall()
print "cr:", u_data
print "res:",int(u_data[0][0])
#res[id] must be set to False and not to None because of XML:RPC
# "cannot marshal None unless allow_none is enabled"
res[ids[0]] = int(u_data[0][0]) if ids else False
return res
Take a look at Function field
Pythionans
Why would these 2 functions return a different value when using a temp return result?
I have never seen this behaviour before and need to understand why.
Any clues or ideas?
def _store_get_values(self, cr, uid, ids, fields, context=None):
return super(pai, self)._store_get_values(cr, uid, ids, fields, context)
Returns
[(10, 'pai', [13484L], ['line_next_approver_id', 'next_approver_id', 'line_id', 'partner_id'])]
And
def _store_get_values(self, cr, uid, ids, fields, context=None):
result = super(pai, self)._store_get_values(cr, uid, ids, fields, context)
return result
Returns
[(10, 'pai', [13485L], ['line_id', 'next_approver_id', 'partner_id', 'line_next_approver_id'])]
I have this in the openerp/odoo framework. But I believe this has nothing to do with the framework logic but with Python ways
From sourcecodebrowser.com:
02486 def _store_get_values(self, cr, uid, ids, fields, context):
02487 result = {}
02488 fncts = self.pool._store_function.get(self._name, [])
02489 for fnct in range(len(fncts)):
02490 result.setdefault(fncts[fnct][0], {})
02491 ids2 = fncts[fnct][2](self,cr, uid, ids, context)
02492 for id in filter(None, ids2):
02493 result[fncts[fnct][0]].setdefault(id, [])
02494 result[fncts[fnct][0]][id].append(fnct)
02495 result2 = []
02496 for object in result:
02497 k2 = {}
02498 for id,fnct in result[object].items():
02499 k2.setdefault(tuple(fnct), [])
02500 k2[tuple(fnct)].append(id)
02501 for fnct,id in k2.items():
02502 result2.append((fncts[fnct[0]][4],object,id,map(lambda x: fncts[x][1], fnct)))
02503 result2.sort()
02504 return result2
This code seems the result of a code golf challenge, however... result2.append(...) is the line that is producing your result. Let's take a closer look at it:
result2.append((
fncts[fnct[0]][4],
object,
id,
map(lambda x: fncts[x][1], fnct)
))
The result of map() is the list that is giving you problems. The order of items returned by map() depends on the order of items in fnct.
What is fnct? It comes from k2. k2 was generated from result[object]. result is generated from ids2. ids2 is the result of a call to fncts[fnct][2]. fncts is taken from self.pool._store_function.
So, look at the source of your _store_function and you'll find the answer.
I need to do two activities in my activity method.
one is need to return value for total_workers field.but need to return ID also because its necessary requirement in OpenERP when we override that method.
then have to return 2 things.please advice me how to implement this in my form.
with one return value this is worked for both things.but need to return both.
def create(self, cr, uid, values, context=None):
name = 'CheckRoll No = ' + str(values['checkroll_no']) + ' & Gang No = ' + str(values['gang_no'])
values.update({'name': name})
total_tea_workers = 0
offer_id = super(bpl_work_offer, self).create(cr, uid, values, context=context)
tea_worker_obj = self.browse(cr, uid, offer_id, context=context) or []
tea_worker_ids = self.pool.get('bpl.selected.tea.workers.line').search(cr, uid, [('tea_line_worker_id', '=', tea_worker_obj.id)])
for tea_worker in self.pool.get('bpl.selected.tea.workers.line').browse(cr, uid, tea_worker_ids):
if tea_worker.is_selected:
total_tea_workers += 1
return {'value': {'total_workers': total_tea_workers}}
return offer_id
EDITED
I sort it out in this way.hope this will help for others
:-)
i wrote a function for my field
def _compute_workers(self, cr, uid, ids, fieldname, arg, context=None):
total_workers = total_tea_workers = total_rubber_workers = total_sundry_workers = total_other_workers = 0
res = dict.fromkeys(ids, False)
for this in self.browse(cr, uid, ids, context=context):
tea_worker_ids = self.pool.get('bpl.selected.tea.workers.line').search(cr, uid, [('tea_line_worker_id', '=', this.id)])
for tea_worker in self.pool.get('bpl.selected.tea.workers.line').browse(cr, uid, tea_worker_ids):
if tea_worker.is_selected:
total_tea_workers += 1
rubber_worker_ids = self.pool.get('bpl.selected.rubber.workers.line').search(cr, uid, [('rubber_line_worker_id', '=', this.id)])
for rubber_worker in self.pool.get('bpl.selected.rubber.workers.line').browse(cr, uid, rubber_worker_ids):
if rubber_worker.is_selected:
total_rubber_workers += 1
sundry_worker_ids = self.pool.get('bpl.selected.sundry.workers.line').search(cr, uid, [('sundry_line_worker_id', '=', this.id)])
for sundry_worker in self.pool.get('bpl.selected.sundry.workers.line').browse(cr, uid, sundry_worker_ids):
if sundry_worker.is_selected:
total_sundry_workers += 1
other_worker_ids = self.pool.get('bpl.selected.other.workers.line').search(cr, uid, [('other_line_worker_id', '=', this.id)])
for other_worker in self.pool.get('bpl.selected.other.workers.line').browse(cr, uid, other_worker_ids):
if other_worker.is_selected:
total_other_workers += 1
total_workers = total_tea_workers + total_rubber_workers + total_sundry_workers + total_other_workers
res[this.id] = total_workers
return res
i changed my integer field to functional field
'total_workers': fields.function(_compute_workers, type="integer", string="Total Workers"),
You should never return anything else in create() except the ID of the record that was created. Usually this is done by returning the result of the call to the parent via super(myclass, self).create(...) indeed.
It's not clear what you are trying to achieve with your total_workers code. If total_workers is supposed to be a computed field, you don't have to override create at all: just declare this column as a fields.function and put the code to compute it in the corresponding function.
For example:
def _compute_workers(self, cr, uid, ids, fieldname, arg, context=None):
result = dict.fromkeys(ids, False) # default result for each id
for this in self.browse(cr, uid, ids, context=context):
# let's assume you have a one2many called worker_ids
result[this.id] = len(this.worker_ids)
return result
_columns = {
'total_workers': fields.function(_compute_workers, type="integer",
string="Total Workers")
}
At this point it would be a good idea to have a good look at the OpenERP technical memento and the OpenERP framework documentation, to get an overview of the OpenERP API and how it is supposed to be used :-)
Once you have a good understanding of the structure of models, the various field types, the CRUD methods and the inheritance patterns, you should be able to quickly browse the source code of the official modules and find examples of anything you want to accomplish. This should make your life much more easier!
I think that you're doing the counting of the workers in a very inefficient manner.
You're doing your SQL filter to obtain each of the workers matching an ID, and then testing for a single flag within them.
I think it would be much more efficient to just add another criteria to your select statement.
total_tea_workers = self.pool.get('bpl.selected.tea.workers.line').search(cr, uid, [('tea_line_worker_id', '=', id), ('is_selected', '=', True)]), count=True)
I am learning to develop OpenERP modules, and one of the things I need to do is calculate the average of all the inputs from the user.
My idea was to loop the records while keeping the sum and the count and then make the average, but I can't seem to understand how to access the value for the total field for each record in the sim.students table
Here is part of my code
def get_text(self, cr, uid, ids, fields, arg, context):
result = {}
i = 0
for id in ids:
print self.browse(cr,uid,id,['total'])
print id
i = i+1
print i
return result
But the result of printing self.browse(cr,uid,id,['total']) returns me browse_record(sim.student, 3)and not the total itself.
I know this must be really simple but I can't seem to figure out how to get to that value.
Any tip much appreciated
So this is what I got from here:
browse(cr ,uid, select, context=None, list_process=None, fields_process=None)
where:
cr = database cursor
uid = user id
select = id or list of ids
context = context arguments like lang, time zone
It returns an object with all the fields accessible by dot notation. So you can do something like:
records = self.browse(cr, uid, ids)
for rec in records:
print rec.total
print rec.otherfield
or if you like list comprehensions:
records = self.browse(cr, uid, ids)
totals = [rec.total for rec in records]
average = sum(totals)/len(totals)
I do a project about Timesheet in OpenERP. I have this problem:
this is x_luong table.
class x_luong(osv.osv):
_name = 'x_luong'
_description = 'Luong'
_columns = {'name': fields.many2one('x_nhanvien', 'Mã nhân viên', size=10, required='1'),
'ma_luong': fields.integer('ma luong', size=10, required='1'),
'giolam': fields.float('Giờ làm', size=100, required='1'),
'giolamthuc': fields.char('Gio lam thuc te', size=5, required='1'),
'time_in': fields.char('Gio vào', size=20),
'time_out' :fields.char('Gio về', size=20),
'state' :fields.selection([('dangnhap','Đẳng nhập.'),('rave','Ra về')]),
'test': fields.integer('Kiem tra', size=20),
'phutvao': fields.integer('Phut vao ', size=20),
'phutra': fields.integer('phut ra', size=20),
}
_defaults = {'state':'dangnhap',
}
and this some function in it:
this 2 function mean get time when the staff sign_in or sign_out the system:
def get_timein(self,cr,uid,ids,context={}):
obj = self.browse(cr,uid,ids,context=context)[0]
timein = str(datetime.now())
self.write(cr, uid, ids, {'time_in':timein }, context=context)
return 1
def get_timeout(self,cr,uid,ids,context={}):
obj = self.browse(cr,uid,ids,context=context)[0]
timeout = str(datetime.now())
self.write(cr, uid, ids, {'time_out':timeout }, context=context)
return 1
and this 2 function for button sign_in and sign_out:
def cho_dangnhap(self,cr,uid,ids,context={}):
self.pool.get('x_luong').write(cr,uid,ids,{'state':'dangnhap'})
self.get_timein(cr,uid,ids)
return 1
def cho_rave(self,cr,uid,ids,context={}):
self.pool.get('x_luong').write(cr,uid,ids,{'state':'rave'})
self.get_timeout(cr,uid,ids)
self.tinh_thoigian(cr,uid,ids)
self.insert(cr,uid,ids)
function tinh_thoigian mean cut the string time for get ... hour or min for calculation
def _thoigianlam(self,cr,uid,ids,context={}):
obj = self.browse(cr,uid,ids,context=context)[0]
hour_den = int(obj.time_in[12:13])
hour_di = int(obj.time_out[12:13])
min_den = int(obj.time_in[15:16])
min_di = int(obj.time_out[15:16])
gl = int(hour_di)-int(hour_den)
pl = min_di-min_den
thucte = str(gl)+':'+pl
self.write(cr, uid, ids, {'giolam':gl }, context=context)
self.write(cr, uid, ids, {'giolamthuc':thucte }, context=context)
return 1
and last function insert() get ma_luong(i think this same the primary key in sql) and giolam(the hour of the staff work in company), time_in, time_out and this is function insert()
def insert(self,cr,uid,ids,context={}):
obj = self.browse(cr,uid,ids,context=context)
values = {'ma_luong':obj.name.id,
'giolam':obj.giolam,
'time_in':time_in,
'time_out':time_out,
self.pool.get('x_giolam').create(cr,uid,values,context=context)
with this function i want insert data in table x_giolam because when the staff sign in or sign out the system in day ... the data of it with save in this table and a other day when they do it again it with save it again ... and last month if you want calculation about salary of them you just select ma_luong=ma_luong(of table x_luong) and this table x_giolam:
class x_giolam(osv.osv):
_name = 'x_giolam'
_description = 'Gio Lam'
_columns = {'name': fields.integer('Lọai',size=64,required="true"),
'giolam' : fields.float('Gio lam',size=64,required="True"),
'time_in': fields.char('Gio vào',size=20),
'time_out' :fields.char('Gio về',size=20),
}
and i have 3 question with my project:
1) function insert have aerror:
AttributeError: 'browse_record_list' object has no attribute 'name'
How can i fix it ??? i data of it is save in table x_giolam
2) how can i select many row of table x_giolam which of thte employee' own.. give me some example about this function
3) how i can organization field.Xml when i show rows in
Sorry for your troubles because it is so long ... but i hope every body in here can help me. Python and open Erp so difference with c++ or c#. And this my project"research and write a module timesheet with OpenErp" of me and next week is deadline.
English of me not good, i'm sory about it!!!
Thanks!!
I can help with your first question. The problem is in this code:
def insert(self,cr,uid,ids,context={}):
obj=self.browse(cr,uid,ids,context=context)
values={'ma_luong':obj.name.id,
The error message was like this:
AttributeError: 'browse_record_list' object has no attribute 'name'
If you call orm.browse() with a list of ids, you will get back a list of browse records. You then have to enumerate through the list, or get a single entry from the list to work with.
For example:
for luong in self.browse(cr,uid,ids,context=context):
print luong.name
Or:
luongs = self.browse(cr,uid,ids,context=context)
luong = luongs[0]
print luong.name
Why don't you take a look at the standard hr_attendance module and go on from there?
For your model, the name is a reserved field name, so it would be best to keep it as achar. Try that change and see if it solves your error message.
For the other two questions, I think you should try to rephrase them a little better...
The type of obj is list of records, so for browse the list of records, you must define a one element.
in your case, you can type : obj[0].giolam --> for the giolam of the first record of obj.
forgive me for my bad english