This question has been flagged

I'm trying to make a field's default value the result of computing some of it's related objects' fields. How can I achieve that?

In this case, I have an Item that has multiple Payments (one2many). The item has its total cost as a field, and every Payment has it's amount (i.e., it can be a partial Payment). I want the default value of a new Payment's amount to be the balance of the item (say, the total cost of the Item, minus the sum of all current Payments' amount for that Item).

How can I get this done?

My current classes:

from osv import fields, osv

class item_payment(osv.osv):
    def _item_balance(self, cr, uid, ids, context):
        for id in ids:
            this_payment = self.browse(cr, uid, id)
            item_payments = self.search(cr, uid, [('project_item_id', '=', this_payment.project_item_id)])
            total_payed = item_payments.reduce((lambda acum, payment: acum + payment.amount), 0)
            this_item = self.pool.get('sade.project.item').browse(cr, uid, this_payment.project_item_id)
            res[id] = this_item.amount - total_payed
        return res

    _name = "item.payment"
    _columns = { 'amount' : fields.float('Amount', digits = (16,2)),
                'project_item_id' : fields.many2one('item', 'Item', ondelete = 'set null')
                }
    _defaults = { 'amount' : _item_balance }

class item(osv.osv):
    _name = "item"
    _columns = { 'amount' : fields.float('Importe', digits = (16, 2)),
                'payments' : fields.one2many('item.payment', 'project_item_id', 'Pagos')
                }

item()
item_payment()

I'm getting this error:

Traceback (most recent call last):
  File "/usr/share/pyshared/openerp-server/osv/osv.py", line 122, in wrapper
    return f(self, dbname, *args, **kwargs)
  File "/usr/share/pyshared/openerp-server/osv/osv.py", line 176, in execute
    res = self.execute_cr(cr, uid, obj, method, *args, **kw)
  File "/usr/share/pyshared/openerp-server/osv/osv.py", line 167, in execute_cr
    return getattr(object, method)(cr, uid, *args, **kw)
  File "/usr/share/pyshared/openerp-server/osv/orm.py", line 985, in default_get
    defaults[f] = self._defaults[f](self, cr, uid, context)
TypeError: _item_balance() takes exactly 5 arguments (4 given)

I'm currently using OpenERP v6.1, if that matters.

Avatar
Discard
Best Answer

A solution is to use a function as default value for your field:

def _your_function(self, cr, uid, context=None):
    your code here
    ...
    ...
    ...
    return field_value

_defaults = {
    'your_field' : _your_function,
    }
Avatar
Discard
Author

Thanks for the quick reply, but _defaults' functions seem to not receive an ids parameter (has sense, as the new instance still doesn't exist - it has no id). I'm updating the question now with further detail I could add after your advice.

I'm sorry, the correct function is _your_function(self, cr, uid, context=None):

Author

But, how could I grab the project_item_id value for the new Payment I'm creating now that I don't have an id? I'm lost with this, though I'm pretty sure this has to be extremely trivial.

You can't use a browse in a record that noe exist, yet. I think you need to change amount as function fiueld and calculate it whee the user save the page.