|
| 1 | +================== |
| 2 | +Web Backend Action |
| 3 | +================== |
| 4 | + |
| 5 | +.. |
| 6 | + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
| 7 | + !! This file is generated by oca-gen-addon-readme !! |
| 8 | + !! changes will be overwritten. !! |
| 9 | + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
| 10 | + !! source digest: sha256:2c74fe8141e08a0ee82f5bac841673ab92bb84ebeeba5172c98a9a7ac5731710 |
| 11 | + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
| 12 | +
|
| 13 | +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png |
| 14 | + :target: https://odoo-community.org/page/development-status |
| 15 | + :alt: Beta |
| 16 | +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png |
| 17 | + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html |
| 18 | + :alt: License: LGPL-3 |
| 19 | +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github |
| 20 | + :target: https://github.com/OCA/web/tree/18.0/web_backend_action |
| 21 | + :alt: OCA/web |
| 22 | +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png |
| 23 | + :target: https://translation.odoo-community.org/projects/web-18-0/web-18-0-web_backend_action |
| 24 | + :alt: Translate me on Weblate |
| 25 | +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png |
| 26 | + :target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=18.0 |
| 27 | + :alt: Try me on Runboat |
| 28 | + |
| 29 | +|badge1| |badge2| |badge3| |badge4| |badge5| |
| 30 | + |
| 31 | +**Trigger UI actions from backend code in real time.** |
| 32 | + |
| 33 | +This technical module allows you to send standard Odoo actions |
| 34 | +(``ir.actions.*``) from the server to the user’s web client and execute |
| 35 | +them live via the bus. Instead of only showing a toast notification, the |
| 36 | +client actually runs the action when the conditions match. |
| 37 | + |
| 38 | +**Typical use cases include**: |
| 39 | + |
| 40 | +- Open a wizard automatically when a background job finishes (e.g. an |
| 41 | + import summary or a follow-up confirmation dialog). |
| 42 | +- Redirect the user to a specific list/form view after a workflow event |
| 43 | + (approval, status change, external webhook, etc.). |
| 44 | +- React in real time to server-side events by refreshing or changing the |
| 45 | + current screen without manual user navigation. |
| 46 | + |
| 47 | +Backend helpers are provided on ``res.users`` to send actions, |
| 48 | +optionally tagged with a target model (``res_model``), a specific record |
| 49 | +(``res_id``) and allowed view types (``view_types``). A small service in |
| 50 | +the web client listens to the bus channel and only executes the action |
| 51 | +when the current UI context (model / record / view type) matches the |
| 52 | +hints sent from the server. |
| 53 | + |
| 54 | +**Table of contents** |
| 55 | + |
| 56 | +.. contents:: |
| 57 | + :local: |
| 58 | + |
| 59 | +Installation |
| 60 | +============ |
| 61 | + |
| 62 | +This module is based on the Instant Messaging Bus. To work properly, the |
| 63 | +server must be launched in gevent mode. |
| 64 | + |
| 65 | +Usage |
| 66 | +===== |
| 67 | + |
| 68 | +To trigger an action for the current user, call ``_send_action`` on |
| 69 | +``res.users``: |
| 70 | + |
| 71 | +.. code:: python |
| 72 | +
|
| 73 | + action = { |
| 74 | + "type": "ir.actions.act_window", |
| 75 | + "name": "My Wizard", |
| 76 | + "res_model": "my.wizard", |
| 77 | + "view_mode": "form", |
| 78 | + "target": "new", |
| 79 | + "context": { |
| 80 | + "default_some_field": 42, |
| 81 | + }, |
| 82 | + } |
| 83 | +
|
| 84 | + self.env.user._send_action(action) |
| 85 | +
|
| 86 | +This will send a cleaned version of the action to the web client of the |
| 87 | +current user. |
| 88 | + |
| 89 | +**Filter by model (``res_model``)** |
| 90 | + |
| 91 | +If you want the action to run when the user is currently working with a |
| 92 | +specific model. You can pass a ``res_model`` hint: |
| 93 | + |
| 94 | +.. code:: python |
| 95 | +
|
| 96 | + action = { |
| 97 | + "type": "ir.actions.act_window", |
| 98 | + "name": "Order Helper", |
| 99 | + "res_model": "sale.order.helper.wizard", |
| 100 | + "view_mode": "form", |
| 101 | + "target": "new", |
| 102 | + } |
| 103 | +
|
| 104 | + self.env.user._send_action( |
| 105 | + action, |
| 106 | + res_model="sale.order", |
| 107 | + ) |
| 108 | +
|
| 109 | +**Filter by record (``res_id``)** |
| 110 | + |
| 111 | +For form views, it is often useful to restrict execution to a specific |
| 112 | +record (for example, only when the user is looking at a particular |
| 113 | +partner or document). You can pass a res_id value: |
| 114 | + |
| 115 | +.. code:: python |
| 116 | +
|
| 117 | + action = { |
| 118 | + "type": "ir.actions.client", |
| 119 | + "tag": "soft_reload", |
| 120 | + } |
| 121 | +
|
| 122 | + # Only execute when the user is viewing this specific partner record |
| 123 | + self.env.user._send_action( |
| 124 | + action, |
| 125 | + res_model="res.partner", |
| 126 | + res_id=self.id, |
| 127 | + view_types=["form"], |
| 128 | + ) |
| 129 | +
|
| 130 | +**Filter by view type (view_types)** |
| 131 | + |
| 132 | +You can also restrict execution to specific view types, for example only |
| 133 | +in form view or only in list view. Use the ``view_types`` parameter: |
| 134 | + |
| 135 | +.. code:: python |
| 136 | +
|
| 137 | + action = { |
| 138 | + "type": "ir.actions.act_window", |
| 139 | + "name": "Mass Update", |
| 140 | + "res_model": "stock.quant", |
| 141 | + "view_mode": "form", |
| 142 | + "target": "new", |
| 143 | + } |
| 144 | +
|
| 145 | + self.env.user._send_action( |
| 146 | + action, |
| 147 | + res_model="stock.quant", |
| 148 | + view_types=["list"], # only when the user is on a list view |
| 149 | + ) |
| 150 | +
|
| 151 | +If ``view_types`` is omitted or an empty list, no restriction by view |
| 152 | +type is applied. |
| 153 | + |
| 154 | +**Example patterns** |
| 155 | + |
| 156 | +- Update UI after a background job |
| 157 | + |
| 158 | +.. code:: python |
| 159 | +
|
| 160 | + def _cron_enrich_contact(self): |
| 161 | + # ... heavy enrich logic ... |
| 162 | +
|
| 163 | + action = { |
| 164 | + "type": "ir.actions.client", |
| 165 | + "tag": "soft_reload", |
| 166 | + } |
| 167 | +
|
| 168 | + # Ask the client to soft-reload when viewing this contact |
| 169 | + self.env.user._send_action( |
| 170 | + action, |
| 171 | + res_model="res.partner", |
| 172 | + res_id=self.id, |
| 173 | + view_types=["form"], |
| 174 | + ) |
| 175 | +
|
| 176 | +- Notify after creating a record |
| 177 | + |
| 178 | +.. code:: python |
| 179 | +
|
| 180 | + def create(self, vals_list): |
| 181 | + res = super().create(vals_list) |
| 182 | + action = { |
| 183 | + "type": "ir.actions.client", |
| 184 | + "tag": "display_notification", |
| 185 | + "params": { |
| 186 | + "type": "info", |
| 187 | + "title": _("Info"), |
| 188 | + "message": _("Record was created successfully."), |
| 189 | + "next": {"type": "ir.actions.act_window_close"}, |
| 190 | + }, |
| 191 | + } |
| 192 | + # Notify only when the user is on the partner form |
| 193 | + self.env.user._send_action( |
| 194 | + action, |
| 195 | + res_model="res.partner", |
| 196 | + res_id=self.id, |
| 197 | + view_types=["form"], |
| 198 | + ) |
| 199 | +
|
| 200 | +- Ask the user to fill in missing information |
| 201 | + |
| 202 | +.. code:: python |
| 203 | +
|
| 204 | + def _cron_check_employees_data(self): |
| 205 | + # ... find employees with incomplete data ... |
| 206 | + employees = self.search([("some_field", "=", False)]) |
| 207 | +
|
| 208 | + for employee in employees: |
| 209 | + action = { |
| 210 | + "type": "ir.actions.act_window", |
| 211 | + "name": "Complete Employee Data", |
| 212 | + "res_model": "hr.employee.wizard", |
| 213 | + "view_mode": "form", |
| 214 | + "target": "new", |
| 215 | + "context": { |
| 216 | + "default_employee_id": employee.id, |
| 217 | + }, |
| 218 | + } |
| 219 | +
|
| 220 | + # Ask the responsible user to complete data |
| 221 | + employee.user_id._send_action( |
| 222 | + action, |
| 223 | + ) |
| 224 | +
|
| 225 | +Bug Tracker |
| 226 | +=========== |
| 227 | + |
| 228 | +Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_. |
| 229 | +In case of trouble, please check there if your issue has already been reported. |
| 230 | +If you spotted it first, help us to smash it by providing a detailed and welcomed |
| 231 | +`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_backend_action%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. |
| 232 | + |
| 233 | +Do not contact contributors directly about support or help with technical issues. |
| 234 | + |
| 235 | +Credits |
| 236 | +======= |
| 237 | + |
| 238 | +Authors |
| 239 | +------- |
| 240 | + |
| 241 | +* Dinar Gabbasov |
| 242 | + |
| 243 | +Contributors |
| 244 | +------------ |
| 245 | + |
| 246 | +- Dinar Gabbasov < [email protected]> |
| 247 | + |
| 248 | +Maintainers |
| 249 | +----------- |
| 250 | + |
| 251 | +This module is maintained by the OCA. |
| 252 | + |
| 253 | +.. image:: https://odoo-community.org/logo.png |
| 254 | + :alt: Odoo Community Association |
| 255 | + :target: https://odoo-community.org |
| 256 | + |
| 257 | +OCA, or the Odoo Community Association, is a nonprofit organization whose |
| 258 | +mission is to support the collaborative development of Odoo features and |
| 259 | +promote its widespread use. |
| 260 | + |
| 261 | +This module is part of the `OCA/web <https://github.com/OCA/web/tree/18.0/web_backend_action>`_ project on GitHub. |
| 262 | + |
| 263 | +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
0 commit comments