Odoo Help


2 Answers
27/03/14, 12:24

The working solution is finally:

class product_supplierinfo(Model):
    _inherit = 'product.supplierinfo'

    def _get_product_uom(self, cr, uid, ids, field_name, arg, context):
        res = {}
        for psi in self.browse(cr, uid, ids, context=context):
            res[psi.id] = psi.product_uom_stored.id
        return res

    def _set_product_uom(self, cr, uid, ids, field_name, field_value, arg, context):
        psi = self.browse(cr, uid, ids, context=context)
        psi.write({'product_uom_stored': field_value})
        return ids

    _columns = {
        'product_uom': fields.function(_get_product_uom, fnct_inv=_set_product_uom, type="many2one", relation="product.uom", help="The supplier UoM for this product."),
        'product_uom_stored': fields.many2one('product.uom', "Supplier Unit of Measure", required=True, help="This comes from the product form."),

Olivier Dony (odo)

--Olivier Dony (odo)--

| 8 6 18
Ramilies, Belgio
--Olivier Dony (odo)--


Olivier Dony (odo)
26/03/14, 05:47

Short answer: that's the expected behavior, and you're doing something that is considered a bad practice.

Why does this happen: For many technical and logical reasons, during installations/upgrades the framework needs to handle each module and its dependencies as an isolated set of modules. For instance the product module will be upgraded before loading the modules that depend on product. This is necessary to maintain the modularity of OpenERP and let each module deal with the database and registry state that it should know about.

Why is it a bad practice: Overriding a field to change its type (or make it stored when it wasn't) is one of the few things that will break the encapsulation principle, by seriously changing the original behavior of the parent module rather than simply extending it. The extent of that change means the original module and other modules based on it may suddenly have surprises that could break their logic completely. The OpenERP API contains enough entry points for extending the behavior of other modules that you can always do what you want in a different manner, without breaking this rule. Here you could probably add a new m2o field and override some methods to use it as you need. It will also force you to review the cases where the original field is used and perhaps help you detect cases where you wrongly assumed you could replace the related field by an arbitrary value. For example what happens if the UOM you pick is not compatible with the product UOM, and what if some code elsewhere directly takes the Purchase UOM on the product because it does not expect the one of the supplierinfo to be different?

Some similarly bad practice:

  • Storing a field that is normally not stored (this is what you're doing)
  • Changing the required flag of a stored field from a parent module (at model level, not view level)
  • Overriding methods without calling super()
  • Monkey-patching code from parent modules

You can inherit a model and re-declare some of its fields, but in that case you should not alter anything that will significantly change the model. You can change view-level attributes (such as states, readonly, string, etc.). You can even change its type if the new type is 100% compatible at model level, e.g. replace a char field by a stored function field of type char, with a proper setter and getter that guarantee it will at least keep its old behavior. Anything else is usually a bad idea.

There have been a few cases were official OpenERP modules used to do this (changing a field type), because it often looks easier at first sight, but it was a bad decision in every case, and most of them have been removed now.

The framework gives you a lot of freedom, including the option to shoot yourself in the foot if you really ask for it, but the cases where you'll need that are not very frequent, and you should be ready to deal with the consequences if you're asking for that.

That may not be the answer you expected but I hope it helps a bit... ;-)

26/03/14, 12:15

Thanks for the explanations.

So in my exemple, I should:

  • create a new fields.many2one named product_uom_stored.

  • in place of the existing product_uom field, put a function field, not stored, with a proper setter and getter, that would return the value stored in product_uom_stored.

Would that be the correct way to do?

Olivier Dony (odo)
26/03/14, 14:15

@Weste: yes that solution would probably work without the problems you were facing :)

Ask a Question
Keep Informed
0 follower(s)
About This Community

This platform is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.

Odoo Training Center

Access to our eLearning platform and experience all Odoo Apps through learning videos, use cases and quizzes.

Test it now