Use ORM methods, to get the required data? - odoo

I need to get the value of field in a tree view of the fields_view_get method and a
I use ORM methods to achieve this. my code :
class res_partner(osv.osv):
_inherit = 'res.partner'
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
if context is None:
context = {}
partner_obj = self.pool.get('res.partner')
ids_partner = partner_obj.search(cr, uid, [], context=context)
partner_name = partner_obj.browse(cr, uid, ids_partner, context=context)
element = partner_obj.browse(cr,uid,ids_partner[0]).numcte
res = super(res_partner,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
newcte=test_name.numcte
doc = etree.XML(res['arch'])
if view_type == 'tree':
for node in doc.xpath("//field[#name='numcte']"):
node.set('string', 'numcte')
for node in doc.xpath("//button[#name='icono']"):
node.set('icon', newcte)
res['arch'] = etree.tostring(doc)
return res
_columns = {
'numcte': fields.text('numero cliente'),
}
res_partner()
My problem is when I, use for instance :
element = partner_obj.browse(cr,uid,ids_partner[0]).numcte
It returns me the value of the field that I want, but in the treeView is the same for each row, like this A001, A001, A001, in instead of A001, A002, A003.
in this case ids_partner[0], How can I make this number to be dynamic and changing for each row ?
Or in the case that use this:
my_data = partner_obj.read(cr, uid, ids_partner, ["numcte"], context=context)
returns me the tuple like this:
[{'numcte': u'A001', 'id': 3}, {'numcte': u'A002', 'id': 2}, {'numcte': u'A003', 'id': 4}]
[{'numcte': u'A001', 'id': 3}, {'numcte': u'A002', 'id': 2}, {'numcte': u'A003', 'id': 4}]
[{'numcte': u'A001', 'id': 3}, {'numcte': u'A002', 'id': 2}, {'numcte': u'A003', 'id': 4}]
one for each row
How can I get the value of the field that I want for the correct row. ?
thank you all for your time, I been a while in this so any help is usefull.

fields_view_get is provided to allow you to change/create the XML that defines the view, not the data.
What you need to do in fields_view_get is drop your field onto the view. However, overriding fields_view_get is only done in very unusual cases where you need the view to by dynamic in a way that can't be achieved easily with attrs and states in the XML view.
The usual pattern is to create a view in XML that extends the partner tree view and adds your field in the correct place using an XPATH expression. If your field is a new field, you will need to also need to create a new model that inherits the res_partner model and add your new field in _columns.

Related

Add a custom button without close odoo 9 wizard?

Good day,
I've been working on the lot and serial number module in odoo 9.
I changed the sequence that the module has as default and I substituted it with the generation of an UUID, but when I call this component in the received items part, when I click on the button that generates the UUID the app suddenly returns to the window that I used to call it without letting me to save the UUID that I generated.
Here's my code:
class stock_production_lot(osv.osv):
_name = 'stock.production.lot'
_inherit = ['mail.thread']
_description = 'Lot/Serial'
_columns = {
'name': fields.char('Serial Number', required=True, help="Unique Serial Number"),
'x_num_serie_': fields.char('No. de serie', required=False, help="No. de serie del producto"),
'ref': fields.char('Internal Reference', help="Internal reference number in case it differs from the manufacturer's serial number"),
'product_id': fields.many2one('product.product', 'Product', required=True, domain=[('type', 'in', ['product', 'consu'])]),
'quant_ids': fields.one2many('stock.quant', 'lot_id', 'Quants', readonly=True),
'create_date': fields.datetime('Creation Date'),
}
_defaults = {
'name': lambda x, y, z, c: x.pool.get('ir.sequence').next_by_code(y, z, 'stock.lot.serial'),
'x_num_serie_':None,
'product_id': lambda x, y, z, c: c.get('product_id', False),
}
_sql_constraints = [
('name_ref_uniq', 'unique (name, product_id)', 'The combination of serial number and product must be unique !'),
]
def action_traceability(self, cr, uid, ids, context=None):
""" It traces the information of lots
#param self: The object pointer.
#param cr: A database cursor
#param uid: ID of the user currently logged in
#param ids: List of IDs selected
#param context: A standard dictionary
#return: A dictionary of values
"""
quant_obj = self.pool.get("stock.quant")
quants = quant_obj.search(cr, uid, [('lot_id', 'in', ids)], context=context)
moves = set()
for quant in quant_obj.browse(cr, uid, quants, context=context):
moves |= {move.id for move in quant.history_ids}
if moves:
return {
'domain': "[('id','in',[" + ','.join(map(str, list(moves))) + "])]",
'name': _('Traceability'),
'view_mode': 'tree,form',
'view_type': 'form',
'context': {'tree_view_ref': 'stock.view_move_tree'},
'res_model': 'stock.move',
'type': 'ir.actions.act_window',
}
return False
def action_generate_uuid(self, cr, uid, ids, context=None):
print "< action_generate_uuid >"
_uuid = (uuid.uuid1()).hex
obj = self.browse(cr, uid, ids,context=context)
print "< obj.name >",obj.name
for item in self.browse(cr, uid, ids,context=context):
if item.name:
item.name = _uuid
item.x_num_serie_ = _uuid
print "< name >",item.name
print "< x_num_serie_>",item.x_num_serie_
else:
print "< falta un elemento >"
return None
I'll really appreciate any idea on what is happening and how can I avoid it.
Best regards,
Alain
The default behaviour is to close upon the pressing of any button and execution of the function associated with the button. The work around is to have the button execute a function and then return an action bringing up the exact same wizard.
You can set context to open the wizard again with all the form values populated.
Here is an example:
class MyWizard(models.TransientModel):
_name = 'myaddon.mywizard'
def _get_default_char(self):
return self._context.get('mychar',"")
mychar = fields.Char(string="My Char", default=_get_default_char)
#api.multi
def my_button(self):
# Execute Function Here
# reload wizard with context
return {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'myaddon.mywizard',
'type': 'ir.actions.act_window',
'target': 'new',
'res_id': self.id,
'context': '{"default_mychar":'HELLO WORLD'}',
}

How to override create methode in odoo 10

i want to use same create method in odoo 10 as below means i want to convert below code in odoo 10, below code is working well for odoo 8
def create(self, cr, uid, vals, context=None):
phase_obj = self.pool.get('hr_evaluation.plan.phase')
survey_id = phase_obj.read(cr, uid, vals.get('phase_id'), fields=['survey_id'], context=context)['survey_id'][0]
if vals.get('user_id'):
user_obj = self.pool.get('res.users')
partner_id = user_obj.read(cr, uid, vals.get('user_id'), fields=['partner_id'], context=context)['partner_id'][0]
else:
partner_id = None
user_input_obj = self.pool.get('survey.user_input')
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = user_input_obj.create(cr, uid, {'survey_id': survey_id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id}, context=context)
vals['request_id'] = ret
return super(hr_evaluation_interview, self).create(cr, uid, vals, context=context)
i am trying below code:
def create(self, vals):
survey_id = self.env['hr_evaluation.plan.phase'].read(vals.get('phase_id'),fields=['survey_id'])['survey_id'][0]
if vals.get('user_id'):
partner_id = self.env['res.users'].read(vals.get('user_id'), fields=['partner_id'])['partner_id'][0]
else:
partner_id = None
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = self.env['survey.user_input'].create({'survey_id': survey_id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id})
vals['request_id'] = ret
return super(hr_evaluation_interview, self).create(vals)
but it is giving me error like TypeError: read() got multiple values for keyword argument 'fields' so please guide me how can i remove this error?
read method accept fields as argument and you give it two arguments.
read([fields])
Reads the requested fields for the records in self, low-level/RPC method. In Python code, prefer browse().
Parameters
fields -- list of field names to return (default is all fields)
Returns
a list of dictionaries mapping field names to their values, with one dictionary per record
Raises
AccessError -- if user has no read rights on some of the given records
Instead of calling read method it's better to call browse() method, you can read Browse() vs read() performance in Odoo 8
Your code should be:
def create(self, vals):
survey_id = self.env['hr_evaluation.plan.phase'].browse(vals.get('phase_id'))
if vals.get('user_id'):
partner_id = self.env['res.users'].browse(vals.get('user_id'))
else:
partner_id = None
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = self.env['survey.user_input'].create({'survey_id': survey_id.id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id.id})
vals['request_id'] = ret.id
return super(hr_evaluation_interview, self).create(vals)

Auto fill on2many field on form load odoo 8

I have tried to create a functional field with type="one2many" and auto fill on form load. I tried below code:
Code 1:
'flat_members1': fields.function(_get_flat_members, relation="family.info", method=True, type="one2many", multi='flat_fkk'),
def _get_flat_members(self, cr, uid, ids, name, arg, context=None):
cr.execute("Select * from family_info where flat="+str(flat_id)+"")
cr_res = cr.dictfetchall()
res = {}
for data in self.browse(cr,uid,ids):
res[data.id] = self.pool.get('family.info').search(cr,uid,[('flat', '=', flat_id)])
return values
Code 2:
member_ids = []
for res in cr_res:
member_ids.append((0,0,{'name':res.get('name'),
'flat':res.get('flat'),
}))
values.update(family_members1=member_ids)
return values
In both way i got an error:
AttributeError: 'list' object has no attribute 'iteritems'
Please suggest me a solution thanks.
Use Odoo8 new api:
flat_members1 = fields.One2many(compute='_get_flat_members',
comodel_name='family.info',
string='flat_members1',
store=True)
#api.one
#api.depends('flat_id')
def _get_flat_members(self):
member_ids = []
# get member_ids
self.flat_members1 = member_ids

openerp 7 create method override

I am new OpenERP 7 programming. I have created a booking module that allows a guest to book more than one room. I want to be able to change the room status from available to booked when creating the new reservation. The solution to this kind of scenario seems to be overriding the create or write ORM methods for openERP.
I completely don't know how to incorporate this in my code. Below is part of my code.
class reservation(osv.osv):
_columns = {
'name': fields.char('Reservation No', required=True, select=True, readonly=True),
'date_order':fields.datetime('Date Ordered', required=True, readonly=True),
'reserved_rooms': fields.one2many('hotel.reservation.line','line_id', 'Reserved Rooms'),
'state': fields.selection([('draft', 'Draft'),('confirmed','Confirmed'),('cancelled','Cancelled'),('done','Done')], 'State',readonly=True),
}
reservation()
_defaults = {
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid,'hotel.reservation'),
'state': lambda *a: 'draft',
'date_order': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S')
}
The reservation is created with the default state as draft. How and where in my code do i put and use the create or write method? Thanks.
Try following,
class reservation(osv.osv):
_columns = {
'name': fields.char('Reservation No', required=True, select=True, readonly=True),
'date_order':fields.datetime('Date Ordered', required=True, readonly=True),
'reserved_rooms': fields.one2many('hotel.reservation.line','line_id', 'Reserved Rooms'),
'state': fields.selection([('draft', 'Draft'),('confirmed','Confirmed'),('cancelled','Cancelled'),('done','Done')], 'State',readonly=True),
}
_defaults = {
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid,'hotel.reservation'),
'state': lambda *a: 'draft',
'date_order': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S')
}
def create(self, cr, uid, vals, context=None):
###Add your code here
####update status in vals
return super(reservation,self).create(cr, uid, vals, context=context)
def write(self, cr, uid, ids, vals, context=None):
###Add your code here
####update status in vals
## you will get only those fields into the vals which are updated.
return super(reservation,self).write(cr, uid, ids, vals, context=context)

