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')
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.
I created a method with scheduled action.
Object: 'product.product'
What I want to achieve is to send notifications to the purchasers group if the product is out of stock.
So far I have this code:
class product_product(osv.osv):
_name = 'product.product'
_inherit = ['product.product', 'mail.thread', 'ir.needaction_mixin']
def notification(self, cr, uid, context=None):
product_uom_obj = self.pool.get('product.uom')
partner_obj = self.pool.get('res.partner')
user_obj = self.pool.get('res.users')
group_obj = self.pool.get('res.groups')
partners = []
followers = []
group_users= group_obj.search(cr, uid, ['&', ('category_id.name', '=', 'Purchases'), ('name', '=', 'User')])
for recipient in group_obj.browse(cr, uid, group_users).users:
partners.append(recipient.id)
for partner in partners:
for follower in user_obj.browse(cr, uid, partner).partner_id:
followers.append(follower.id)
products = self.search(cr, uid, [('type', '=', 'product')])
for product in products:
for prod in self.browse(cr, uid, product):
#check if the product is out of stock
So how can I check if the product is out of stock?
You can check the Stock of the Products using prod.product_tmpl_id.qty_available , but to get the qty_available field for product.template you have to install stock module also. So, in depends of openerp.py add stock also.
for prod in self.browse(cr, uid, products):
#check if the product is out of stock
if prod.product_tmpl_id.qty_available<=0:
#Send mail using message_post method
In your code for product in products: is not required. you can directly send the products list of ids to browse method
To Send a mail only to the Suppliers of the Product while Confirming the Sale Order is
def action_button_confirm(self, cr, uid, ids, context=None):
ret = super(sale_order, self).action_button_confirm(cr, uid, ids, context=context)
for order in self.browse(cr, uid, ids, context=context):
for line in order.order_line:
if line.product_id and line.product_id.product_tmpl_id.qty_available<=0:
partnerids = []
for suppinfo in line.product_id.seller_ids:
if suppinfo.name.email:
partnerids.append(suppinfo.name.id)
post_values = {
'partner_ids': partnerids,
'subject':"Send '%s' Stock of %s Quantity"%(line.product_id.name,line.product_uom_qty),
'body': '<div><p>Dear Seller,</p>'
'<p>Please send us "%s" Product Stock of %s Quantity as soon as Possible.</p></div>'
'<p>Regards,</p>'
'<p>%s</p>'%(line.product_id.name,line.product_uom_qty,order.company_id.name),
}
msg_id = self.message_post(cr, SUPERUSER_ID, [order.id], type='email', subtype=False, context=context, **post_values)
return ret
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 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()
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}