0
votes

Is there any way in Odoo 8 to create a field which is computed only if some condition is fulfilled, otherwise the user will be able to set its value?

Example

I have a model named box, which has a float field named value.

Imagine a box can have several boxes inside, each one which its own value.

So we have a one2many field named child_ids pointing to box and a many2one named parent_id pointig to box too.

Now I want the following behaviour: an user can set the value field of a box which has not any box inside (it means, childs_ids is False), but, if the box has at least one box inside (it means, childs_ids is NOT False), the value field must be computed and it will be the sum of its childs value.

Does anyone have an idea of how to achieve this behaviour?

I put my code, which is not working (the value of value is always being reset to 0):

class box(models.Model):
    _name='box'

    @api.one
    @api.depends('child_ids', 'child_ids.value')
    def _compute_value(self):
        if self.child_ids:
            self.value = sum(
                [child.value for child in self.child_ids])

    def _set_value(self):
        pass

    parent_id = fields.Many2one(comodel_name='box',
                                string='Parent Box')

    child_ids = fields.One2many(comodel_name='box',
                                inverse_name='parent_id',
                                string='Boxes inside')

    value = fields.Float(
        string='Value',
        compute='_compute_value',
        inverse='_set_value',
        store=False,
        required=True,
        readonly=True,
        states={'draft':[('readonly',False)]},
    )
1

1 Answers

2
votes

in the model

computed_field = fields.Char(compute='comp', inverse='inv', store=True)
boolean_field = fields.Boolean()

@api.one
def comp(self):
    ...

@api.one
def inv(self):
    ...

in the view

<field name="boolean_field" />
<field name="computed_field" attrs="{'readonly': [('boolean_field','=',True)]}" />

edit:

now that your example is more clear, i'd say you should change the following:

set value's store parameter to True instead of False and just remove the inverse which, in your case, you don't need.

then you need another 2 fields

value_manual = fields.Float()
manual = fields.Boolean(compute='_is_manual', default=True)

@api.one
@api.depends('child_ids')
def _is_manual(self):
    self.manual = len(self.child_ids) == 0

plus

@api.one
@api.depends('child_ids', 'child_ids.value')
def _compute_value(self):
    if self.child_ids:
        self.value = sum(
            [child.value for child in self.child_ids])
    else:
        self.value = self.value_manual

in the view:

<field name="manual" invisible="1" />
<field name="value" attrs="{'invisible': [('manual','=',True)]}" />
<field name="value_manual" attrs="{'invisible': [('manual','=',False)]}" />

There could be another solution that avoid this double field, maybe using the inverse, but I am not sure.