Search code examples
odooodoo-online

Odoo online requests not defined in actions


I have a very simple scheduled action I'd like to implement

webhook_url = 'https://xxxxx'

recs = model.search([("x_studio_processed", "=", False)])

for rec in recs:
    data = recs.x_studio_json_text    # json_text is just a text field with json in it.
    requests.post(webhook_url, data=data)

However I'm getting the following error, which didn't happen in the automated action version of this script.

RPC_ERROR
Odoo Server Error
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/tools/safe_eval.py", line 391, in safe_eval
return unsafe_eval(c, globals_dict, locals_dict)
File "ir.actions.server(1049,)", line 21, in <module>
NameError: name 'requests' is not defined

Is this a feature? Is there a workaround? I can think of one, but I'm new to Odoo and have no access to the code (I did mention this was Odoo online), and even this workaround is not guaranteed:

Basically, use the scheduled action to trigger an automated action (updating a field should do), and use the automated action script's request object.

Any thoughts or ideas? I'm looking for simpler, Odoo-esque ways to handle this.

EDIT: I tweaked the description, because it turns out that both action types don't have requests defined. I suspect that the requests that worked in an automated action were being done on an odoo.sh or homegrown odoo install.

So for Odoo online, even my workaround has failed. My next try (a true work around :) ) is to use the external api to get these records, and then call whatever webservice I need.


Solution

  • Round about solution:

    Using a record to store the future request (the json to send to the server), the scheduled automation set's a field on that meta record to trigger a webhook. I created a "spinner" - just increment it to trigger the webhook - it thus keeps track of number of attempts and makes testing super easy.

    Nothing special about the webhook - it just calls the server with the payload in the meta record.

    The script on the serverside returns back a success response asap. This can be before storing or processing the data since this is not processed by a user script in Odoo.

    Using PHP, call this function:

    function end_connection()
    {
            set_time_limit(0);
    
            session_write_close();
            fastcgi_finish_request();
    
            return;
    }
    

    While conceptually you don't have to do this, with Odoo you should because it has a pretty tight window for handling webhooks, and Re:my original problem, it doesn't allow you to interact with a failed or timed out request.

    When you have enough information to let Odoo know of the results of the call, Call a webhook in odoo, making sure in the json response to specify the model and record id of the meta record:

    $postdata = json_encode(["_model" => $jsonResponse->data['_model'], "_id" => $jsonResponse->data['_id']]);
    

    On the odoo side, the webhook calls a set field action with the default record being the specified record - the is_processed field that the scheduled automation uses to filter for records already sent. In my case this is sufficient since I just want to know that the information was saved into a db, which is a simple yes or no. But feel free to process the "return" hook for more complex processing. Keep in mind that responding to a webhook is also time bound without notification, so it's better to save the response and have a scheduled automation deal with the results.