How to make constraint on a field - python

I want to perform a constraint on the jrestant that returns me the number of days between two dates which must also be positive.
How to make constraint on a field?
def compa_date(self,cr,uid,ids,args,fields,context=None):
res = {}
for self_brow in self.browse(cr,uid,ids,context):
if self_brow.Date_ouv_pli or self_brow.date_depot:
date_debut = datetime.strptime(self_brow.Date_ouv_pli,'%Y-%m-%d')
date_fin = datetime.strptime(self_brow.date_depot,'%Y-%m-%d')
res[self_brow.id] = (date_debut - date_fin).days
return res
_columns = {
'date_depot' : fields.date('Date dépot de soumission'),
'Date_ouv_pli' : fields.date('Date Ouverture Plis'),
'jrestant': fields.function(compa_date,string='Jours restant')
}
def _check(self, cr, uid, ids, context=None):
for product in self.read(cr, uid, ids, ['jrestant'], context=context):
if jrestant < '0' :
return False
return True
_constraints = [(_check, 'Days must be positive', ['jrestant'])]

Set store to True so the value of the functional field will be stored in the database, which allows you to set constraints on it.
'jrestant': fields.function(compa_date, string='Jours restant', store=True)

Related

Set default value of field depends on other field in odoo

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.

How to write maximum value of tree view in odoo?

I have one tree view have 3 columns . I wanted to get maximum of each column in function field ?
class feeder_data(osv.Model):
_name = "feeder.data"
_rec_name= "company_id1"
_columns = {
'company_id1': fields.many2one('res.company', 'Substation', required=True),
'combine2':fields.one2many('data.value','combine','Details'),
'max_mw': fields.function(_amount_line, string='Subtotal',type='integer'),
}
class data_value(osv.Model):
_name = "data.value"
_rec_name = "mega_wat"
_columns={
'Hours':fields.integer('Hours'),
'mega_wat':fields.integer('Mega Watts'),
'combine':fields.many2one('feeder.data','details'),
}
Here I do have tree view in data.value. In this class I have mega_wat field here I will enter values in hourly_feeder class i have one field as max_wt i wanted to have function field with max of mega_wat in it
First, create the max function in your model:
def _get_max_of_tree(self,cr,uid,ids,context=None):
res={}
for o in self.browse(cr, uid, ids, context):
res[o.id] = max(0.col1 , o.col2, o.col3)
return res
then create a function field for it
_columns = {
...
'mymax' : fields.function(_get_max_of_tree, type='float'),
...
}
EDIT:
In you situation, it should be like this:
class feeder_data(osv.Model):
_name = "feeder.data"
_rec_name= "company_id1"
def _amount_line(self,cr,uid,ids,context=None):
res={}
for fd in self.browse(cr, uid, ids, context):
res[fd.id] = max([dv.mega_wat for dv in fd.combine2])
return res
_columns = {
'company_id1': fields.many2one('res.company', 'Substation', required=True),
'combine2':fields.one2many('data.value','combine','Details'),
'max_mw': fields.function(_amount_line, string='Subtotal',type='integer'),
}
Use Built in Max function.
Help on built-in function max in module builtin:
max(...)
max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.
Or you can define your own function.
def max_number(a, b, c):
Max = a
if b > Max:
Max = b
if c > Max:
Max = c
return Max
Your functional fields should be like this,
def _amount_line(self, cr, uid, ids, field_names, arg=None, context=None):
res = {}
for obj in self.browse(cr, uid, ids, context=context):
max = 0
for data in obj.combine2:
if data.mega_wat > max:
max = data.mega_wat
res[obj.id] = max
return res

How can I get filtred data from a view?

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')

odoo - get value from many2one field

My code:
class SaleOrder(osv.Model):
_inherit = 'sale.order'
_columns = {
'xx_delivery_date': fields.date(string='Delivery date'),
'xx_payment_method': fields.many2one('xx.payment.method',
string='Payment method'),
'xx_insurance_type': fields.many2one('xx.insurance.type', string='Insurance')
}
def _amount_insurance(self, cr, uid, val1, context=None):
val = 0.0
insurance_chosen = self.pool.get('xx.insurance.type').browse(cr, uid, insurance_percentage.id,context=context)
val = val1*insurance_chosen/100
return val
class InsuranceType(osv.Model):
_name='xx.insurance.type'
_columns = {
'name' : fields.char(size=128, string = 'Name'),
'sale_ids': fields.one2many('sale.order', 'xx_insurance_type', string = 'Sale orders'),
'insurance_percentage' : fields.float('Insurance cost in %')
}
I am trying to get the float from the 'insurance_percentage' field and add this percentage to val1.
At the moment my code results in
'Global name insurance_percentage not defined,
So I have to somehow tell the function to take the variable from the InsuranceType class but I don't know how to do this.
For many2one field, we need to first take id of that record and than browse that record with id and take desire value from that.
Try with this code:
def _amount_insurance(self, cr, uid, ids, val1, context=None):
val = 0.0
for insurance in self.browse(cr, uid, ids,context=context):
if insurance.xx_insurance_type:
val = (val1 * (insurance.xx_insurance_type.insurance_percentage/100))
return val

OpenERP: Function field

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()

Categories

Resources