Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[18.0][MIG] usability_webhooks #242

Open
wants to merge 45 commits into
base: 18.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
8e01f10
[ADD] usability_webhook
Saran440 Apr 20, 2022
6baabb4
[FIX] convert type
Saran440 Aug 3, 2022
1be9bb0
[15.0][MIG] usability_webhook
Saran440 Jun 29, 2023
d096274
[ENH] webhook logs and test itself
Saran440 Aug 10, 2023
d7dee90
[FIX] add create date on list view
Saran440 Aug 11, 2023
ce36653
[FIX] create logs after done
Saran440 Aug 11, 2023
4093452
[FIX] return api.log with false exception
Saran440 Aug 15, 2023
95411f0
[FIX] rollback api configuration on system parameter
Saran440 Aug 15, 2023
8e84f39
[FIX] self to request
Saran440 Aug 15, 2023
03fc226
[FIX] api log view
Saran440 Aug 24, 2023
ab62639
[ENH] api logs
Saran440 Sep 13, 2023
5f27af4
[IMP] usability_webhooks: pre-commit stuff
Saran440 Nov 28, 2023
102162a
[MIG] usability_webhooks: Migration to 16.0
Saran440 Nov 28, 2023
4930710
[ENH] webhooks: search_data by query
Saran440 Dec 8, 2023
51670c7
[FIX] traceback error when call api is not success
Saran440 Dec 14, 2023
b414600
[UPD] send context for function create()
Saran440 Dec 27, 2023
202e0d6
[ENH] usability_webhook: performance with cache
Saran440 Apr 10, 2024
76d7a49
[FIX] usability_webhooks: improved word error with key
Saran440 Apr 11, 2024
f1ae7d9
[ENH] webhooks_usability: enhance auto-vacuum log
Saran440 Apr 23, 2024
681c48c
[UPD] copier update
Saran440 Jul 17, 2024
d95c95e
[UDP] usage update
Pani-k-folk Jul 26, 2024
9654968
[ENH] add new api for call method
Pani-k-folk Aug 20, 2024
1252486
[UDP] usage update
Pani-k-folk Aug 20, 2024
7b4c20e
[ADD] usability_webhooks: can choose whether to keep log
Pani-k-folk Jul 23, 2024
d4d129b
[ENH] usability_webhooks: search_data by search_read function
Saran440 Jul 19, 2024
9d0d024
[IMP] usability_wenhooks: filter value 2many in search_data
Saran440 Sep 30, 2024
c81bcb6
[IMP] usability_webhooks: support x2many, many2one to fetch field
Saran440 Sep 30, 2024
6e1defc
[IMP] usability_webhooks: add key for product.template
Pani-k-folk Oct 1, 2024
3fb2aa2
[FIX] usability_webhooks: version
Saran440 Oct 1, 2024
4de7f79
[FIX] usability_webhooks: add call function logs
Saran440 Oct 1, 2024
9d80be3
[FIX] usability_webhooks: readme
Saran440 Oct 1, 2024
f91f1ad
[IMP] usability_webhooks: check_company
Pani-k-folk Oct 1, 2024
2fbd018
[IMP] usability_webhooks: use parameter 'search_key' to search record
Saran440 Oct 3, 2024
6f89192
[FIX] usability_webhooks: multi search_key
Saran440 Oct 4, 2024
e1b994a
[FIX] usability_webhooks: varresult_dict
Saran440 Oct 8, 2024
47272e4
[FIX] usability_webhooks: orm cache
Saran440 Oct 10, 2024
5c04568
[FIX] update copier with ruff format
Nov 14, 2024
8fc8b3a
[IMP] usability_webhooks: update multi record
Nov 14, 2024
25b4481
[FIX] update readme
Nov 14, 2024
8ffad89
[FIX] usability_webhooks: split function for hooks
Saran440 Nov 21, 2024
aa9c06c
[IMP] usability_webhooks: pre-commit auto fixes
Saran440 Mar 10, 2025
6a65b51
[FIX] usability_webhooks: auto delete log with direct query
Saran440 Dec 13, 2024
2a5f8bc
[IMP] usability_webhooks: many2many format
Saran440 Nov 25, 2024
9e354ad
[IMP] usability_webhooks: support reference type
Saran440 Dec 13, 2024
ecc4201
[MIG] usability_webhooks: Migration to 18.0
Saran440 Mar 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 220 additions & 0 deletions usability_webhooks/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
====================
REST API for Webhook
====================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:118b3dcbe0ecd2d2813ecb16117bddb07226db7b09f60de3924b570ea6e2dfc4
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-ecosoft--odoo%2Fecosoft--addons-lightgray.png?logo=github
:target: https://github.com/ecosoft-odoo/ecosoft-addons/tree/18.0/usability_webhooks
:alt: ecosoft-odoo/ecosoft-addons

