2

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

Charif DZ
  • 13,500
  • 3
  • 13
  • 36
mYmage
  • 77
  • 13

2 Answers2

1

Please try the following code.

def my_method(self, active_cron_id):
    cron = self.env.ref('module_name.myobject_cron_task')
    print(cron)
Charif DZ
  • 13,500
  • 3
  • 13
  • 36
Younis Mahsud
  • 407
  • 4
  • 14
  • your code give me ```External ID not found in the system: module_name.myobject_cron_task``` – mYmage Sep 30 '19 at 19:20
  • 1
    Replace the module_name by the actual module name that you have, the name of your app, the folder that contains your costum module and do the same in my answer too – Charif DZ Sep 30 '19 at 19:54
  • Thanks @CharifDZ (I'm not a dragon on Odoo/Python ;-)) and I confirm that with different cron that call the same method the returned id is only one. – mYmage Sep 30 '19 at 20:33
1

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.

Charif DZ
  • 13,500
  • 3
  • 13
  • 36
  • Your code give me ```name 'cron_id' is not defined``` evaluating the cron Python code – mYmage Sep 30 '19 at 19:26
  • Sorry forgot to remove it from the call, just use it as a keyword arguement, don't pass it as arguement sorry about that check my edits – Charif DZ Sep 30 '19 at 19:52
  • I tried it before but now the message is ```External ID not found in the system: app_name.myobject_cron_task``` always evaluating Python code. – mYmage Sep 30 '19 at 20:02
  • Yes you should replace the app_name by the name of the folder, like. `sale.som_xmli_id` or `purchase.som_xml_id`, what is the name of the folder that contains `__manifest__.py` replace `app_name` with it – Charif DZ Sep 30 '19 at 20:07
  • I fixed the error and now it works but don't solves the problem. To have different results I have to change the xml-id called ```cron_id="app_name.myobject_cron_task"``` to ex. ```cron_id="app_name.myobject2_cron_task"``` and these means that I have to preset all the crons with xml. What happen if I duplicate a cron? It returns the id of the original one, instead I need the id of the new one. – mYmage Sep 30 '19 at 20:46
  • I have some bad news for you, there is no way to get the database id of the ir.cron inside the code, I checked the variable passed to `safe_eval` nothing contains the ID, so I came up with an Idea to work around that , and retrieve the ID of cron by a special key in the name of the cron this will work for sure hope you find it easy to implement good luck – Charif DZ Sep 30 '19 at 21:46
  • Thanks for your edit but I did a similar thing as first solution simply adding a filed m2o cron_key to the object ```cron_key = fields.many2one("myobject.cronkey", "Cron Key")```, passing the key name in method call ```model.my_method('my_cron_key')``` and filtering object on the associated key ```def my_method(self, active_key): sel_objec = self.env['my.object'].search([('cron_key', '=', active_key)])``` I keep trying, mybe the solution is behind the corner. – mYmage Oct 01 '19 at 11:13
  • Okay I think I found a simple solution for by just override two method of `ir.cron` to pass the Id. – Charif DZ Oct 01 '19 at 18:50
  • sorry about docs string I mixed them, `method_direct_trigger` is the one called from the button. – Charif DZ Oct 02 '19 at 09:23
  • You anticipated me: these solves the problem (I only unchecked the comment on method_direct_trigger rec var). You are right that these solution could be a problem if something will change in the future but for now it is the only solution. In case, it can be usefull to create a PR to integrate the base model. Well done Charif! – mYmage Oct 02 '19 at 09:28
  • good news for you it doesn't change any thing, it's a perfect solution I didn't override any method code, I just called them after adding a key to context. don't worry about it, I thought that I have to rewrite the code of `_callback` to pass the id for `safe_eval`. – Charif DZ Oct 02 '19 at 09:31