Skip to content

Commit

Permalink
Merge PR #700 into 14.0
Browse files Browse the repository at this point in the history
Signed-off-by simahawk
  • Loading branch information
OCA-git-bot committed Aug 16, 2023
2 parents 4a45e54 + c0e06b7 commit 9fea4aa
Show file tree
Hide file tree
Showing 17 changed files with 202 additions and 2 deletions.
11 changes: 11 additions & 0 deletions shopfloor_base/models/shopfloor_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# @author Simone Orsi <[email protected]>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).

import logging

from odoo import api, fields, models, tools
from odoo.tools import DotDict

Expand All @@ -10,6 +12,8 @@

from ..utils import APP_VERSION, RUNNING_ENV

_logger = logging.getLogger(__file__)


class ShopfloorApp(models.Model):
"""Backend for a Shopfloor app."""
Expand Down Expand Up @@ -281,6 +285,13 @@ def _is_component_registry_ready(self):
return comp_registry and comp_registry.ready

def _get_services(self):
forced_services = self.env.context.get("sf_service_components")
if forced_services:
_logger.debug(
"_get_services forced services: %s",
", ".join([x._usage for x in forced_services]),
)
return forced_services
if not self._is_component_registry_ready():
# No service is available before the registry has been loaded.
# This is a very special case, when the odoo registry is being
Expand Down
70 changes: 70 additions & 0 deletions shopfloor_base/utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
# Copyright 2021 Camptocamp SA (http://www.camptocamp.com)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
# @author Simone Orsi <[email protected]>
import logging
import os
from functools import wraps

from odoo.modules.module import load_information_from_description_file
from odoo.tools.config import config as odoo_config

from odoo.addons.base_rest.controllers.main import _PseudoCollection
from odoo.addons.component.core import WorkContext, _component_databases

_logger = logging.getLogger(__name__)


def ensure_model(model_name):
"""Decorator to ensure data method is called w/ the right recordset."""
Expand Down Expand Up @@ -65,3 +71,67 @@ def _get_running_env():


RUNNING_ENV = _get_running_env()


def register_new_services(env, *component_classes, apps=None):
"""Enforce registration of new services straight from their classes.
At some stage (eg: a post install hook) the component registry
might not be fully loaded and the components might be not fully "ready".
For this reason, not all the inherited properties
are granted to be available (eg: _collection)
and they won't be available for `components_registry.lookup` call.
This is why, to ensure that the new services endpoints
are registered in any case we prepare their classes "manually" here
and pass them over to sf.app._get_services.
In this way, if their endpoint_route rows are not there
they will be generated on the fly,
Please, note that this func is very low level
and must be used only in particular situations (such as install hooks).
"""
if odoo_config["test_enable"]:
# When installing modules for tests, there's nothing to do.
# Moreover, it can lead to weird service behavior
# because the classes will be decorated
# but when they are not fully ready.
return
components = load_components_without_registry(env, *component_classes)
if not components:
return
apps = apps or env["shopfloor.app"].search([])
apps.with_context(sf_service_components=components)._register_controllers()


def load_components_without_registry(env, *component_classes):
"""Prepare components' instances w/o real registry lookup."""
collection = _PseudoCollection("shopfloor.app", env)
rest_service = env["rest.service.registration"]
if not _component_databases.get(env.cr.dbname):
# no registry ready yet (eg: install via cmd line, tests, etc)
_logger.info("component registry not ready yet")
return []
work = WorkContext(model_name=rest_service._name, collection=collection)
return [comp(work) for comp in component_classes]


def purge_endpoints(env, service_usage, endpoint=None):
"""Remove stale services' endpoints routes.
When scenario are removed (eg: module uninstalled)
their routes must be cleaned up.
You can use this function to easily clean them for all apps.
Motivation: registered routes for a given app are taken
from the endpoint_route table via `route_group`.
As the table is populated dynamically with registered components
when a component is removed there's no direct update to the table.
Hence, is the responsibility of the dev to take care of the cleanup.
"""
apps = env["shopfloor.app"].search([])
for app in apps:
route = app.api_url_for_service(service_usage, endpoint=endpoint)
route = route + ("/" if not endpoint else "")
env.cr.execute("DELETE FROM endpoint_route WHERE route like %s", (f"{route}%",))
1 change: 1 addition & 0 deletions shopfloor_delivery_shipment/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from . import actions
from . import models
from . import services
from .hooks import post_init_hook, uninstall_hook
2 changes: 2 additions & 0 deletions shopfloor_delivery_shipment/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@
],
"data": ["data/shopfloor_scenario_data.xml", "views/shopfloor_menu.xml"],
"demo": ["demo/shopfloor_profile_demo.xml", "demo/shopfloor_menu_demo.xml"],
"post_init_hook": "post_init_hook",
"uninstall_hook": "uninstall_hook",
}
24 changes: 24 additions & 0 deletions shopfloor_delivery_shipment/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

