I have a selection field in account.invoice.line named form_type. It has three selection options:
1) form_a
2) form_b
3) form_c
There is also an integer field named flag in account.invoice.line. When form_c is selected, the flag value should be set to 1; otherwise, if either form_a or form_b is selected, the flag value should be set to 0. I wrote an onchange function for the above case but it's not working. Can someone help me out? What is wrong in my code?
def onchange_form_type(self, cr, uid, ids, invoice, context=None):
val={}
flag=0
invoice = self.pool.get('account.invoice.line').browse(cr, uid, invoice)
for invoice in self.browse(cr, uid, ids, context=context):
if invoice.form_type=="form_c":
flag="1"
else:
flag="0"
print flag
val = { 'flag': flag, }
return {'value': val}
My XML code in account.invoice.line for onchange is:
<field name="form_type" on_change="onchange_form_type(form_type)"/>
In your on-change function you don't need to call the browse function of the object, because the values are not stored in the database yet. Also, you are passing the "form_type" value to the function and not the object id(as browse accepts object id).
So, below will be the on_change function, for the expected requirement:
def onchange_form_type(self, cr, uid, ids, form_type, context=None):
val={}
flag=0
if form_type == 'form_c':
flag="1"
val = { 'flag': flag }
return {'value': val}
Related
I am setting up default value of analytics_id in account.move.line by below code
class account_move_line(models.Model):
_inherit = 'account.move.line'
_name = "account.move.line"
def _get_default_account(self, cr, uid, context=None):
obj = self.pool.get('account.move')
value = obj.browse(cr, uid, uid)
if value.move_id.debit>0 or value.move_id.credit<0:
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,
}
it is working well for me but now i want to set this default value if debit field value is greater then zero OR credit field value less then zero otherwise analytics_id field remain empty.
Try to use this type of code
res = self.pool.get('account.analytic.plan.instance').search(cr, uid, [('code','=','LAL')], context=context)
if res:
br_analytic_plan=self.pool.get('account.analytic.plan.instance').browse(cr,uid,res[0],context=context)
if ---your Condition---- # You can access For example. br_analytic_plan.amount > 0
return res[0]
This same logic you can apply to both groups condition (it means under if and else on your current code).
Hope this helps.
def onchange_product_id(self, cr, uid, ids, product_id, context=None):
val = {
'name': product_id,
}
return {'value': val}
<field name="product_id" on_change="onchange_product_id(product_id, context)"/>
<field name="name"/>
I have the value in one2many (product1, product2) when I select 'product2' the function onchange_product_id returns the value of 2 instead of product2 and it appears on field 'name'.
This is only happens when I am using on_change in many2one,one2many.... relationship but in char,int and float the value of function returns correct.
My question is how can I get the correct value of one2many using on_change function ?
Thanks,
You need to do something like ,
def onchange_product_id(self, cr, uid, ids, product_id, context=None):
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
val = {
'name': product and product.name or '',
}
return {'value': val}
Because product_id contains and id not the browsable record. So first you need to browse that record and then need to fetch the name of product.
I added a module "Base Candidat" in this module base.candidat I want to open the applications of a specific candidate (that have the same email as the candidate ) I added this function to base_candidat.py
class base_candidat(osv.osv):
_columns = {
'candidat_name': fields.char('Candidat', size=128, required=True),
'blacklist': fields.boolean('Blacklist'),
'email_candidat': fields.char('Email', size=32),
'mobile': fields.char('Mobile', size=32),
'priority': fields.selection(AVAILABLE_PRIORITIES, 'Appreciation'),
'user_id': fields.many2one('res.users', 'Responsable'),
'specialite': fields.many2one('base.candidat.specialite', 'Spécialité'),
}
def action_get_applications(self, cr, uid, ids, context=None):
modelDataClass = self.pool.get('ir.model.data')
hrApplicantClass = self.pool.get('hr.applicant')
model, action_id = modelDataClass.get_object_reference(cr, uid, 'hr_recruitment', 'action_hr_job_applications')
action = self.pool.get(model).read(cr, uid, action_id, context=context)
email_ids = self.browse(cr, uid, ids[0], context).email_candidat
candidature_ids = hrApplicantClass.search(cr, uid, [('email_from', '=', email_ids)], context=context)
action['context'] = {'default_res_model': self._name, 'default_res_id': ids[0]}
action['domain'] = str([('candidature_ids', 'in', email_ids)])
return action
I have no result . Any suggestions??
If I know well, 'action' is an unallowed variable name. If you use it, the program will be not consistent. (Same situation with 'active')
In my opinion, this domain expression is not correct in this line:
action['domain'] = str([('candidature_ids', 'in', email_ids)])
Because this mean you model has candidature_ids field, but the model has not, so this condition can't satisfied, so you can't see any record, when you use it.Another problem with your conception, email_ids is string (not number, so the variable name is deceptive)and candidature_ids is a list of numbers.
In my opinion, you want to write a function field. This is an example code, it may not the optimum performance, but I think it will help you understanding the essential of function field:
def _getApplications(self, cr, uid, ids):
hrApplicantClass = self.pool.get('hr.applicant')
# get all of candidate
candidateDatas = self.read(cr, uid, ids, ['email_candidat'])
# collect all of emails
emails = []
for candidate in candidateDatas:
if candidate['email_candidat'] not in emails:
emails.append(candidate['email_candidat'])
# get all of relevant applicant
applicantIds = hrApplicantClass.search(cr, uid, [('email_from', 'in', emails)])
applicantDatas = hrApplicantClass.read(cr, uid, applicantIds, ['email_from'])
# pair base_candidat id with application id
retVal = {}
for candidate in candidateDatas:
retVal[candidate['id']] = []
if not candidate['email_candidat']:
continue
else:
for applicant in applicantDatas:
if applicant['email_from'] == candidate['email_candidat']:
retVal[candidate['id']].append(applicant['id'])
return retVal
# the field definition
'application_ids': fields.function(_getApplications, method=True, type='one2many', 'Applications')
I'm trying to show a res.partner field, which is called phone into the treeview of a sale.order.
But it is not showing anything, just the name of the field without data. This is my code on sale.order
phone : fields.char('Telefono del Cliente'),
Onchange function for this field:
def onchange_phone(self, cr, uid, ids, phone, context=None):
res = {}
if phone:
obj = self.pool.get('res.partner')
browse(cr, uid, phone)
res['phone'] = obj.phone
return {'value' : res}
On res.partner the field is also called phone which is obviously the client's phone, i need to show it on the sale.order treeview, this is the code on my sale_view.xml:
<field name="phone" on_change="onchange_phone(phone)"/>
Any ideas?
Thanks in advance.
As a suggestion, If you want phone number of partner, than you should not create on_change of phone field. You can get phone number in 2 ways.
First way and best way, In sale.order, onchange_partner_id() method is their, you need to override that method and update vals with phone number of partner.
And Second way and long way, You may override create() method and write() method of sale.order.
create() method trick:
in create() method, you can take partner id from the context. For example vals.get('partner_id')
write() method trick:
in write() method, you have id of created record so you need to simply browse that record and write phone number of partner.
As Odedra suggested, you should do this like so (this is taken from sale.py file):
def onchange_partner_id(self, cr, uid, ids, part, context=None):
if not part:
return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False, 'payment_term': False, 'fiscal_position': False}}
part = self.pool.get('res.partner').browse(cr, uid, part, context=context)
addr = self.pool.get('res.partner').address_get(cr, uid, [part.id], ['delivery', 'invoice', 'contact'])
pricelist = part.property_product_pricelist and part.property_product_pricelist.id or False
payment_term = part.property_payment_term and part.property_payment_term.id or False
fiscal_position = part.property_account_position and part.property_account_position.id or False
dedicated_salesman = part.user_id and part.user_id.id or uid
phone = part.phone or False
val = {
'partner_invoice_id': addr['invoice'],
'partner_shipping_id': addr['delivery'],
'payment_term': payment_term,
'fiscal_position': fiscal_position,
'user_id': dedicated_salesman,
'phone': phone,
}
if pricelist:
val['pricelist_id'] = pricelist
return {'value': val}
Note that you should not do that on base module, but instead create your own module and inherit it to sale.order model. What is more, onchange will not work on tree view (like you suggested), but you can easily show it on the tree - you have to first put it on your form with the onchange provided, then modify tree view to show phone number.
I want to calculate the value of a function field using its previous value ( = value of the record with previous id)
'testrest' : fields.function(get_reste, method=True, string='Restant',type='integer'),
def get_reste(self, cr, uid, ids, field_name, arg, context):
x = {}
for record in self.browse(cr, uid, ids ,context):
if record.statut != 'entree':
x[record.id]= a + record.entree_nbr # a should be the same field for the previous record
How can I do that? thank you
First point here about OE 6.1+ and fields.function() : it does not take a method parameter anymore [ Server rev 3495 revid odo#openerp.com-20110701232328-flgxulxva70vnyxr and addons rev 4844].So please do not use the "method" parameter anymore!
Now you want to calculate the value based on previous value so what you can do is you can use store=True param here that will store your previous value in data now in your calculation for your record you can read previous value and calculate new value and return it.
'testrest' : fields.function(get_reste, store=True, string='Restant',type='integer'),
def get_reste(self, cr, uid, ids, field_name, arg, context):
x = {}
for record in self.browse(cr, uid, ids ,context):
if record.statut != 'entree':
x[record.id]= record.testrest + record.entree_nbr
return x
Here benefit of string will be you can use this value any where out side OE or fro some external reporting tool and you can even expoer this field.
Hope this will help.
Some More Code :
'price': fields.function(_price_get, method=True, string="Price", store=True),
def get_reste(self, cr, uid, ids, field_name, arg, context):
x = {}
a = 0.0
for record in self.browse(cr, uid, ids ,context):
if record.statut != 'entree':
x[record.id]= a + record.entree_nbr
a =record.testrest
return x
If you need you can sort the list of ids by ids.sort()