Search code examples
pythoncronodooodoo-11

Odoo 11: get cron id or name inside the called method for ir.cron that are create manually not just the ones that are created from XML


I assigned (m2o) to my_object a cron (Automation->Scheduled Actions). The cron execute (Python code) a method. I need to have the id (or name) of the cron that call the method inside the method to do some actions on the objects assigned to the cron.

I think that the cron-object is not defined when the method execute, but it can be when the method is called. So I think that the way is to pass the id as argument but I don't know how to do so. I tried with "env" without succes.

Cron Python code

<record id="myobject_cron_task" forcecreate='True' model="ir.cron">
    <field name="name">MyModel Task</field>
    <field name="active" eval="True" />
    <field name="user_id" ref="base.user_root"/>
    <field name="interval_number">1</field>
    <field name="interval_type">minutes</field>
    <field name="numbercall">-1</field>
    <field name="model_id" ref="model_my_object"/>
    <field name="state">code</field>
    <field name="code">model.my_method(cron_id)</field>
</record>

Method

def my_method(self, active_cron_id):
    sel_objec = self.env['my.object'].search([('cron_id', '=', active_cron_id)])
    print(sel_objec)

NB: same question asked here without solution


Solution

  • To retrieve the database id of crons that are created from setting menu (no xml_id).

    It turns out that odoo passed the same context also to the execution so anything you add to context you will find it in the context of self in your method, so just add the Id of the cron in the context by just overriding two method:

    from odoo import models, api
    
    class IrCron(models.Model):
        _inherit = 'ir.cron'
    
        @api.model
        def _callback(self, cron_name, server_action_id, job_id):
            """ to handle cron thread executed by Odoo."""
            self = self.with_context(cron_id=job_id)
            return super(IrCron, self)._callback(cron_name,server_action_id, job_id)
    
        @api.multi
        def method_direct_trigger(self):
            """ to handle manual execution using the button."""
            for rec in self:
                # rec = rec.with_context(cron_id=rec.id)
                super(IrCron, rec).method_direct_trigger()
            return True
    

    and in your method:

    def my_method(self):
        cron_id = self.env.context.get('cron_id', False)
        if cron_id:
            cron = self['ir.cron'].browse(cron_id)
            print(cron)
    

    I tested this and It work hope it's easy for you, and no need to pass any argument or anyting in the cron. Hope this what you are looking for. By default Odoo logic don't provide this information so you need to change this behavior. no easy way to do it.