Includes: - Odoo 19 framework (odoo/) - 27 custom EnCoach addons (new_project/custom_addons/) - encoach_core, encoach_api, encoach_lms_api, encoach_adaptive_api - encoach_exam, encoach_taxonomy, encoach_adaptive, encoach_assignment - encoach_ai, encoach_ai_grading, encoach_ai_generation, encoach_ai_media - encoach_courseware, encoach_communication, encoach_subscription - encoach_notification, encoach_approval, encoach_branding - encoach_classroom, encoach_registration, encoach_stats - encoach_faq, encoach_ticket, encoach_training, encoach_resources - encoach_adaptive_ai, encoach_sis - 21 OpenEduCat Enterprise modules (new_project/enterprise-19/) - 14 OpenEduCat Community modules (new_project/openeducat_erp-19.0/) - Configuration: odoo.conf, requirements.txt, scripts - 200+ REST API endpoints with JWT authentication - SRS and test documentation Made-with: Cursor
91 lines
2.6 KiB
Python
91 lines
2.6 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import inspect
|
|
import logging
|
|
from collections.abc import Mapping, Sequence
|
|
from typing import Any
|
|
|
|
from werkzeug.exceptions import (
|
|
NotFound,
|
|
UnprocessableEntity,
|
|
)
|
|
|
|
from odoo import http
|
|
from odoo.http import request
|
|
from odoo.models import BaseModel
|
|
from odoo.service.model import get_public_method
|
|
from odoo.tools import frozendict
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class WebJson2Controller(http.Controller):
|
|
def _web_json_2_rpc_readonly(self, rule, args):
|
|
try:
|
|
model_name = args['__model__']
|
|
method_name = args['__method__']
|
|
Model = request.registry[model_name]
|
|
except KeyError:
|
|
# no need of a read/write cursor to send a 404 http error
|
|
return True
|
|
for cls in Model.mro():
|
|
method = getattr(cls, method_name, None)
|
|
if method is not None and hasattr(method, '_readonly'):
|
|
return method._readonly
|
|
return False
|
|
|
|
# Take over /json/<path:subpath>
|
|
@http.route(
|
|
['/json/2', '/json/2/<path:subpath>'],
|
|
auth='public',
|
|
type='json2',
|
|
readonly=True,
|
|
methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
|
|
)
|
|
def web_json_2_404(self, subpath=None):
|
|
e = "Did you mean POST /json/2/<model>/<method>?"
|
|
raise request.not_found(e)
|
|
|
|
@http.route(
|
|
'/json/2/<__model__>/<__method__>',
|
|
methods=['POST'],
|
|
auth='bearer',
|
|
type='json2',
|
|
readonly=_web_json_2_rpc_readonly,
|
|
save_session=False,
|
|
)
|
|
def web_json_2_rpc(
|
|
self,
|
|
__model__: str,
|
|
__method__: str,
|
|
ids: Sequence[int] = (),
|
|
context: Mapping[str, Any] = frozendict(),
|
|
**kwargs,
|
|
):
|
|
try:
|
|
Model = request.env[__model__].with_context(context)
|
|
except KeyError as exc:
|
|
e = f"the model {__model__!r} does not exist"
|
|
raise NotFound(e) from exc
|
|
|
|
try:
|
|
func = get_public_method(Model, __method__)
|
|
except AttributeError as exc:
|
|
raise NotFound(exc.args[0]) from exc
|
|
if hasattr(func, '_api_model') and ids:
|
|
e = f"cannot call {__model__}.{__method__} with ids"
|
|
raise UnprocessableEntity(e)
|
|
|
|
records = Model.browse(ids)
|
|
signature = inspect.signature(func)
|
|
try:
|
|
signature.bind(records, **kwargs)
|
|
except TypeError as exc:
|
|
raise UnprocessableEntity(exc.args[0])
|
|
|
|
result = func(records, **kwargs)
|
|
if isinstance(result, BaseModel):
|
|
result = result.ids
|
|
|
|
return result
|