Search code examples
pythonodooopenerp-7

Querying an object in OpenErp 7


I have two objects,'article' and 'mvt', the logic behind the module am trying to create is that an article is defined by a name and a price, but the quantity is calculated through a set of transactions or 'mouvements', each mouvement has a realtion of many2one with an article, a date and a qte, the last field can be either positive or negative (positive means we added new articles, negative the opposite), so here's the code i used to do this, i am kind of new to openErp.

class article(osv.osv):

_name = 'cm.article'

def _get_qte(self, cr, uid, ids, fld_name, arg, context=None):
    result = {}
    mvtObject=self.pool.get('cm.mvt')
    mvtids=mvtObject.search(cr,uid,[])
    sum = 0
    for id in mvtids:
        mvt_line=mvtObject.browse(cr,uid,id,context)
        if mvt_line.article.id == ids[0]:
            sum = sum + mvt_line.qte
    result[sum] = sum
    return result
_columns = {
        'name': fields.char(size=32, string='Nom', required=True),
        'pu':fields.float(required="True",string='Prix Unitaire'),
        'qte': fields.function(_get_qte,type='integer',obj="cm.article",method=True,string='Quantity'),
}
article()


class mvt(osv.osv):
    _name = 'cm.mvt'
    _columns = {
        'article' : fields.many2one('cm.article', 'name'),
        'date' : fields.datetime(string="Date Mouvement"),
        'qte':fields.integer(String="Quantity")
    }
    _defaults = {'date' : fields.date.context_today}
mvt()

Thank you in advance.


Solution

  • We did something very similar and it worked perfectly.

    Just beware, after a large number of transactions, the code will become slow as you have to recalculate each time you open the form. You will have to write a "purge" wizard that will summarise transactions older than say three years. It all depends on the number of transactions and local legislation.

    To access the movements for each transaction add the following line to your columns in your articles model:

    'art_movements':fields.one2many('cm.history', 'article', 'Movements'),
    

    I would also suggest that you add a description field to the mvt class:

    'name':fields.char('Short movement description'),
    

    To see all the data you will use xml that looks like this:

    <record model="ir.ui.view" id="view_articles_form">
        <field name="cm.article">Articles.form</field>
        <field name="model">cm.article</field>
        <field name="type">form</field>
        <field name="arch" type="xml">
            <form string = "Articles" version="7.0" create="false" edit="false">
                <sheet>
                    <group>
                        <field name="name"  readonly="True"/>
                        <field name="pu"  readonly="True" />
                        <field name="qty"  readonly="True"/>
                    </group>
                    <field name="art_movements">
                        <tree string="History" default_order="date">
                            <field name="name"/>
                            <field name="date"/>
                            <field name="qte"/>
                        </tree>
                    </field>
                </sheet>
            </form>
        </field>
    </record>
    

    My guess is that the cause of your problem originates in the function field because there was no link between the two tables. The above code should fix it, but your function field is not correct, see below (You will have to verify the code as I did not test it, but the principle is correct).

    def _get_qte(self, cr, uid, ids, fld_name, arg, context=None):
    
        res={}
        qty=0.0
        for record in self.browse(cr, uid, ids, context=context):    
            if record.art_movements:
                for movement in record.art_movements:
                    qty=qty+movement.qte
            res[record.id] = qty
        return res
    

    Note that if there is no records in art_movements, it will return a value of zero.