From df80e08ecfa0b5a8c3a2af3c41176343a7cc7294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Sun, 15 Oct 2023 10:14:26 +0200 Subject: [PATCH 1/2] fastapi: add base service for exposing search/get --- fastapi/__init__.py | 1 + fastapi/services/__init__.py | 1 + fastapi/services/fastapi_service_base.py | 51 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 fastapi/services/__init__.py create mode 100644 fastapi/services/fastapi_service_base.py diff --git a/fastapi/__init__.py b/fastapi/__init__.py index d5429650..7afbddc9 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,2 +1,3 @@ from . import models from . import fastapi_dispatcher +from . import services diff --git a/fastapi/services/__init__.py b/fastapi/services/__init__.py new file mode 100644 index 00000000..5228898e --- /dev/null +++ b/fastapi/services/__init__.py @@ -0,0 +1 @@ +from . import fastapi_service_base diff --git a/fastapi/services/fastapi_service_base.py b/fastapi/services/fastapi_service_base.py new file mode 100644 index 00000000..d85a06f7 --- /dev/null +++ b/fastapi/services/fastapi_service_base.py @@ -0,0 +1,51 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Sébastien BEAU +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +from odoo import _, models +from odoo.exceptions import MissingError +from odoo.osv import expression + + +class FastapiServiceBase(models.AbstractModel): + _name = "fastapi.service.base" + _description = "Fastpi Service Base can help you to expose odoo model" + _odoo_model = None + + @property + def _odoo_model_domain_restrict(self): + """Restrict domain should be only used to apply some restriction + on the record to expose. + For example, if you do a service that expose "delivery address" + you can return [("type", "=", "delivery")] + The purpose of the restrict domain is not restrict the information + dependending on the authenticated partner. + For security restriction, use security rule. + """ + return [] + + def _convert_search_params_to_domain(self, params): + return [] + + def _search(self, paging, params=None): + domain = expression.AND( + [ + self._odoo_model_domain_restrict, + self._convert_search_params_to_domain(params) if params else [], + ] + ) + count = self.env[self._odoo_model].search_count(domain) + return count, self.env[self._odoo_model].search( + domain, limit=paging.limit, offset=paging.offset + ) + + def _get(self, record_id): + record = ( + self.env[self._odoo_model] + .browse(record_id) + .filtered_domain(self._odoo_model_domain_restrict) + ) + if not record: + raise MissingError(_("The record do not exist")) + return record From 3c96e2307c530fa08d3e20187ae71d3987317f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Mon, 16 Oct 2023 15:17:20 +0200 Subject: [PATCH 2/2] fixup! fastapi: add base service for exposing search/get --- fastapi/__init__.py | 2 +- fastapi/services/__init__.py | 1 - fastapi/services/fastapi_service_base.py | 51 ------------------------ fastapi/utils.py | 27 +++++++++++++ 4 files changed, 28 insertions(+), 53 deletions(-) delete mode 100644 fastapi/services/__init__.py delete mode 100644 fastapi/services/fastapi_service_base.py create mode 100644 fastapi/utils.py diff --git a/fastapi/__init__.py b/fastapi/__init__.py index 7afbddc9..ebee13b5 100644 --- a/fastapi/__init__.py +++ b/fastapi/__init__.py @@ -1,3 +1,3 @@ from . import models from . import fastapi_dispatcher -from . import services +from . import utils diff --git a/fastapi/services/__init__.py b/fastapi/services/__init__.py deleted file mode 100644 index 5228898e..00000000 --- a/fastapi/services/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import fastapi_service_base diff --git a/fastapi/services/fastapi_service_base.py b/fastapi/services/fastapi_service_base.py deleted file mode 100644 index d85a06f7..00000000 --- a/fastapi/services/fastapi_service_base.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright 2023 Akretion (https://www.akretion.com). -# @author Sébastien BEAU -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). - - -from odoo import _, models -from odoo.exceptions import MissingError -from odoo.osv import expression - - -class FastapiServiceBase(models.AbstractModel): - _name = "fastapi.service.base" - _description = "Fastpi Service Base can help you to expose odoo model" - _odoo_model = None - - @property - def _odoo_model_domain_restrict(self): - """Restrict domain should be only used to apply some restriction - on the record to expose. - For example, if you do a service that expose "delivery address" - you can return [("type", "=", "delivery")] - The purpose of the restrict domain is not restrict the information - dependending on the authenticated partner. - For security restriction, use security rule. - """ - return [] - - def _convert_search_params_to_domain(self, params): - return [] - - def _search(self, paging, params=None): - domain = expression.AND( - [ - self._odoo_model_domain_restrict, - self._convert_search_params_to_domain(params) if params else [], - ] - ) - count = self.env[self._odoo_model].search_count(domain) - return count, self.env[self._odoo_model].search( - domain, limit=paging.limit, offset=paging.offset - ) - - def _get(self, record_id): - record = ( - self.env[self._odoo_model] - .browse(record_id) - .filtered_domain(self._odoo_model_domain_restrict) - ) - if not record: - raise MissingError(_("The record do not exist")) - return record diff --git a/fastapi/utils.py b/fastapi/utils.py new file mode 100644 index 00000000..874c07d8 --- /dev/null +++ b/fastapi/utils.py @@ -0,0 +1,27 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Sébastien BEAU +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +from odoo import _, models +from odoo.exceptions import MissingError +from odoo.osv import expression + + +class FilteredDomainAdapter: + def __init__(self, model: models.BaseModel, base_domain: list): + self._model = model + self._base_domain = base_domain + + def get(self, record_id: int) -> models.BaseModel: + record = self._model.browse(record_id).filtered_domain(self._base_domain) + if record: + return record + else: + raise MissingError(_("The record do not exist")) + + def search_with_count(self, domain: list, limit, offset): + domain = expression.AND([self._base_domain, domain]) + + count = self._model.search_count(domain) + return count, self._model.search(domain, limit=limit, offset=offset)