feat: initial backend codebase — EnCoach v3

Complete Odoo 19 backend with 25 custom addons:
- encoach_core: user/entity/role management
- encoach_api: REST API + JWT auth
- encoach_ai: OpenAI integration, AI settings, generation
- encoach_ai_course: AI-powered English & IELTS course generation
- encoach_exam_template/session: exam creation, structures, sessions
- encoach_scoring: AI auto-grading + manual approval
- encoach_vector: pgvector RAG integration
- encoach_adaptive: adaptive learning engine
- encoach_placement: placement testing
- encoach_taxonomy/resources: content taxonomy & resource management
- Plus 14 more modules for courses, branding, portal, etc.

Includes docs: user guide, generation report, developer workflow.

Made-with: Cursor
This commit is contained in:
Yamen Ahmad
2026-04-11 15:44:20 +04:00
commit 982d4bca30
371 changed files with 35211 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_adaptive_event_form" model="ir.ui.view">
<field name="name">encoach.adaptive.event.form</field>
<field name="model">encoach.adaptive.event</field>
<field name="arch" type="xml">
<form string="Adaptive Event">
<sheet>
<group>
<group>
<field name="student_id"/>
<field name="course_id"/>
<field name="event_type"/>
</group>
<group>
<field name="signal_name"/>
<field name="signal_value"/>
<field name="decision"/>
<field name="created_at"/>
</group>
</group>
<group>
<field name="context"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_adaptive_event_list" model="ir.ui.view">
<field name="name">encoach.adaptive.event.list</field>
<field name="model">encoach.adaptive.event</field>
<field name="arch" type="xml">
<list string="Adaptive Events">
<field name="student_id"/>
<field name="event_type" widget="badge"/>
<field name="signal_name"/>
<field name="signal_value"/>
<field name="decision"/>
<field name="created_at"/>
</list>
</field>
</record>
<record id="view_adaptive_event_search" model="ir.ui.view">
<field name="name">encoach.adaptive.event.search</field>
<field name="model">encoach.adaptive.event</field>
<field name="arch" type="xml">
<search string="Search Adaptive Events">
<field name="student_id"/>
<separator/>
<filter string="Signals" name="signal" domain="[('event_type', '=', 'signal')]"/>
<filter string="Decisions" name="decision" domain="[('event_type', '=', 'decision')]"/>
<separator/>
<filter string="Student" name="group_student" context="{'group_by': 'student_id'}"/>
</search>
</field>
</record>
<record id="action_adaptive_event" model="ir.actions.act_window">
<field name="name">Adaptive Events</field>
<field name="res_model">encoach.adaptive.event</field>
<field name="view_mode">list,form</field>
</record>
</odoo>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<menuitem id="menu_adaptive_events"
name="Adaptive Events"
parent="encoach_core.menu_encoach_config"
action="encoach_adaptive.action_adaptive_event"
sequence="60"/>
<menuitem id="menu_adaptive_paths"
name="Adaptive Paths"
parent="encoach_core.menu_encoach_config"
action="encoach_adaptive.action_adaptive_path"
sequence="70"/>
<menuitem id="menu_adaptive_settings"
name="Adaptive Settings"
parent="encoach_core.menu_encoach_config"
action="encoach_adaptive.action_adaptive_settings"
sequence="80"/>
</odoo>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_adaptive_path_form" model="ir.ui.view">
<field name="name">encoach.adaptive.path.form</field>
<field name="model">encoach.adaptive.path</field>
<field name="arch" type="xml">
<form string="Adaptive Path">
<sheet>
<group>
<group>
<field name="student_id"/>
<field name="course_id"/>
<field name="source"/>
</group>
</group>
<group>
<field name="module_queue"/>
</group>
<group>
<field name="next_generation_brief"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_adaptive_path_list" model="ir.ui.view">
<field name="name">encoach.adaptive.path.list</field>
<field name="model">encoach.adaptive.path</field>
<field name="arch" type="xml">
<list string="Adaptive Paths">
<field name="student_id"/>
<field name="course_id"/>
<field name="source"/>
</list>
</field>
</record>
<record id="action_adaptive_path" model="ir.actions.act_window">
<field name="name">Adaptive Paths</field>
<field name="res_model">encoach.adaptive.path</field>
<field name="view_mode">list,form</field>
</record>
</odoo>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_adaptive_settings_form" model="ir.ui.view">
<field name="name">encoach.adaptive.settings.form</field>
<field name="model">encoach.adaptive.settings</field>
<field name="arch" type="xml">
<form string="Adaptive Settings">
<sheet>
<group>
<group>
<field name="teacher_id"/>
<field name="entity_id"/>
</group>
<group>
<field name="step_up_threshold"/>
<field name="step_down_threshold"/>
</group>
</group>
<group>
<group>
<field name="micro_lesson_trigger"/>
<field name="module_skip_threshold"/>
</group>
<group>
<field name="no_progress_alert_days"/>
<field name="max_retries"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_adaptive_settings_list" model="ir.ui.view">
<field name="name">encoach.adaptive.settings.list</field>
<field name="model">encoach.adaptive.settings</field>
<field name="arch" type="xml">
<list string="Adaptive Settings">
<field name="teacher_id"/>
<field name="entity_id"/>
<field name="step_up_threshold"/>
<field name="step_down_threshold"/>
</list>
</field>
</record>
<record id="action_adaptive_settings" model="ir.actions.act_window">
<field name="name">Adaptive Settings</field>
<field name="res_model">encoach.adaptive.settings</field>
<field name="view_mode">list,form</field>
</record>
</odoo>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="action_signal_timeline" model="ir.actions.client">
<field name="name">Signal Timeline</field>
<field name="tag">encoach_signal_timeline</field>
</record>
<menuitem id="menu_signal_timeline"
name="Signal Timeline"
parent="encoach_core.menu_encoach_config"
action="action_signal_timeline"
sequence="55"/>
</odoo>