import logging

from odoo import SUPERUSER_ID, api

from odoo.addons.shopfloor_base.utils import purge_endpoints, register_new_services

from .services.delivery_shipment import DeliveryShipment as Service

_logger = logging.getLogger(__file__)


def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Register routes for %s", Service._usage)
register_new_services(env, Service)


def uninstall_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Refreshing routes for existing apps")
purge_endpoints(env, Service._usage)
1 change: 1 addition & 0 deletions shopfloor_manual_product_transfer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import actions
from . import services
from .hooks import post_init_hook, uninstall_hook
2 changes: 2 additions & 0 deletions shopfloor_manual_product_transfer/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@
],
"demo": ["demo/stock_picking_type.xml", "demo/shopfloor_menu.xml"],
"installable": True,
"post_init_hook": "post_init_hook",
"uninstall_hook": "uninstall_hook",
}
24 changes: 24 additions & 0 deletions shopfloor_manual_product_transfer/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

import logging

from odoo import SUPERUSER_ID, api

from odoo.addons.shopfloor_base.utils import purge_endpoints, register_new_services

from .services.manual_product_transfer import ManualProductTransfer as Service

_logger = logging.getLogger(__file__)


def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Register routes for %s", Service._usage)
register_new_services(env, Service)


def uninstall_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Refreshing routes for existing apps")
purge_endpoints(env, Service._usage)
1 change: 1 addition & 0 deletions shopfloor_reception/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import services
from . import models
from .hooks import post_init_hook, uninstall_hook
2 changes: 2 additions & 0 deletions shopfloor_reception/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@
"demo/stock_picking_type_demo.xml",
"demo/shopfloor_menu_demo.xml",
],
"post_init_hook": "post_init_hook",
"uninstall_hook": "uninstall_hook",
}
24 changes: 24 additions & 0 deletions shopfloor_reception/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

import logging

from odoo import SUPERUSER_ID, api

from odoo.addons.shopfloor_base.utils import purge_endpoints, register_new_services

from .services.reception import Reception as Service

_logger = logging.getLogger(__file__)


def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Register routes for %s", Service._usage)
register_new_services(env, Service)


def uninstall_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Refreshing routes for existing apps")
purge_endpoints(env, Service._usage)
2 changes: 1 addition & 1 deletion shopfloor_single_product_transfer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from . import services
from .hooks import post_init_hook
from .hooks import post_init_hook, uninstall_hook
1 change: 1 addition & 0 deletions shopfloor_single_product_transfer/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@
"demo/shopfloor_menu_demo.xml",
],
"post_init_hook": "post_init_hook",
"uninstall_hook": "uninstall_hook",
}
12 changes: 11 additions & 1 deletion shopfloor_single_product_transfer/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@

from odoo import SUPERUSER_ID, api

from odoo.addons.shopfloor_base.utils import purge_endpoints, register_new_services

from .services.single_product_transfer import ShopfloorSingleProductTransfer as Service

_logger = logging.getLogger(__file__)


def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
env["shopfloor.app"].search([])._handle_registry_sync()
_logger.info("Register routes for %s", Service._usage)
register_new_services(env, Service)


def uninstall_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Refreshing routes for existing apps")
purge_endpoints(env, Service._usage)
1 change: 1 addition & 0 deletions shopfloor_workstation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import models
from . import services
from .hooks import post_init_hook, uninstall_hook
2 changes: 2 additions & 0 deletions shopfloor_workstation/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@
"depends": ["shopfloor", "base_report_to_printer"],
"demo": ["demo/shopfloor_workstation_demo.xml"],
"data": ["security/ir.model.access.csv", "views/shopfloor_workstation.xml"],
"post_init_hook": "post_init_hook",
"uninstall_hook": "uninstall_hook",
}
24 changes: 24 additions & 0 deletions shopfloor_workstation/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

import logging

from odoo import SUPERUSER_ID, api

from odoo.addons.shopfloor_base.utils import purge_endpoints, register_new_services

from .services.workstation import ShopfloorWorkstation as Service

_logger = logging.getLogger(__file__)


def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Register routes for %s", Service._usage)
register_new_services(env, Service)


def uninstall_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
_logger.info("Refreshing routes for existing apps")
purge_endpoints(env, Service._usage)

0 comments on commit 9fea4aa

Please sign in to comment.