odoo - get value from many2one field - python

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

Related

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 to make constraint on a field

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)

odoo - display name of many2one field combination of 2 fields

In my module i have the following many2one field:
'xx_insurance_type': fields.many2one('xx.insurance.type', string='Insurance')
where xx.insurance.type is the following:
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 know the many2one field takes the name field as its display name but I would like to have it use the combination of name and insurance_percentage in the form of name + " - " + insurance_percentage + "%"
I read it is best to overwrite the get_name method so I tried the following:
def get_name(self,cr, uid, ids, context=None):
if context is None:
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
res = []
for record in self.browse(cr, uid, ids, context=context):
name = record.name
percentage = record.insurance_percentage
res.append(record.id, name + " - " + percentage + "%")
return res
and placed this inside the ÌnsuranceType` class.
Since nothing happened:
Do i have to place it inside the main class containing the field? If so, is there an other way to do this since that will probably also change the display ways of the other many2one fields?
If you don't want to alter the display name of the rest of the many2one related to the model xx.insurance.type, you can add a context in the XML view to the many2one whose display name you want to modify:
<field name="xx_insurance_type" context="{'special_display_name': True}"/>
And then, in your name_get function:
def name_get(self, cr, uid, ids, context=None):
if context is None:
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
res = []
if context.get('special_display_name', False):
for record in self.browse(cr, uid, ids, context=context):
name = record.name
percentage = record.insurance_percentage
res.append(record.id, name + " - " + percentage + "%")
else:
# Do a for and set here the standard display name, for example if the standard display name were name, you should do the next for
for record in self.browse(cr, uid, ids, context=context):
res.append(record.id, record.name)
return res
#api.depends('name', 'insurance_percentage')
def name_get(self):
res = []
for record in self:
name = record.name
if record.insurance_percentage:
name = '[' + record.insurance_percentage+ ']' + name
res.append((record.id, name))
return res

domain filter for many2one fields in odoo?

Below code is asset inherited class . Here i will add 'place' field with 'Karn/Bang/Kengeri' and 'karn/bang/malleshwaram' for 'Karn/Bang/Kengeri' will add 'asset_catg_id' with A and B. then for 'karn/bang/malleshwaram' with Y and Z.
Now at calander inherited class . if i select 'place' with 'Karn/Bang/Kengeri' then next field 'asset_catg_id' i have to get only A and B drop down list. if again 'karn/bang/malleshwaram' then i have to get only Y,Z options . and previous selected 'asset_catg_id' values should get deleted . i have tried with domain filter option got keyvalue error
class asset_asset(osv.osv):
_inherit = "asset.asset"
#_name = "asset_asset"
_rec_name= "folio_num"
_columns = {
'name': fields.char('Asset Name', size=64),
'place': fields.many2one('asset.parentlocation', 'Location'),
'asset_catg_id' : fields.many2one('asset.catg', 'Asset Catg Selection', select=True, required=True),}
class asset_catg(osv.Model):
_name="asset.catg"
_rec_name='name1'
_description="Define Asset Catgs"
_columns={ 'name1':fields.char('Asset Catg Names',size=64,required=True),}
asset_catg()
class asset_parentlocation(osv.osv):
_name="asset.parentlocation"
_rec_name="location_name"
_columns = {
'location_name' : fields.char('Asset Location', required=True),
'parent_location' : fields.many2one('asset.parentlocation','Parent Location'),
'nameee':fields.many2one('ir.attachment','Attachments'),}
def name_get(self, cr, uid, ids, context=None):
if context is None:
context = {}
if not ids:
return []
reads = self.read(cr, uid, ids, ['location_name','parent_location'], context=context)
res = []
for record in reads:
name = record['location_name']
if record['parent_location']:
name = record['parent_location'][1]+' / '+name
res.append((record['id'], name))
return res
**Following code is calendar inherited class**
class calendar_event(osv.osv):
_inherit = "calendar.event"
_rec_name = 'number'
_columns = {
'number' : fields.char('Meeting ID',readonly=1),
#'place' : fields.many2one('stock.location','Substation Location',),
'place' : fields.many2one('asset.parentlocation','Substation Location',),
#'location' : fields.selection(STATUS_SELECTION,'Location', default='Board A'),
'asset_catg_id' : fields.many2one('asset.catg','Asset Catg Selection', domain="[('asset_catg_id', '=',place)]"),}
First your domain is wrong in a principle. Domain is what is "inside" a field, in other words in its model (for example field name or id in asset.catg model). So you should fix that one first.
If domain depends on another field, you can use onchange method to return domain (used placeholder place_id). Like this:
#api.onchange('place')
def onchange_place(self):
res = {}
if self.place:
res['domain'] = {'asset_catg_id': [('place_id', '=', self.place.id)]}
return res
P.S. This is example with new v8 api, but same principle applies to old api (you then don't nee to use decorator, also add cr, uid, ids on method and call it through your view. All of this not needed for new api). As it looks like you are still developing on old api.
Update
For old api:
def onchange_place(self,cr, uid, ids, place, context=None):
res = {}
if self.place: #on old api it will return id, instead of record
res['domain'] = {'asset_catg_id': [('place_id', '=', self.place)]}
return res
And then in your view (don't know what kind of view you are using):
<field name="place" on_change="onchange_place(place)"/>
Still you need to define some field in asset.catg so it would be used to match place field. For example:
'place_id': fields.many2one('asset.parentlocation', 'Place')
And then when you define asset category, you set which Place it should belong to. Then when you choose place calendar.event, onchange method will set domain on asset_catg_id field correctly.

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