|badge1| |badge2| |badge3|

This module is base webhooks standard and keep all log that interface

Step to see logs:

1. Go to Settings > Technical > API Configuration > API Logs
2. this table will keep all log that interface '/api/create_data' or '/api/create_update_data'
3. Users can used this table for test API by click 'Update API'

**Table of contents**

.. contents::
:local:

Usage
=====

Before sending a REST API request to Odoo, an initial call to authenticate the API is necessary.
You can achieve this by calling the ``/web/session/authenticate`` route.

The authentication format requires a header with ``Content-type`` set to ``application/json``,
and the body should include:

.. code-block:: python

{
"jsonrpc": "2.0",
"method": "call",
"params": {
"db": "<db_name>",
"login": "<username>",
"password": "<password>"
}
}

Following successful authentication, you can proceed with five API routes:

1. ``/api/create_data``: This route allows the creation of new data only.
The format for creating data should be in the following structure:

.. code-block:: python

{
"params": {
"model": "<model name>",
"vals": {
"payload": {
"field1": "value1",
...
},
"result_field": ["field1", ...] # optional
}
}
}

2. ``/api/create_update_data``: This route facilitates updating data.
If the data does not exist, it will automatically create it.
The format follows that of ``create_data``, but it requires a unique key in the field to update the values.

.. code-block:: python

{
"params": {
"model": "<model name>",
"vals": {
"search_key": {
"<key_field>": "value", # can be ID or name search string
},
"payload": {
"field1": "value1",
...
},
"result_field": ["field1", ...] # optional
}
}
}

3. ``/api/update_data``: This route allows updating existing data,
using a unique key in the field to find the desired data and update values in that recordset.

.. code-block:: python

{
"params": {
"model": "<model name>",
"vals": {
"search_key": {
"<key_field>": "value", # can be ID or name search string
},
"payload": {
"field1": "value1",
...
}
}
}
}

4. ``/api/search_data``: This route allows you to search for the value of a desired field in a model
by using a search domain to find the desired recordset. You can also limit and order the resulting data.

.. code-block:: python

{
"params": {
"model": "<model name>",
"vals": {
"payload": {
"search_field": ["field1", "field2", "field3{subfield1, subfield2}", ...],
"search_domain": "[('field', 'operator', 'value')]",
"limit": 1,
"order": "field1 , field2 desc, ..."
}
}
}
}

5. ``/api/call_function``: This route allows you to call a function on a model object based on the provided input.

**Parameters**:
- **name** (*str*): The name of the model to perform the function on.
- **method** (*str*): The name of the function to call.
- **parameter** (*dict*): A dictionary containing the arguments to pass to the function (if any).

.. code-block:: python

{
"params": {
"model": "<model name>",
"vals": {
"search_key": {
"<key_field>": "value", # can be ID or name search string
},
"payload": {
"method": "<method>",
"parameter": {"<key>": "<value>", ...}
}
}
}
}

**Note**:
If you want to attach a file to a record, you can add the key "attachment_ids" at any level of the payload.

**Example Request with Attachment**:

.. code-block:: python

{
"params": {
"model": "<model name>",
"vals": {
"search_key": {
"<key_field>": "value", # can be ID or name search string
},
"payload": {
"attachment_ids": [
{
"name": "<file_name>",
"datas": "<base64_encoded_data>"
}
],
...
}
}
}
}

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/ecosoft-odoo/ecosoft-addons/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/ecosoft-odoo/ecosoft-addons/issues/new?body=module:%20usability_webhooks%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
~~~~~~~