take field date from another database

in ticket.py. I have two class. class deposit.line and res_partner (inherit). I want to take the date of the class deposit.line but its function in the class res_partner(inherit)
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
obj2 = self.pool.get('deposit.line')
for record in obj2.deposit_line:
temp1 = record.date
print temp1
print result
return result
but the results of its existing print false. what wrong ? please correct my code
PS:
My explanation is less good. but look at my code,surely knowing my explanation.
THIS MY COMPLETE CODE:
class deposit_line(osv.osv):
_name ="deposit.line"
_description = "Deposit Line"
_columns = {
'name': fields.char('Name', size=64),
'ref': fields.char('Reference', size=64),
'amount': fields.float('Amount'),
'date': fields.date('Date', required=True),
'deposit_id': fields.many2one('res.partner', 'Deposit ', required=True, ondelete='cascade'),
}
deposit_line()
class res_partner(osv.osv):
_inherit = 'res.partner'
def _compute_age(self, cr, uid, ids,date_birth,age,arg, context=None):
result = {}
for r in self.browse(cr, uid, ids, context=context):
age=0
if r.date_birth:
age = (datetime.now()-datetime.strptime(r.date_birth,"%Y-%m-%d")).days/365.25
result[r.id] = age
return result
def _compute_dept(self, cr, uid, ids, deposit, available, arg, context=None):
result = {}
for r in self.browse(cr, uid, ids, context=context):
avail=0
temp = r.available
if r.deposit:
avail = r.deposit + temp
result[r.id] = avail
return result
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
obj2 = self.pool.get('deposit.line')
for record in obj2.deposit_line:
temp1 = record.date
print temp1
print result
return result
_columns = {
'speaker': fields.boolean('Leader'),
'event_ids': fields.one2many('event.event','main_speaker_id', readonly=True),
'event_registration_ids': fields.one2many('event.registration','partner_id', readonly=True),
'airline': fields.boolean('Airlines'),
'hotel': fields.boolean('Hotel'),
'date_birth': fields.date('Date of Birth'),
'id_no': fields.char('ID. No', size=20),
'id_expired': fields.date('Expired Date'),
'sex':fields.selection([('male','Male'),('female','Female')],'Sex'),
'age' : fields.function(_compute_age, type='float', method=True, store=True, string='Age', readonly=True),
'deposit': fields.function(_compute_dept2, type='float', method=True, store=True, string='Deposit', readonly=True),
'available': fields.function(_compute_dept, type='float', method=True, store=True, string='Available', readonly=True),
'deposit_ids':fields.one2many('deposit.line', 'deposit_id', 'Deposit Line'),
}
res_partner()
Since you have one2many field for deposit_line defined in the res.partner model, you do not need the to access deposit_line object directly.
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
for partner in self.browse(cr, uid, id, context=context)
result[partner.id]=0
for deposit_line in partner.deposit_ids:
result[partner.id] += deposit_line.amount
return result
After line 3, you forgot to:
obj2.browse(cr, uid, ids, context=context)
You should learn to use the debugger:
Add the line import pdb; pdb.set_trace() where you want to place a breakpoint. When the Python reaches the breakpoint it stops at the console with a (pdb) prompt. There type p obj to print variable obj, n to step to the next instruction, and hfor help. You might find more info in this post and in the docs.