Way to override field function in v8 - python

I want to override a original field function in Odoo.
According to the answer here: Odoo: How to override original function
i just have to define exactly the same method as in the original model. So here is my code:
class paiement_client_difference_montant(models.Model):
_inherit="account.voucher"
#writeoff_amount=fields.Float(compute='_get_writeoff_amount')
def _get_writeoff_amount(self, cr, uid, ids, name, args, context=None):
print '_get_writeoff_amount _inherit'
if not ids: return {}
currency_obj = self.pool.get('res.currency')
res = {}
for voucher in self.browse(cr, uid, ids, context=context):
debit = credit = 0.0
sign = voucher.type == 'payment' and -1 or 1
for l in voucher.line_dr_ids:
debit += l.amount
for l in voucher.line_cr_ids:
credit += l.amount
currency = voucher.currency_id or voucher.company_id.currency_id
res[voucher.id] = currency_obj.round(cr, uid, currency, voucher.amount - sign * (credit - debit))
return res
But that code is never reached.
Any help please. Thank you.

You have to override that field again in your class, to execute this newly created method.

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.

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

override create method with multiple returns in OpenERP ver 7

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)

openerp sum function for relational fields

In Openerp, we have object_A with one one2many field belonging to object_B. Object_B has a float field. In object_A we have a one2many_list widget for the corresponding object_B so naturally we'd have multiple rows for each new record.
I know it's trivial but I'm having a hard time writing a function in object_A to sum up the total value of Object_B float column. What i have so far is something like that:
def get_result(self, cr, uid, ids):
total = {}
for obj in self.browse(cr, uid, ids):
result=0.0
total[result]+= obj.o2m_field.float_field
return total
The code provided by #DReispt should work, and if you approve an answer, please approve his, and not mine.
The important thing to understand is that a function field in OpenERP returns a dictionary with the object ids for the key and the value of the field for the given object as the associated value.
In your orginal code:
result = 0.0
total[result] += anything
would result in a KeyError since the dictionary is empty originally (total = {} at the beginning of your code).
A shorter version of DReispt code would be
def get_result(self, cr, uid, ids, context=None):
total = {}
for obj in self.browse(cr, uid, ids, context=context):
total[obj.id] = sum(o2m.float_field for o2m in obj.o2m_field)
return total
This version takes advantage of Python's generator expression which can be passed to the sum() built in function. It is also slightly faster, because you avoid accessing the total dictionary multiple times for each object.
You need to loop the o2m:
def get_result(self, cr, uid, ids, context=None):
total = {}
for obj in self.browse(cr, uid, ids, context=context):
total[obj.id] = 0
for o2m in obj.o2m_field:
total[obj.id] += o2m.float_field
return total
#example: {56: 12.34, 57: 56.78}
Just for kicks, doing it the functional way:
def get_result(self, cr, uid, ids, context=None):
return {obj.id: sum(o2m.float_field for o2m in obj.o2m_field)
for obj in self.browse(cr, uid, ids, context=context)}

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