Files
Yamen Ahmad 3e83d8d7d5 feat: add complete EnCoach backend — Odoo 19 + all addons
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
2026-04-01 17:10:04 +04:00

175 lines
5.7 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from pytz import timezone, utc
from odoo import fields
from odoo.tests.common import TransactionCase
class TestResourceCommon(TransactionCase):
@classmethod
def datetime_tz(cls, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
""" Return a `datetime` object with a given timezone (if given). """
dt = datetime(year, month, day, hour, minute, second, microsecond)
return timezone(tzinfo).localize(dt) if tzinfo else dt
@classmethod
def datetime_str(cls, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
""" Return a fields.Datetime value with the given timezone. """
dt = datetime(year, month, day, hour, minute, second, microsecond)
if tzinfo:
dt = timezone(tzinfo).localize(dt).astimezone(utc)
return fields.Datetime.to_string(dt)
@classmethod
def _define_calendar(cls, name, attendances, tz):
return cls.env["resource.calendar"].create(
{
"name": name,
"tz": tz,
"attendance_ids": [
(
0,
0,
{
"name": "%s_%d" % (name, index),
"hour_from": att[0],
"hour_to": att[1],
"dayofweek": str(att[2]),
"duration_days": att[3],
},
)
for index, att in enumerate(attendances)
],
},
)
@classmethod
def _define_calendar_2_weeks(cls, name, attendances, tz):
return cls.env["resource.calendar"].create(
{
"name": name,
"tz": tz,
"two_weeks_calendar": True,
"attendance_ids": [
(
0,
0,
{
"name": "%s_%d" % (name, index),
"hour_from": att[0],
"hour_to": att[1],
"dayofweek": str(att[2]),
"week_type": att[3],
},
)
for index, att in enumerate(attendances)
],
},
)
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env.company.resource_calendar_id.tz = "Europe/Brussels"
# UTC+1 winter, UTC+2 summer
cls.calendar_jean = cls._define_calendar(
"40 Hours", [(8, 16, i, 1) for i in range(5)], "Europe/Brussels",
)
# UTC+6
cls.calendar_patel = cls._define_calendar(
"38 Hours",
sum((((9, 12, i, 3 / 7), (13, 17, i, 4 / 7)) for i in range(5)), ()),
"Etc/GMT-6",
)
# UTC-8 winter, UTC-7 summer
cls.calendar_john = cls._define_calendar(
"8+12 Hours",
[(8, 16, 1, 1), (8, 13, 4, 5 / 12), (16, 23, 4, 7 / 12)],
"America/Los_Angeles",
)
# UTC+1 winter, UTC+2 summer
cls.calendar_jules = cls._define_calendar_2_weeks(
"Week 1: 30 Hours - Week 2: 16 Hours",
[
(8, 16, 0, "0"),
(9, 17, 1, "0"),
(8, 16, 0, "1"),
(7, 15, 2, "1"),
(8, 16, 3, "1"),
(10, 16, 4, "1"),
],
"Europe/Brussels",
)
cls.calendar_paul = cls._define_calendar(
"Morning and evening shifts",
sum((((2, 7, i, 0.5), (10, 16, i, 0.5)) for i in range(5)), ()),
"America/Noronha",
)
cls.calendar_bob = cls._define_calendar(
"Calendar with adjacent attendances",
sum((((8, 12, i, 0.5), (12, 16, i, 0.5)) for i in range(5)), ()),
"Europe/Brussels",
)
# Employee is linked to a resource.resource via resource.mixin
cls.jean = cls.env["resource.test"].create(
{
"name": "Jean",
"resource_calendar_id": cls.calendar_jean.id,
},
)
cls.patel = cls.env["resource.test"].create(
{
"name": "Patel",
"resource_calendar_id": cls.calendar_patel.id,
},
)
cls.john = cls.env["resource.test"].create(
{
"name": "John",
"resource_calendar_id": cls.calendar_john.id,
},
)
cls.jules = cls.env["resource.test"].create(
{
"name": "Jules",
"resource_calendar_id": cls.calendar_jules.id,
},
)
cls.paul = cls.env["resource.test"].create(
{
"name": "Paul",
"resource_calendar_id": cls.calendar_paul.id,
},
)
cls.bob = cls.env["resource.test"].create(
{
"name": "Bob",
"resource_calendar_id": cls.calendar_bob.id,
},
)
cls.two_weeks_resource = cls._define_calendar_2_weeks(
"Two weeks resource",
[
(8, 16, 0, "0"),
(8, 16, 1, "0"),
(8, 16, 2, "0"),
(8, 16, 3, "0"),
(8, 16, 4, "0"),
(8, 16, 0, "1"),
(8, 16, 1, "1"),
(8, 16, 2, "1"),
(8, 16, 3, "1"),
(8, 16, 4, "1"),
],
"Europe/Brussels",
)