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
54 lines
2.4 KiB
Python
54 lines
2.4 KiB
Python
from odoo.fields import Domain
|
|
|
|
# Default hour per day value. The one should
|
|
# only be used when the one from the calendar
|
|
# is not available.
|
|
HOURS_PER_DAY = 8
|
|
|
|
|
|
def filter_domain_leaf(domain, field_check, field_name_mapping=None):
|
|
"""
|
|
filter_domain_lead only keep the leaves of a domain that verify a given check. Logical operators that involves
|
|
a leaf that is undetermined (because it does not pass the check) are ignored.
|
|
|
|
each operator is a logic gate:
|
|
- '&' and '|' take two entries and can be ignored if one of them (or the two of them) is undetermined
|
|
-'!' takes one entry and can be ignored if this entry is undetermined
|
|
|
|
params:
|
|
- domain: the domain that needs to be filtered
|
|
- field_check: the function that the field name used in the leaf needs to verify to keep the leaf
|
|
- field_name_mapping: dictionary of the form {'field_name': 'new_field_name', ...}. Occurences of 'field_name'
|
|
in the first element of domain leaves will be replaced by 'new_field_name'. This is usefull when adapting a
|
|
domain from one model to another when some field names do not match the names of the corresponding fields in
|
|
the new model.
|
|
returns: The filtered version of the domain
|
|
"""
|
|
field_name_mapping = field_name_mapping or {}
|
|
|
|
def adapt_condition(condition, ignored):
|
|
field_name = condition.field_expr
|
|
if not field_check(field_name):
|
|
return ignored
|
|
field_name = field_name_mapping.get(field_name)
|
|
if field_name is None:
|
|
return condition
|
|
return Domain(field_name, condition.operator, condition.value)
|
|
|
|
def adapt_domain(domain: Domain, ignored) -> Domain:
|
|
if hasattr(domain, 'OPERATOR'):
|
|
if domain.OPERATOR in ('&', '|'):
|
|
domain = domain.apply(adapt_domain(d, domain.ZERO) for d in domain.children)
|
|
elif domain.OPERATOR == '!':
|
|
domain = ~adapt_domain(~domain, ~ignored)
|
|
else:
|
|
assert False, "domain.OPERATOR = {domain.OPEATOR!r} unhandled"
|
|
else:
|
|
domain = domain.map_conditions(lambda condition: adapt_condition(condition, ignored))
|
|
return ignored if domain.is_true() or domain.is_false() else domain
|
|
|
|
domain = Domain(domain)
|
|
if domain.is_false():
|
|
return domain
|
|
return adapt_domain(domain, ignored=Domain.TRUE)
|