From 19a17b18bb6232feb9339051703e88387ddd5125 Mon Sep 17 00:00:00 2001 From: mymage Date: Mon, 24 Aug 2026 06:28:56 +0000 Subject: [PATCH 1/5] Translated using Weblate (Italian) Currently translated at 100.0% (110 of 110 strings) Translation: server-env-16.0/server-env-16.0-server_environment Translate-URL: https://translation.odoo-community.org/projects/server-env-16-0/server-env-16-0-server_environment/it/ --- server_environment/i18n/it.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server_environment/i18n/it.po b/server_environment/i18n/it.po index b417622af..f50bd3ee8 100644 --- a/server_environment/i18n/it.po +++ b/server_environment/i18n/it.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: server-tools (9.0)\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-09-10 02:53+0000\n" -"PO-Revision-Date: 2025-05-16 09:20+0000\n" +"PO-Revision-Date: 2026-08-24 08:46+0000\n" "Last-Translator: mymage \n" "Language-Team: Italian (http://www.transifex.com/oca/OCA-server-tools-9-0/" "language/it/)\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.10.4\n" +"X-Generator: Weblate 5.15.2\n" #. module: server_environment #: model:ir.model.fields,field_description:server_environment.field_server_config__config @@ -279,7 +279,7 @@ msgstr "odoo | list_db" #. module: server_environment #: model:ir.model.fields,field_description:server_environment.field_server_config__odoo_I_log_config msgid "odoo | log_config" -msgstr "" +msgstr "odoo | log_config" #. module: server_environment #: model:ir.model.fields,field_description:server_environment.field_server_config__odoo_I_log_db From 4c2a6eeac78f87f843c39e5b0a4388ea1af1c009 Mon Sep 17 00:00:00 2001 From: Alexandre Fayolle Date: Wed, 25 Mar 2026 15:40:12 +0100 Subject: [PATCH 2/5] [IMP] server_environment: module uninstallation Add a helper to manage the restoring of the database columns when a module using `server_environment` is uninstalled or the dependency on `server_environment` is dropped. Document how to use the helper in an uninstall script or in an upgrade script (if a new version of the addon drops the dependency). --- server_environment/README.rst | 155 ++++++++++++++ server_environment/__init__.py | 1 + server_environment/readme/USAGE.rst | 155 ++++++++++++++ .../static/description/index.html | 189 ++++++++++++++++-- .../tests/test_server_environment.py | 13 ++ server_environment/uninstall.py | 96 +++++++++ 6 files changed, 595 insertions(+), 14 deletions(-) create mode 100644 server_environment/uninstall.py diff --git a/server_environment/README.rst b/server_environment/README.rst index 6cbcc3853..ccb7af0ee 100644 --- a/server_environment/README.rst +++ b/server_environment/README.rst @@ -203,6 +203,161 @@ If you want to have a technical name to reference:: [...] +Restoring columns on uninstall +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When ``server.env.mixin`` is bound to an existing model, the ORM drops the +original stored columns for all env-managed fields. If the binding addon is +later uninstalled, those columns must be recreated so the database remains +usable. + +Add an ``uninstall_hook`` to your addon and delegate to +``restore_env_managed_columns``:: + + # your_addon/__init__.py + from .hooks import uninstall_hook + # your_addon/hooks.py + from odoo import SUPERUSER_ID, api + from odoo.addons.server_environment import uninstall + + def uninstall_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + uninstall.restore_env_managed_columns( + env, + "storage.backend", + ["directory_path", "other_field"], + ) + + # your_addon/__manifest__.py + { + ... + "uninstall_hook": "uninstall_hook", + } + +The helper creates any missing columns (idempotent: safe to call multiple +times) and repopulates them with each record's current effective value — +whether that value came from an environment configuration file or from the +stored default field (``x__env_default``). + +The hook must run *before* the ORM extensions are removed, which is guaranteed +by Odoo's uninstall sequence (hooks execute before +``Module.module_uninstall()``). + +Handling required fields +^^^^^^^^^^^^^^^^^^^^^^^^ + +If a restored column is **required** (has a ``NOT NULL`` constraint) but has no +effective value (missing from environment config and no default field set), the +restoration will fail with a ``UserError``. + +**Solution:** pass a ``field_defaults`` dictionary with fallback values:: + + def uninstall_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + restore_env_managed_columns( + env, + "ir.mail_server", + ["smtp_host", "smtp_authentication"], + field_defaults={ + "smtp_authentication": "login", # fallback for required field + }, + ) + +The helper will use the fallback value if provided and the computed field value +is empty. If no fallback is provided but a required field has no value, a +``UserError`` is raised with instructions on how to provide a ``field_defaults`` +parameter. + +Migrating when dropping server_environment dependency +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When refactoring an existing addon that embeds a ``server.env.mixin`` binding, you +may want to extract the binding into a separate *glue* addon and drop the +``server_environment`` dependency from the original. This keeps the base addon +lightweight while preserving server-environment features for those who install +the glue addon. + +**Pattern:** + +- **Original addon (v1)**: depends on ``server_environment`` and binds the mixin + directly in model code. +- **Refactored addon (v2)**: removes ``server_environment`` from dependencies, + removes the mixin binding and the related ORM model inheritance. +- **New glue addon** (optional, same version): depends on both + ``server_environment`` and the original addon v2; re-adds the mixin binding in + a separate module file. + +**Migration checklist:** + +1. In the **original addon's v2** ``__manifest__.py``: + + - Remove ``"server_environment"`` from ``depends``. + - Remove the model file(s) that contained the mixin binding. + - Update ``depends`` to add the new glue addon *if* the base addon still needs + it (otherwise, make the glue addon optional for users who want env-binding). + +2. In the **original addon's v2 model code**: + + - Delete or simplify the model class that inherited from + ``server.env.mixin``. + - If the model was only there for the binding, remove it entirely. + - Restore the original field definitions (not as computed fields). + +3. **Create a migration script** (if needed) to restore columns *during the addon + upgrade*, before the ORM model extensions are unloaded. Use a ``@post_load`` + hook or a dedicated migration script:: + + # migrations/18.0.1.0.0/post-restore-columns.py + def migrate(cr, version): + # Call the restoration logic while the v1 model is still active + env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {}) + # If any field is required and may have no value in the environment, + # provide a fallback via field_defaults + restore_env_managed_columns( + env, + "storage.backend", + ["directory_path", "other_field"], + field_defaults={ + "directory_path": "/tmp", # fallback for required field + }, + ) + +4. **Create the glue addon** with the model re-inheritance:: + + # your_addon_env/__init__.py + from . import models + + # your_addon_env/models/__init__.py + from . import storage_backend + + # your_addon_env/models/storage_backend.py + class StorageBackend(models.Model): + _name = "storage.backend" + _inherit = ["storage.backend", "server.env.mixin"] + + @property + def _server_env_fields(self): + return {"directory_path": {}} + + # your_addon_env/__manifest__.py + { + "name": "Storage Backend – Server Environment", + "version": "18.0.1.0.0", + "depends": ["server_environment", "storage_backend"], + "installable": True, + } + +**Key points:** + +- Column restoration must happen *during the addon upgrade* (step 3), not as an + uninstall hook, because the original model binding is still active. +- The ``restore_env_managed_columns`` helper is idempotent and safe to call even + if columns already exist. +- Users who do not need server environment features simply do *not* install the + glue addon—the base addon continues to work with plain database columns. +- Users who do need server environment can install both the base addon (v2+) and + the glue addon (same version) to get the binding back. + Known issues / Roadmap ====================== diff --git a/server_environment/__init__.py b/server_environment/__init__.py index 52bc6e602..85c79f6fd 100644 --- a/server_environment/__init__.py +++ b/server_environment/__init__.py @@ -1,3 +1,4 @@ from . import models from . import server_env from .server_env import serv_config, setboolean +from . import uninstall diff --git a/server_environment/readme/USAGE.rst b/server_environment/readme/USAGE.rst index deeea866a..47736e0a6 100644 --- a/server_environment/readme/USAGE.rst +++ b/server_environment/readme/USAGE.rst @@ -22,3 +22,158 @@ If you want to have a technical name to reference:: _inherit = ["storage.backend", "server.env.techname.mixin"] [...] + +Restoring columns on uninstall +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When ``server.env.mixin`` is bound to an existing model, the ORM drops the +original stored columns for all env-managed fields. If the binding addon is +later uninstalled, those columns must be recreated so the database remains +usable. + +Add an ``uninstall_hook`` to your addon and delegate to +``restore_env_managed_columns``:: + + # your_addon/__init__.py + from .hooks import uninstall_hook + # your_addon/hooks.py + from odoo import SUPERUSER_ID, api + from odoo.addons.server_environment import uninstall + + def uninstall_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + uninstall.restore_env_managed_columns( + env, + "storage.backend", + ["directory_path", "other_field"], + ) + + # your_addon/__manifest__.py + { + ... + "uninstall_hook": "uninstall_hook", + } + +The helper creates any missing columns (idempotent: safe to call multiple +times) and repopulates them with each record's current effective value — +whether that value came from an environment configuration file or from the +stored default field (``x__env_default``). + +The hook must run *before* the ORM extensions are removed, which is guaranteed +by Odoo's uninstall sequence (hooks execute before +``Module.module_uninstall()``). + +Handling required fields +^^^^^^^^^^^^^^^^^^^^^^^^ + +If a restored column is **required** (has a ``NOT NULL`` constraint) but has no +effective value (missing from environment config and no default field set), the +restoration will fail with a ``UserError``. + +**Solution:** pass a ``field_defaults`` dictionary with fallback values:: + + def uninstall_hook(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + restore_env_managed_columns( + env, + "ir.mail_server", + ["smtp_host", "smtp_authentication"], + field_defaults={ + "smtp_authentication": "login", # fallback for required field + }, + ) + +The helper will use the fallback value if provided and the computed field value +is empty. If no fallback is provided but a required field has no value, a +``UserError`` is raised with instructions on how to provide a ``field_defaults`` +parameter. + +Migrating when dropping server_environment dependency +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When refactoring an existing addon that embeds a ``server.env.mixin`` binding, you +may want to extract the binding into a separate *glue* addon and drop the +``server_environment`` dependency from the original. This keeps the base addon +lightweight while preserving server-environment features for those who install +the glue addon. + +**Pattern:** + +- **Original addon (v1)**: depends on ``server_environment`` and binds the mixin + directly in model code. +- **Refactored addon (v2)**: removes ``server_environment`` from dependencies, + removes the mixin binding and the related ORM model inheritance. +- **New glue addon** (optional, same version): depends on both + ``server_environment`` and the original addon v2; re-adds the mixin binding in + a separate module file. + +**Migration checklist:** + +1. In the **original addon's v2** ``__manifest__.py``: + + - Remove ``"server_environment"`` from ``depends``. + - Remove the model file(s) that contained the mixin binding. + - Update ``depends`` to add the new glue addon *if* the base addon still needs + it (otherwise, make the glue addon optional for users who want env-binding). + +2. In the **original addon's v2 model code**: + + - Delete or simplify the model class that inherited from + ``server.env.mixin``. + - If the model was only there for the binding, remove it entirely. + - Restore the original field definitions (not as computed fields). + +3. **Create a migration script** (if needed) to restore columns *during the addon + upgrade*, before the ORM model extensions are unloaded. Use a ``@post_load`` + hook or a dedicated migration script:: + + # migrations/18.0.1.0.0/post-restore-columns.py + def migrate(cr, version): + # Call the restoration logic while the v1 model is still active + env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {}) + # If any field is required and may have no value in the environment, + # provide a fallback via field_defaults + restore_env_managed_columns( + env, + "storage.backend", + ["directory_path", "other_field"], + field_defaults={ + "directory_path": "/tmp", # fallback for required field + }, + ) + +4. **Create the glue addon** with the model re-inheritance:: + + # your_addon_env/__init__.py + from . import models + + # your_addon_env/models/__init__.py + from . import storage_backend + + # your_addon_env/models/storage_backend.py + class StorageBackend(models.Model): + _name = "storage.backend" + _inherit = ["storage.backend", "server.env.mixin"] + + @property + def _server_env_fields(self): + return {"directory_path": {}} + + # your_addon_env/__manifest__.py + { + "name": "Storage Backend – Server Environment", + "version": "18.0.1.0.0", + "depends": ["server_environment", "storage_backend"], + "installable": True, + } + +**Key points:** + +- Column restoration must happen *during the addon upgrade* (step 3), not as an + uninstall hook, because the original model binding is still active. +- The ``restore_env_managed_columns`` helper is idempotent and safe to call even + if columns already exist. +- Users who do not need server environment features simply do *not* install the + glue addon—the base addon continues to work with plain database columns. +- Users who do need server environment can install both the base addon (v2+) and + the glue addon (same version) to get the binding back. diff --git a/server_environment/static/description/index.html b/server_environment/static/description/index.html index 4c7df4d67..0f6c2271c 100644 --- a/server_environment/static/description/index.html +++ b/server_environment/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +server configuration environment files