1

I'm doing this official tutorial https://www.odoo.com/documentation/14.0/developer/howtos/rdtraining/11_constraints.html#howto-rdtraining-11-constraints in Odoo 14 docs and have trouble with Python constraint, which doesn't trigger if I change selling_price.

I have this method on selling_price, which change selling_price whenever any offer is accepted (This works fine).

@api.depends('offer_ids')
def _compute_selling_price(self):
    """When any offer is accepted set selling_price"""
    for offer in self.offer_ids:
        if offer.status == "accepted":
            self.selling_price = offer.price
            break
    else:
        self.selling_price = 0

Then I have this python constraint, which should raise ValidationError, whenever selling_price is set and is lower than 90% of the expected price.

@api.constrains('selling_price', 'expected_price', 'offer_ids')
def _check_selling_price(self):
    """Raise Validation Error, if selling_price is lower than 90% of expected price"""
    if float_utils.float_compare(self.selling_price, 0.9 * self.expected_price, precision_digits=2) == -1:
        raise ValidationError("Selling price cannot be lower than 90% of the expected price.")

Attribute selling_price looks like this:

selling_price = fields.Float(readonly=True, copy=False, compute="_compute_selling_price")

The problem is, if I accept any offer, it doesn't do anything. I searched through the internet for some solution but didn't find any answer for this. In their docs, there's also no solution, so maybe I'm doing something different than they do.

PS: float_utils.float_compare just compares 2 floats with precision and return -1, if value1 is lower than value2.

tscunami
  • 45
  • 5

1 Answers1

2

I'm not sure if your solution for setting the selling_price is correct. But in Chapter 4 selling_price is created and called "basic field". That's a contradiction to a computed field, which you've implemented. Even in Chapter 9 (Computed Fields And Onchanges) there is no hint to change selling_price to a computed field.

So first you could try is to set your computed field sellling_price to store in the database, by adding the parameter store=True to the field definition:

selling_price = fields.Float(
    readonly=True, copy=False, store=True,
    compute="_compute_selling_price")

A second approach would be changing selling_price back to a basic field (removing compute parameter) and changing the implementation of setting the selling price, when an offer was accepted. I won't reveal a solution for the second part, because that's what a tutorial is for.

CZoellner
  • 13,553
  • 3
  • 25
  • 38
  • In chapter 10, there is task to create this computed field. ```When an offer is accepted, set the buyer and the selling price for the corresponding property```. If I set store=True as you wrote, it brokes it entirely and even the compute method doesn't do anything. Sure I can add an additional check in compute method, but in that case, the python constraint will be useless and the whole exercise is useless. – tscunami Sep 21 '22 at 15:23
  • 1
    I don't see a statement "implement it as a computed field" in Chapter 10. And i wouldn't implement it that way either. What do you mean by "it brokes it entirely"? Yes adding the check would contradict the chapter goals. – CZoellner Sep 21 '22 at 17:09
  • I removed the compute function and moved the logic on the button press action. Now it seems, it works fine and python constraint finally detects this change and raises ValidationError. Thanks for the hint, that it doesn't have to be a computed field. – tscunami Sep 22 '22 at 07:43
  • 1
    You're welcome. Using the button action would've been my preferred way, too ;-) – CZoellner Sep 22 '22 at 08:11