# HG changeset patch # User Vincent Hatakeyama <vincent.hatakeyama@xcg-consulting.fr> # Date 1740052304 -3600 # Thu Feb 20 12:51:44 2025 +0100 # Branch 18.0 # Node ID 0de61891edacf2629b4aca660ae72d020f8edcf9 # Parent e87d2e751c850954a2125261af05822ff430d90c Add JsonLD_ID converter diff --git a/NEWS.rst b/NEWS.rst --- a/NEWS.rst +++ b/NEWS.rst @@ -1,6 +1,11 @@ Changelog ========= +18.0.4.1.0 +---------- + +Add JsonLD_ID converter. + 18.0.4.0.0 ---------- diff --git a/__init__.py b/__init__.py --- a/__init__.py +++ b/__init__.py @@ -52,4 +52,4 @@ NotInitialized, Validator, ) -from .xref import Xref +from .xref import Xref, JsonLD_ID diff --git a/__manifest__.py b/__manifest__.py --- a/__manifest__.py +++ b/__manifest__.py @@ -21,7 +21,7 @@ "name": "Converter", "license": "AGPL-3", "summary": "Convert odoo records to/from plain data structures.", - "version": "18.0.4.0.0", + "version": "18.0.4.1.0", "category": "Hidden", "author": "XCG Consulting", "website": "https://orbeet.io/", diff --git a/xref.py b/xref.py --- a/xref.py +++ b/xref.py @@ -1,7 +1,7 @@ ############################################################################## # # Converter Odoo module -# Copyright © 2020 XCG Consulting <https://xcg-consulting.fr> +# Copyright © 2020, 2025 XCG Consulting <https://xcg-consulting.fr> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -17,14 +17,24 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################## - +import logging +import os from typing import Any -from odoo import api, models # type: ignore[import-untyped] +from odoo import _, api, models # type: ignore[import-untyped] -from .base import Context, NewinstanceType, PostHookConverter +from .base import ( + Context, + ContextBuilder, + Converter, + NewinstanceType, + PostHookConverter, + build_context, +) from .models.ir_model_data import _XREF_IMD_MODULE +_logger = logging.getLogger(__name__) + # TODO dans quel cas ça ne pourrait pas être un instance getter??? class Xref(PostHookConverter): @@ -65,3 +75,92 @@ @property def is_instance_getter(self) -> bool: return self._is_instance_getter + + +class JsonLD_ID(Xref): + """This converter represents a JsonLD ID , an url made of + a base part defined as ir.config_parameter, an optional breadcrumb + and a unique id part using the standard xmlid. + """ + + def __init__( + self, + breadcrumb: str | Converter, + module: str | None = _XREF_IMD_MODULE, + is_instance_getter: bool = True, + unique_id_field: str | None = None, + context: ContextBuilder | None = None, + has_base_url: bool = True, + ): + """ + :param breadcrumb: Part of the url describing the entity, + must match the syntax expected by os.path, ie absolute path + begins with a slash. With absolute path the base part is + ignored. Can also be a converter, if so, the result of the + combined converters must be a string. + """ + super().__init__( + module=module, + is_instance_getter=is_instance_getter, + ) + self.converter: Converter | None = None + self._breadcrumb = breadcrumb if isinstance(breadcrumb, str) else None + if isinstance(breadcrumb, Converter): + self.converter = breadcrumb + self._unique_id_field = unique_id_field + self._context = context + self._has_base_url = has_base_url + + def odoo_to_message(self, instance: models.BaseModel, ctx: Context = None) -> Any: + if not instance: + return "" + + ctx = build_context(instance, ctx, self._context) + if self._unique_id_field is not None: + name = getattr(instance, self._unique_id_field) + else: + _module, name = instance.env["ir.model.data"].object_to_module_and_name( + instance, self._module + ) + + jsonld_id_base_url = ( + instance.env["ir.config_parameter"] + .sudo() + .get_param("sync.jsonld_id_base_url") + ) + if self._has_base_url and not jsonld_id_base_url: + _logger.error( + _("Missing config parameter: 'sync.jsonld_id_base_url' is not defined") + ) + return "" + + if self.converter is not None: + self._breadcrumb = self.converter.odoo_to_message(instance, ctx) + + xref = os.path.join( + jsonld_id_base_url if self._has_base_url else "", + self._breadcrumb if self._breadcrumb is not None else "", + name, + ) + instance.env["ir.model.data"].set_xmlid( + instance, xref, module=self._module, only_when_missing=True + ) + + # In case of jsonld_id, replace the xref generated by + # `object_to_module_and_name` with jsonld format. + if self._has_base_url: + # Need sudo as typical user does not have the rights on ir.model.data + imd = ( + instance.env["ir.model.data"] + .sudo() + .search( + [ + ("module", "=", self._module), + ("model", "=", instance._name), + ("res_id", "=", instance.id), + ] + ) + ) + imd.write({"name": xref}) + + return xref