* Ecosoft

Contributors
~~~~~~~~~~~~

* Kitti Upariphutthiphong <[email protected]>
* Saran Lim. <[email protected]>

Maintainers
~~~~~~~~~~~

This module is part of the `ecosoft-odoo/ecosoft-addons <https://github.com/ecosoft-odoo/ecosoft-addons/tree/18.0/usability_webhooks>`_ project on GitHub.

You are welcome to contribute.
4 changes: 4 additions & 0 deletions usability_webhooks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import controllers
from . import models
18 changes: 18 additions & 0 deletions usability_webhooks/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2022 Ecosoft Co., Ltd. (http://ecosoft.co.th)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "REST API for Webhook",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"category": "Tools",
"author": "Ecosoft, Odoo Community Association (OCA)",
"website": "https://github.com/ecosoft-odoo/ecosoft-addons",
"depends": ["base", "mail"],
"data": [
"security/ir.model.access.csv",
"data/config_parameter.xml",
"data/ir_cron.xml",
"views/api_log.xml",
],
}
4 changes: 4 additions & 0 deletions usability_webhooks/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import main
from . import utils
88 changes: 88 additions & 0 deletions usability_webhooks/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Copyright 2022 Ecosoft Co., Ltd (http://ecosoft.co.th/)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)

import ast
import json
import traceback

from odoo import http
from odoo.http import request


class WebhookController(http.Controller):
def _call_function_api(self, model, vals, function):
"""
This function will call the function from webhook.utils
Can be hook to add something before or after the function
"""
return getattr(request.env["webhook.utils"], function)(model, vals)

def _create_api_logs(self, model, vals, function):
# Add logs
data_dict = {
"data": json.dumps(vals),
"model": model,
"route": f"/api/{function}",
"function_name": function,
}

ICP = request.env["ir.config_parameter"]
rollback_state_failed = ICP.sudo().get_param("webhook.rollback_state_failed")
rollback_except = ICP.sudo().get_param("webhook.rollback_except")
try:
res = self._call_function_api(model, vals, function)
state = "done" if res["is_success"] else "failed"
data_dict.update({"result": res, "state": state})
# Not success, rollback all data (if config in system parameter)
if not res["is_success"] and rollback_state_failed:
request.env.cr.rollback()
except Exception:
res = {
"is_success": False,
"messages": traceback.format_exc(),
}
data_dict.update({"result": res, "state": "failed"})
# Error from odoo exception,
# rollback all data (if config in system parameter)
if rollback_except:
request.env.cr.rollback()
if vals["is_create_log"]:
request.env["api.log"].create(data_dict)
return res

def _set_create_logs(self, param, vals):
ICP = request.env["ir.config_parameter"]
is_create_log = ICP.sudo().get_param(param)
# convert str to bool
is_create_log = ast.literal_eval(is_create_log.capitalize())
vals.update({"is_create_log": is_create_log})

@http.route("/api/create_data", type="json", auth="user")
def create_data(self, model, vals):
self._set_create_logs("webhook.create_data_log", vals)
res = self._create_api_logs(model, vals, "create_data")
return res

@http.route("/api/update_data", type="json", auth="user")
def update_data(self, model, vals):
self._set_create_logs("webhook.update_data_log", vals)
res = self._create_api_logs(model, vals, "update_data")
return res

@http.route("/api/create_update_data", type="json", auth="user")
def create_update_data(self, model, vals):
self._set_create_logs("webhook.create_update_data_log", vals)
res = self._create_api_logs(model, vals, "create_update_data")
return res

@http.route("/api/search_data", type="json", auth="user")
def search_data(self, model, vals):
self._set_create_logs("webhook.search_data_log", vals)
res = self._create_api_logs(model, vals, "search_data")
return res

@http.route("/api/call_function", type="json", auth="user")
def call_function(self, model, vals):
self._set_create_logs("webhook.call_function_log", vals)
res = self._create_api_logs(model, vals, "call_function")
return res
Loading