From 69d8a7c52f34b9cd55e1d5d9adf283a14be84fc9 Mon Sep 17 00:00:00 2001 From: Yamen Ahmad Date: Sun, 12 Apr 2026 01:34:00 +0400 Subject: [PATCH] fix: resolve all QA/UAT report issues (P0-P3) Made-with: Cursor --- .gitignore | 9 - Dockerfile | 13 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 242 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 247 bytes .../__pycache__/main.cpython-312.pyc | Bin 0 -> 1465 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 295 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 242 bytes .../__pycache__/adaptive.cpython-312.pyc | Bin 0 -> 15433 bytes .../encoach_adaptive/controllers/adaptive.py | 25 +- .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 321 bytes .../adaptive_event.cpython-312.pyc | Bin 0 -> 1414 bytes .../__pycache__/adaptive_path.cpython-312.pyc | Bin 0 -> 1096 bytes .../adaptive_settings.cpython-312.pyc | Bin 0 -> 1735 bytes .../__pycache__/content_cache.cpython-312.pyc | Bin 0 -> 2289 bytes .../diagnostic_session.cpython-312.pyc | Bin 0 -> 2290 bytes .../__pycache__/learning_plan.cpython-312.pyc | Bin 0 -> 3095 bytes .../learning_plan_item.cpython-312.pyc | Bin 0 -> 2021 bytes .../__pycache__/proficiency.cpython-312.pyc | Bin 0 -> 2368 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 336 bytes .../adaptive_engine.cpython-312.pyc | Bin 0 -> 5173 bytes .../__pycache__/alert_service.cpython-312.pyc | Bin 0 -> 3503 bytes .../__pycache__/style_matcher.cpython-312.pyc | Bin 0 -> 2112 bytes custom_addons/encoach_ai/__manifest__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 285 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 317 bytes .../__pycache__/ai_controller.cpython-312.pyc | Bin 0 -> 34005 bytes .../coach_controller.cpython-312.pyc | Bin 0 -> 6505 bytes .../media_controller.cpython-312.pyc | Bin 0 -> 11891 bytes .../controllers/media_controller.py | 48 - .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 260 bytes .../models/__pycache__/ai_log.cpython-312.pyc | Bin 0 -> 1847 bytes .../__pycache__/ai_settings.cpython-312.pyc | Bin 0 -> 2536 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 570 bytes .../__pycache__/coach_service.cpython-312.pyc | Bin 0 -> 7481 bytes .../__pycache__/elai_service.cpython-312.pyc | Bin 0 -> 5015 bytes .../elevenlabs_service.cpython-312.pyc | Bin 0 -> 4939 bytes .../gptzero_service.cpython-312.pyc | Bin 0 -> 4580 bytes .../openai_service.cpython-312.pyc | Bin 0 -> 20224 bytes .../__pycache__/polly_service.cpython-312.pyc | Bin 0 -> 4996 bytes .../whisper_service.cpython-312.pyc | Bin 0 -> 5667 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 296 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 244 bytes .../__pycache__/ai_course.cpython-312.pyc | Bin 0 -> 24324 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 294 bytes .../ai_generation_log.cpython-312.pyc | Bin 0 -> 1611 bytes .../ai_ielts_generation_log.cpython-312.pyc | Bin 0 -> 1878 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 316 bytes .../english_pipeline.cpython-312.pyc | Bin 0 -> 5626 bytes .../ielts_pipeline.cpython-312.pyc | Bin 0 -> 6974 bytes custom_addons/encoach_api/__manifest__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 228 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 261 bytes .../__pycache__/auth.cpython-312.pyc | Bin 0 -> 6515 bytes .../__pycache__/base.cpython-312.pyc | Bin 0 -> 7891 bytes .../encoach_branding/__manifest__.py | 2 +- .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 263 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 242 bytes .../__pycache__/branding.cpython-312.pyc | Bin 0 -> 9983 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 237 bytes .../__pycache__/branding.cpython-312.pyc | Bin 0 -> 2665 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 224 bytes .../migrations/19.0.1.1/pre-migrate.py | 13 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 478 bytes .../models/__pycache__/code.cpython-312.pyc | Bin 0 -> 3263 bytes .../encoach_entity.cpython-312.pyc | Bin 0 -> 3982 bytes .../encoach_invite_code.cpython-312.pyc | Bin 0 -> 2856 bytes .../encoach_permission.cpython-312.pyc | Bin 0 -> 1537 bytes .../__pycache__/encoach_role.cpython-312.pyc | Bin 0 -> 1796 bytes .../__pycache__/encoach_user.cpython-312.pyc | Bin 0 -> 4712 bytes .../entity_level_mapping.cpython-312.pyc | Bin 0 -> 1145 bytes .../models/__pycache__/invite.cpython-312.pyc | Bin 0 -> 2559 bytes .../__pycache__/permission.cpython-312.pyc | Bin 0 -> 1260 bytes .../models/__pycache__/role.cpython-312.pyc | Bin 0 -> 1609 bytes .../user_entity_rel.cpython-312.pyc | Bin 0 -> 1067 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 265 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 242 bytes .../__pycache__/course.cpython-312.pyc | Bin 0 -> 29739 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 357 bytes .../course_extension.cpython-312.pyc | Bin 0 -> 1239 bytes .../__pycache__/course_module.cpython-312.pyc | Bin 0 -> 1995 bytes .../course_section.cpython-312.pyc | Bin 0 -> 1268 bytes .../__pycache__/gap_profile.cpython-312.pyc | Bin 0 -> 1367 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 271 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 254 bytes .../entity_onboard.cpython-312.pyc | Bin 0 -> 13004 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 289 bytes .../credential_service.cpython-312.pyc | Bin 0 -> 3376 bytes .../__pycache__/csv_parser.cpython-312.pyc | Bin 0 -> 3034 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 237 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 250 bytes .../__pycache__/exam_session.cpython-312.pyc | Bin 0 -> 3227 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 268 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 352 bytes .../__pycache__/custom_exam.cpython-312.pyc | Bin 0 -> 17754 bytes .../exam_structures.cpython-312.pyc | Bin 0 -> 5233 bytes .../__pycache__/ielts_exam.cpython-312.pyc | Bin 0 -> 25781 bytes .../__pycache__/templates.cpython-312.pyc | Bin 0 -> 6816 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 600 bytes .../__pycache__/audio_file.cpython-312.pyc | Bin 0 -> 1705 bytes .../exam_assignment.cpython-312.pyc | Bin 0 -> 1219 bytes .../__pycache__/exam_custom.cpython-312.pyc | Bin 0 -> 1795 bytes .../exam_custom_section.cpython-312.pyc | Bin 0 -> 1431 bytes .../exam_structure.cpython-312.pyc | Bin 0 -> 1234 bytes .../__pycache__/exam_template.cpython-312.pyc | Bin 0 -> 1819 bytes .../__pycache__/passage.cpython-312.pyc | Bin 0 -> 2385 bytes .../__pycache__/question.cpython-312.pyc | Bin 0 -> 2946 bytes .../models/__pycache__/rubric.cpython-312.pyc | Bin 0 -> 1028 bytes .../__pycache__/speaking_card.cpython-312.pyc | Bin 0 -> 1623 bytes .../writing_prompt.cpython-312.pyc | Bin 0 -> 1730 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 238 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 262 bytes .../__pycache__/validator.cpython-312.pyc | Bin 0 -> 14565 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 224 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 246 bytes .../__pycache__/code_scorer.cpython-312.pyc | Bin 0 -> 11120 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 226 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 248 bytes .../__pycache__/math_scorer.cpython-312.pyc | Bin 0 -> 5754 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 267 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 243 bytes .../__pycache__/reports.cpython-312.pyc | Bin 0 -> 3151 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 258 bytes .../__pycache__/pdf_generator.cpython-312.pyc | Bin 0 -> 8788 bytes .../services/pdf_generator.py | 6 +- .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 296 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 244 bytes .../__pycache__/placement.cpython-312.pyc | Bin 0 -> 18352 bytes .../controllers/placement.py | 49 +- .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 280 bytes .../__pycache__/cat_session.cpython-312.pyc | Bin 0 -> 1726 bytes .../student_ability.cpython-312.pyc | Bin 0 -> 1482 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 298 bytes .../__pycache__/cat_engine.cpython-312.pyc | Bin 0 -> 7538 bytes .../__pycache__/cefr_mapper.cpython-312.pyc | Bin 0 -> 3120 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 231 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 238 bytes .../__pycache__/portal.cpython-312.pyc | Bin 0 -> 13062 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 264 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 254 bytes .../ielts_standards_check.cpython-312.pyc | Bin 0 -> 1384 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 302 bytes .../__pycache__/content_gate.cpython-312.pyc | Bin 0 -> 1824 bytes .../quality_checker.cpython-312.pyc | Bin 0 -> 6835 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 229 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 249 bytes .../resources_rest.cpython-312.pyc | Bin 0 -> 13651 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 238 bytes .../__pycache__/resource.cpython-312.pyc | Bin 0 -> 4187 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 294 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 313 bytes .../__pycache__/exam_session.cpython-312.pyc | Bin 0 -> 19088 bytes .../__pycache__/grading.cpython-312.pyc | Bin 0 -> 17953 bytes .../__pycache__/score_release.cpython-312.pyc | Bin 0 -> 6703 bytes .../controllers/exam_session.py | 35 + .../encoach_scoring/controllers/grading.py | 21 +- .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 382 bytes .../__pycache__/feedback.cpython-312.pyc | Bin 0 -> 1154 bytes .../models/__pycache__/score.cpython-312.pyc | Bin 0 -> 1384 bytes .../student_answer.cpython-312.pyc | Bin 0 -> 1161 bytes .../student_attempt.cpython-312.pyc | Bin 0 -> 2410 bytes .../student_progress.cpython-312.pyc | Bin 0 -> 1544 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 265 bytes .../speaking_evaluator.cpython-312.pyc | Bin 0 -> 3871 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 293 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 236 bytes .../__pycache__/auth.cpython-312.pyc | Bin 0 -> 16212 bytes .../encoach_signup/controllers/auth.py | 151 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 269 bytes .../models/__pycache__/otp.cpython-312.pyc | Bin 0 -> 1060 bytes .../student_profile.cpython-312.pyc | Bin 0 -> 2953 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 279 bytes .../captcha_service.cpython-312.pyc | Bin 0 -> 1734 bytes .../__pycache__/otp_service.cpython-312.pyc | Bin 0 -> 3473 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 263 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 242 bytes .../__pycache__/taxonomy.cpython-312.pyc | Bin 0 -> 9562 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 337 bytes .../models/__pycache__/domain.cpython-312.pyc | Bin 0 -> 1657 bytes .../learning_objective.cpython-312.pyc | Bin 0 -> 1801 bytes .../__pycache__/subject.cpython-312.pyc | Bin 0 -> 1528 bytes .../models/__pycache__/topic.cpython-312.pyc | Bin 0 -> 1690 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 973 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 232 bytes .../__pycache__/embedding.cpython-312.pyc | Bin 0 -> 6331 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 273 bytes .../embedding_service.cpython-312.pyc | Bin 0 -> 5606 bytes .../__pycache__/indexer.cpython-312.pyc | Bin 0 -> 4449 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 237 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 244 bytes .../__pycache__/verify.cpython-312.pyc | Bin 0 -> 3366 bytes docker-compose.yml | 32 + docs/06-All-Credentials-Inventory.md | 190 -- docs/Developer Workflow Manual.txt | 156 -- docs/ENCOACH_USER_STORIES.md | 2125 -------------- docs/ENCOACH_WORKFLOWS_BACKEND_SRS.md | 2479 ----------------- docs/ENCOACH_WORKFLOWS_FRONTEND_SRS.md | 2109 -------------- docs/EnCoach-Platform-User-Guide.md | 957 ------- docs/REPORT-Generation-Page-Implementation.md | 225 -- docs/encoach_workflows_v3.md | 587 ---- odoo.conf | 18 + openeducat_erp-19.0/openeducat_erp-19.0 | 1 + requirements.txt | 9 + 202 files changed, 364 insertions(+), 8902 deletions(-) delete mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 custom_addons/clarity_backend_theme_bits/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/clarity_backend_theme_bits/controller/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/clarity_backend_theme_bits/controller/__pycache__/main.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/controllers/__pycache__/adaptive.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/adaptive_event.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/adaptive_path.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/adaptive_settings.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/content_cache.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/diagnostic_session.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/learning_plan.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/learning_plan_item.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/models/__pycache__/proficiency.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/services/__pycache__/adaptive_engine.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/services/__pycache__/alert_service.cpython-312.pyc create mode 100644 custom_addons/encoach_adaptive/services/__pycache__/style_matcher.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/controllers/__pycache__/ai_controller.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/controllers/__pycache__/coach_controller.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/controllers/__pycache__/media_controller.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/models/__pycache__/ai_log.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/models/__pycache__/ai_settings.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/services/__pycache__/coach_service.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/services/__pycache__/elai_service.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/services/__pycache__/elevenlabs_service.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/services/__pycache__/gptzero_service.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/services/__pycache__/openai_service.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/services/__pycache__/polly_service.cpython-312.pyc create mode 100644 custom_addons/encoach_ai/services/__pycache__/whisper_service.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/controllers/__pycache__/ai_course.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/models/__pycache__/ai_generation_log.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/models/__pycache__/ai_ielts_generation_log.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/services/__pycache__/english_pipeline.cpython-312.pyc create mode 100644 custom_addons/encoach_ai_course/services/__pycache__/ielts_pipeline.cpython-312.pyc create mode 100644 custom_addons/encoach_api/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_api/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_api/controllers/__pycache__/auth.cpython-312.pyc create mode 100644 custom_addons/encoach_api/controllers/__pycache__/base.cpython-312.pyc create mode 100644 custom_addons/encoach_branding/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_branding/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_branding/controllers/__pycache__/branding.cpython-312.pyc create mode 100644 custom_addons/encoach_branding/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_branding/models/__pycache__/branding.cpython-312.pyc create mode 100644 custom_addons/encoach_core/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_core/migrations/19.0.1.1/pre-migrate.py create mode 100644 custom_addons/encoach_core/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/code.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/encoach_entity.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/encoach_invite_code.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/encoach_permission.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/encoach_role.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/encoach_user.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/entity_level_mapping.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/invite.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/permission.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/role.cpython-312.pyc create mode 100644 custom_addons/encoach_core/models/__pycache__/user_entity_rel.cpython-312.pyc create mode 100644 custom_addons/encoach_course_gen/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_course_gen/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_course_gen/controllers/__pycache__/course.cpython-312.pyc create mode 100644 custom_addons/encoach_course_gen/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_course_gen/models/__pycache__/course_extension.cpython-312.pyc create mode 100644 custom_addons/encoach_course_gen/models/__pycache__/course_module.cpython-312.pyc create mode 100644 custom_addons/encoach_course_gen/models/__pycache__/course_section.cpython-312.pyc create mode 100644 custom_addons/encoach_course_gen/models/__pycache__/gap_profile.cpython-312.pyc create mode 100644 custom_addons/encoach_entity_onboard/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_entity_onboard/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_entity_onboard/controllers/__pycache__/entity_onboard.cpython-312.pyc create mode 100644 custom_addons/encoach_entity_onboard/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_entity_onboard/services/__pycache__/credential_service.cpython-312.pyc create mode 100644 custom_addons/encoach_entity_onboard/services/__pycache__/csv_parser.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_session/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_session/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_session/controllers/__pycache__/exam_session.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/controllers/__pycache__/custom_exam.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/controllers/__pycache__/exam_structures.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/controllers/__pycache__/ielts_exam.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/controllers/__pycache__/templates.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/audio_file.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/exam_assignment.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/exam_custom.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/exam_custom_section.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/exam_structure.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/exam_template.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/passage.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/question.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/rubric.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/speaking_card.cpython-312.pyc create mode 100644 custom_addons/encoach_exam_template/models/__pycache__/writing_prompt.cpython-312.pyc create mode 100644 custom_addons/encoach_ielts_validation/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ielts_validation/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_ielts_validation/services/__pycache__/validator.cpython-312.pyc create mode 100644 custom_addons/encoach_it/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_it/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_it/services/__pycache__/code_scorer.cpython-312.pyc create mode 100644 custom_addons/encoach_math/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_math/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_math/services/__pycache__/math_scorer.cpython-312.pyc create mode 100644 custom_addons/encoach_pdf_report/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_pdf_report/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_pdf_report/controllers/__pycache__/reports.cpython-312.pyc create mode 100644 custom_addons/encoach_pdf_report/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_pdf_report/services/__pycache__/pdf_generator.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/controllers/__pycache__/placement.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/models/__pycache__/cat_session.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/models/__pycache__/student_ability.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/services/__pycache__/cat_engine.cpython-312.pyc create mode 100644 custom_addons/encoach_placement/services/__pycache__/cefr_mapper.cpython-312.pyc create mode 100644 custom_addons/encoach_portal/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_portal/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_portal/controllers/__pycache__/portal.cpython-312.pyc create mode 100644 custom_addons/encoach_quality_gate/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_quality_gate/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_quality_gate/models/__pycache__/ielts_standards_check.cpython-312.pyc create mode 100644 custom_addons/encoach_quality_gate/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_quality_gate/services/__pycache__/content_gate.cpython-312.pyc create mode 100644 custom_addons/encoach_quality_gate/services/__pycache__/quality_checker.cpython-312.pyc create mode 100644 custom_addons/encoach_resources/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_resources/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_resources/controllers/__pycache__/resources_rest.cpython-312.pyc create mode 100644 custom_addons/encoach_resources/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_resources/models/__pycache__/resource.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/controllers/__pycache__/exam_session.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/controllers/__pycache__/grading.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/controllers/__pycache__/score_release.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/models/__pycache__/feedback.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/models/__pycache__/score.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/models/__pycache__/student_answer.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/models/__pycache__/student_attempt.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/models/__pycache__/student_progress.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_scoring/services/__pycache__/speaking_evaluator.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/controllers/__pycache__/auth.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/models/__pycache__/otp.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/models/__pycache__/student_profile.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/services/__pycache__/captcha_service.cpython-312.pyc create mode 100644 custom_addons/encoach_signup/services/__pycache__/otp_service.cpython-312.pyc create mode 100644 custom_addons/encoach_taxonomy/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_taxonomy/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_taxonomy/controllers/__pycache__/taxonomy.cpython-312.pyc create mode 100644 custom_addons/encoach_taxonomy/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_taxonomy/models/__pycache__/domain.cpython-312.pyc create mode 100644 custom_addons/encoach_taxonomy/models/__pycache__/learning_objective.cpython-312.pyc create mode 100644 custom_addons/encoach_taxonomy/models/__pycache__/subject.cpython-312.pyc create mode 100644 custom_addons/encoach_taxonomy/models/__pycache__/topic.cpython-312.pyc create mode 100644 custom_addons/encoach_vector/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_vector/models/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_vector/models/__pycache__/embedding.cpython-312.pyc create mode 100644 custom_addons/encoach_vector/services/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_vector/services/__pycache__/embedding_service.cpython-312.pyc create mode 100644 custom_addons/encoach_vector/services/__pycache__/indexer.cpython-312.pyc create mode 100644 custom_addons/encoach_verification/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_verification/controllers/__pycache__/__init__.cpython-312.pyc create mode 100644 custom_addons/encoach_verification/controllers/__pycache__/verify.cpython-312.pyc create mode 100644 docker-compose.yml delete mode 100644 docs/06-All-Credentials-Inventory.md delete mode 100644 docs/Developer Workflow Manual.txt delete mode 100644 docs/ENCOACH_USER_STORIES.md delete mode 100644 docs/ENCOACH_WORKFLOWS_BACKEND_SRS.md delete mode 100644 docs/ENCOACH_WORKFLOWS_FRONTEND_SRS.md delete mode 100644 docs/EnCoach-Platform-User-Guide.md delete mode 100644 docs/REPORT-Generation-Page-Implementation.md delete mode 100644 docs/encoach_workflows_v3.md create mode 100644 odoo.conf create mode 160000 openeducat_erp-19.0/openeducat_erp-19.0 create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore deleted file mode 100644 index dc5805fb..00000000 --- a/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -__pycache__/ -*.pyc -*.pyo -.env -*.egg-info/ -.vscode/ -.idea/ -*.swp -*.swo diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..d805796e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM odoo:19.0 + +USER root + +COPY requirements.txt /tmp/requirements.txt +RUN pip3 install --no-cache-dir -r /tmp/requirements.txt + +COPY custom_addons /opt/odoo/custom_addons +COPY odoo.conf /etc/odoo/odoo.conf + +USER odoo + +EXPOSE 8069 8072 diff --git a/custom_addons/clarity_backend_theme_bits/__pycache__/__init__.cpython-312.pyc b/custom_addons/clarity_backend_theme_bits/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..119e0fa0226b0daa8ce761dc8219aac550836496 GIT binary patch literal 242 zcmXwzv1$TA5QcZ|KtvEy+FD+dO)LZ<iaCLV_c30(|#1}~8vsl_)VUsFd zz%Etxg87P>?}rb*^Kdv286S@qGtU3B6aOggWuqKWV`=95cy^ z9Ht~;=*3lmmiw$mFCE5hhz{ zQn!T@UUPuQ;p@Etr)`uRi(DxGX~Mz`9IcE0N6XFfK4B!w!sT915zo0PxZ0^>*kXBa z81ag*tYz!E+Ekk|*qR*aWat)v zFK)=FDSwEn%H6dwht^W3#>>t`2g4Vze7^|}j;k8w&1Dh^K4Eg4;*hB^v8Y{V5;Tj+ zlvtQaF~FQT7$(YnLUZMqcq>eN_?YFmwQ$*GTHh=scFc-a6q)@kc5JZ2;ZV*GVqV%; z2lO}9KZ*&B^@asnR^7L-9?{Sxptf*r;kq8;FzmDWcl3ZfHitspPU9r>O$*~Nh;`eu zsFO6zWtce2??-H1s?|b>DJ=TGU`KLw2S^`w==I=L5Mm`>%Pe{f7z< zJN^vV6ZHGkOnYu~Zp+)Bnrr2LE}d`R*}St`*e_juURu~MEp$t7JultdFWo$tn0mUj zRoS_`eR=m>_uQME;?+)}){}&@*IL?PQmDhdUfKk~Jpt-t|3GnS0>3jdB;1SCVO5 zT;osHU<}7@A9rdH5f5Y(CClF$UXp@)ehSOs9uH^ZN2>@9F$5;eV>VY|csEK!ZjH9y`S16?xTFJ7?sq zV+dp2PJWQ;Ev^oH)W&79BNfAtqH`vd*kqHIR+;?J)+ZvZ65Z+-!gstR{RLgvn z-UK=KQu98=C!>ZuyPRF~sAJsW>V^mNEcTCFE%Fe(kXpx(xd|#tHK!>1!7dFK!Uj7C janX<4=9V^GICGcEAC#^0G2xdX;u=oYaP|eKsiCVs?5|H3 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_adaptive/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..427f972713c17f782f38db68b6cd7617a7e91e02 GIT binary patch literal 242 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 T71^<%x{|+`{~H3+!rJ^F5T6|Y literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/controllers/adaptive.py b/custom_addons/encoach_adaptive/controllers/adaptive.py index 18bbc6dc..4cb0b32b 100644 --- a/custom_addons/encoach_adaptive/controllers/adaptive.py +++ b/custom_addons/encoach_adaptive/controllers/adaptive.py @@ -27,14 +27,33 @@ class EncoachAdaptiveController(http.Controller): from odoo.fields import Datetime as DT today_start = DT.now().replace(hour=0, minute=0, second=0, microsecond=0) - total_students = len(Path.search([]).mapped('student_id')) - active_courses = len(Path.search([]).mapped('course_id').filtered(lambda c: c)) + all_paths = Path.search([]) + total_students = len(all_paths.mapped('student_id')) + active_courses = len(all_paths.mapped('course_id').filtered(lambda c: c)) signals_today = Event.search_count([ ('event_type', '=', 'signal'), ('created_at', '>=', today_start), ]) + avg_progress = 0.0 + if all_paths: + progress_values = [] + for p in all_paths: + try: + module_queue = json.loads(p.module_queue or '[]') + except (json.JSONDecodeError, TypeError): + module_queue = [] + total_modules = len(module_queue) if module_queue else 1 + completed = sum( + 1 for m in module_queue + if isinstance(m, dict) and m.get('done') + ) + progress_values.append( + round(completed / total_modules * 100, 1) if total_modules else 0.0 + ) + avg_progress = round(sum(progress_values) / len(progress_values), 1) if progress_values else 0.0 + recent_decisions = [] decisions = Event.search( [('event_type', '=', 'decision')], @@ -52,7 +71,7 @@ class EncoachAdaptiveController(http.Controller): return _json_response({ 'total_students': total_students, 'active_courses': active_courses, - 'avg_progress': 0.0, + 'avg_progress': avg_progress, 'signals_today': signals_today, 'recent_decisions': recent_decisions, }) diff --git a/custom_addons/encoach_adaptive/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_adaptive/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09915cee70c66658261acbe0cd50b8d50f86023c GIT binary patch literal 321 zcmX|-!Ab)$5QZnaTPTGscvkT0UX1o22;w7n^Wa`W*bHvUCRviSvUlIXXYg5k0HIJX z;=!BHTTf1E?HvAm^JNH0-pX@5@*C&o$WX$ z&g-1PP*kIDM&lJ*O{J23)Jqh&L>tMJ2h+>gk~lhufH7+O81AZK1wN+}e34>A@d_JC z*tYyWpbvbI2CZz3RJ`|Yj!g`+i`f--%DG)!UUQ32V!z3oMTpJ_sg$#UqivjQT5A7p t$Bk3i1ulfPItp>#58Lq#$wh~^KK)L5Pnc5t*enxZKRKm^wS5_bTSu+UH^PAA`? zlwniu$hvaC6)q)H89t7)m@>}4%3xjkA8X_NSDAaI<9(m* zEb2@2)VgQ;(B8g`U@LUmc)g9iuv^BNwFbxL8cywROlZ~X7!uF%wyK#!(Iyy%7+El^ zA{^M=9Kk^?3NQ(7(-|8EHbhvLs7CPJ$RQX}&G*=7;1E;AVd#E0=eKIMACUlewE%}z zFLGU7AURe9pQOOq@}NuATj`fsG=yy@aD0zySH_6ZHAX)`+()2t;B@i9@0l`#@FtAh z@TOj-nq_&gi7kufEsKq4zMqN@KQ=sk&l>+U>?jERrUeo5y}%fsKU1@@FtUqmOmr))r`GBaevMPXdlLN0 z#12U2&c*A=(xv!%QaBr5{i{^%mHU<5%HW-+;cw2LUwu6)eG_ja3zeSQFYXoxvrikN zh0F2hNol!P-Y+dbD=jD5nMA7|D$;xEp$bZ;U(860<#^*z150On=ld6TFAhE$EnbMf zNR}$S)qZ`q{{0$DSA6?n`|*QE4+hexcrN}dnSbly=Hok$?tIsbuO*Xh{9OK}@}#n_ z*PrS2QR$O!HweEeX%RPdh044|guiFmIV(5#BbF66y&d^J(o=wjhxx`fdA_V-o cIFtlIcn&Hr)S|HV!|G4Ajh6TEwogoI`;nivn>h}8=xXS&_M#W;s=f4^^j^X>PT`JBsT0bN@^ zPOTvxfbWbXE8PX{NeUVO0mRwB;dIX7b)Ew}m<5R60w{&KvX~sY_%>59)`hB|rhhV` z@@CY)3JCc`wFm0A)XLO)h4-^500gYLBXr!D-j@ zpt(MUU?sF(<7F7G*M@NHEWxg~RAKJnL{wbB(046&t=N&vJ`PGzfc;>FWK0;C5Meb% zBp+`?mX8sUJeM{ZhnS=-iZ*MqS1FlZW>_(djR@M^ zopeV+od^e}Z_yTbuFs}Mq($gf$2=F4Y!F6>reau#$Z^&T3M+UsBuY2%Mua0w8F*QL-0ClEi;cdWzJs2l@=5!Gg(?no} z`Rql;-A*sEXBg*~XWovwK+(DMFmCare}htXzk{pPoTWI9`w9xbMTNVwduxAmZ}bnK HuygV+VT2^W literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/models/__pycache__/adaptive_settings.cpython-312.pyc b/custom_addons/encoach_adaptive/models/__pycache__/adaptive_settings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8c4b34db12974d186541be2ceddaeccb34aa7b0f GIT binary patch literal 1735 zcma)6-D}%c6u*)zTXCEZCr;xgDe)kr^V-Q>IbI+Ib z)5u61P}+O>!uUu4;8*q%kk}V`pHkrvKma)tR5*pJ@CsiM6oCUg_zXaP4?qF&WhrpH zJdbHiMv7REWW@_6W(6W>Rf9w;Hbf>S(Sm_Yh;?QQDAE^tCdY0@K;a-zc*rRNtx#qMzUS+65bIvEb3GwF|addVe||geln5+n|i@D+hVDuitPS zc*>Q7ZT6r(dkV_Y&}&}|CeDF6UDhp!-AdC*1vRdl$Z_u@XWP(GHbQRO(6(t$plxBf zUyT}Sk%z;w#=KP82Rkdh+s!HOjN>i(uOirlk9dd+uIRDK4WDS9}Q zjKu=R{(|^~vOUmETyNyNlkYb+&y$(`D~Iz3^WV>&);r1d#^>Gf`TgkO*umIY=GKoZ zo$-9*PB*>KjJ6Z4#L*X>^wL>msynmTTx{QL-8^zTGasHsrn|G*=5l+rwR-waXO=3` z-MM$08|}^3=4q-kw|o}4+P!w8`BnR2>*48o=NeVabSEIrO literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/models/__pycache__/content_cache.cpython-312.pyc b/custom_addons/encoach_adaptive/models/__pycache__/content_cache.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6a4ef213db7f12e4c671756df7f908502a4ca85 GIT binary patch literal 2289 zcmbVOO>7fa5PrK}+v~qZCTRi`43@mwwh~eg6*o%S3#ZQ8AM6&N`VO-* z^JeC~H}lQdKV>pW1Z!aN2mNCKq2HMhu4urly#>rN!U%IEB(pDH;>x_tbBvFaB4t4q z%27GWAs!t;Sh$36lnBLi7^w4IjrhDAuW|X0Tz#|gvbu5lx0Y|ZLE4B)cWJ`{Fw*9`;O-~^l z|AJeE_-x4u&u)V+b<@>AkW-$;K=+={!(Do4i-XTv-V&dl*XKnWde#Ofx~%$f@)DBQ z;S|vIwRAq?W)B;hscNSWnubjb`yjBSzLEIKNzK)zA|+?5IwjZ@O#=!;Y~n_B;4b7NP^}cXP${W~YU`%qrVe)m*b^&M)ofiO zuJ}g4fmVQUbys*3D3m^q$%0xf*$6s7+ltF16f8NqGIGMu+Nsb3_IrT*79Uo#4u)qAA#@VuBXjfc+URMs zO09g{O%lVZQlgj!anq-WL8xjItf)3+&vwN_AhM=#BZhgNvNS-G*d@jDzsb3RMM?`6 zOUTHRa^Y=@P^(Z=%fwJmmsMP-P_sxh+nRc5YPw)z)AY#8dkY3RuLPR~t!mk3Sy3@I z4XY3!07SK7>*q+pZ^J?W9mRvrWToaNbxVPwGf32jdZ2Eyv!8|gS@3?;K#rJRl&(lE zaf>5m+tSEAX~fBH{#Dwzc=5``wlvz5M(<18ZrJVdJd!Mj&a_^Wo8xj* zlJAQ08pQcGLgJwC5b`=C;{PH9YWNf%>;!-H!V*~azz=A}(5v&M!yT0L!boqg5H|)) zHL&RG#0xn(*jry*7g}__A&P@&tQh}Up#|nXivdRYxqQs!b?9_&3@E^*!}8m;3W2fU z&k?#A0#P=k@=3ah@y|0d%E%Za+km)2(Sn%}Etx8|JP$XaTjqjE%K&rcOt%8@K}?@x z9x2;Y)QYZPU9;=My|C3~u!T8OAl=}4uzu6>_|mvDkXy-I&$I`2GzWG#xsi5mS2MTE zd1d#v`@Y%tsl8lZs^8f5<;3R`t<8no^UnSQ?frB2_Rn2Arh5Lg$|IEbulaEk5k)*?L>|8$Uii%=D*C~pdR1|2KYKie_MLAnlOTkXmGXW(g zmPU1GF4G9Q{Df-MreFkknR62-VYgN3C@<3Oa2;2~!I1Ok zo51E2WxeQUCwhYY5AfeH#k4Hx-rJst`}|zb&}q=IDQGb~J&JG~_X|q>hKBw?!+*uL Sa>;8itV~>=_!|N1`Tqm?CG;}@ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/models/__pycache__/diagnostic_session.cpython-312.pyc b/custom_addons/encoach_adaptive/models/__pycache__/diagnostic_session.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f2426d0e8f394e70b1256c36b1471bae6c1a615 GIT binary patch literal 2290 zcmb7GO>7fK6rNrG#J~BaE*K{^Q53KsaT?m704bscDhh;F1gg4~R@pV+8QrOx5a`}yY0 z&YSOz{cAiPK`{2-|3&u&5c*vh-T>Pk+vi|fMi^nKi1K2Vi&9C>%OzjlCm|VqfUxf# z!hRwbLhhQDY2D`-`M`pd4g4vL>8#9yB@>e(

-6fx6UR-mA3Y|ltyXM*w)MtK=a zc^{VZei@NKA=bLU(XkKvaRB?D1lRqJC*QFvwnJc_gm%6zWFvdqWDVoUoQ$JSV(YS- zHDY5EZLo1b!8ePMkJ+fCW3|e4*T{F;h=JCaqr>^ycng_-BU|?C*)7}7e!aN!9?JJE zbY;8w-m`{gs@nB4x;kf=%+j?hgfZPT7L&w@jN+ZpD05@|O?c)s6W$UrtcjDg&)=MB3bM8F|5r9FJq%y5 zA1g6u<>_pg%R1%}W|c8;Rk3x4Y(kH@#8V8lM0k){s#RvZ_hy+uPnZT%RD<0ng1b>5 zAuvk8s-=o_Dh28(s>NeFL5ZVo=p`z4ORGIt5E>skbz9EEoL%6@d zOoIoCrivLAh2mkInX@J>sTLK-2R{25Db6y%)XXcIyDC~Nw*a{e^?FIgIp`75J#2hz zd?IIJ)3n7~lR1Oj77ZkVIjzhrv!tjP!?|*9qqAoc+@f# zbzWDnu33viyS*KwEhuqF_C1ISYJ_6piRAK)r5laG;rifYb#StA;#B>_h36+OJbZiY`0DXTxIR2l9iFJ| zKeqAl)yCx1Pw5}iD??7^qt)cmTJoJ|xG{CQJ~jP(YI@~NJvCBIjnq@es;OfyQj>r6 zMYmOc9#fQ?Wwj_S6Rd#4otT0N z)2I&BGz}`A2Ohel8Vlos2TcluufPMS*%(nG-f`Zr$Q+?IA-I2r+_4;5gwCiIv2#IV^wGqCJ2q6c82X(7Y|V+*0MZ$R8bjo6{e*+$=Z<>F>f=0RdPy_9~m|Ecw} zzVXRtwVux_A2vMq#)0u4W}cm|^;`pIy#LE<^>}|Z-roofZyb7W%O|IUn_a1w0l9Oa za&9Y#l806jYXhqTPo>(v@eO~X(cAxEc=_%|3K-N!K4&fxwUq8_3qyYRD1D1P>%jU literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/models/__pycache__/learning_plan.cpython-312.pyc b/custom_addons/encoach_adaptive/models/__pycache__/learning_plan.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f57484c2c997b35f876ea4113c0f37152619ad39 GIT binary patch literal 3095 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 r-1=6BHlnmf-#cJurCp8gLYsu%e$EXUs6 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/models/__pycache__/proficiency.cpython-312.pyc b/custom_addons/encoach_adaptive/models/__pycache__/proficiency.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c19304c9006ca45bbdd148eb6523a80c993fe89a GIT binary patch literal 2368 zcmb7GPi)gx7`M|Tb=`zCZD>oEw5~S(WNPD3iD_sEra`+gK|4gzv}|A*zgKXV*x}h> zOEf_a9L5QHYAa1DyMfAq+c@qvv|XAlQml6w(oVZEb-Qrd_xuM8O()HYK7W6H-{<$f zf66b(q{zWDdgmwoQH^|Ga;kC*k4)JBK!k73;q!i(~2=^g}BDXlygZbsS zj}5&xdpw~Otw-~*Kbeq^(0Ii}xNOn*l8(#B(n1bg5M=uj&pwE`5|6l21o5RF6e&ef zPbn7RaC~`B*vaEj6va>+#UA!j|Gl;1FVPZ4le?PH1 z?qPBhZpfZe(nV!GDNHwgp_FnFQrPD4Xiq3k8c>7F2fCnAXyC<}GAMnEEA6ch=7;Fu ztf85zcJ&itF6o+%4Xxf70?KrSYDl^7yj?@su%$(_s%ughKUh&M8=1-ryFnh@IPOj)^3j81z zaQVi&p({uP!_kpcsadvk8A~-ozgELi6%)yKmQ(|I&IQe{ntPxGP}btxKfB%f4YwS& zx)6>Fs>pL-_dCNkxi8TA{TkN(4`eViA$N!=ghZd+C1y8d_n7XYcs1@WF}oqV$7DHt z?Sa#GnQzbzyaoi3jCI#95ADPTl`vqZfLCTG0`cGVpNAbapYNv;9Z~UR_s~SZ8)^lE z#cNdPCb0OtYY~DjqoT*T+T<%^LPgCqmUI{?4bx;9CP+~&3&Ri50gtP|xG9=hGi*4E zhz+YouwojRu+)$g5E^BXNt(&*wq!3OY%7rwAhb`n%q5dlRGW-~oabrO!sR84^{Djx zOZfsDP`M5<4E1V7MKVl0n>}l$IP;EdBGYuq;iIyFzfydotihC+6-7nJG%VSlQV`Xu ztzXBox7%5$V51bOb=q&6idxkbq{C>B&+gbdg^-=y!ulRalXHZ`oz(4ATiEw>aCr6L z%0Xvrd_!KBJ7ZI=u_-4jZ7i%Wbh5=(w)h{G(d|%8XAa%C(wW_AN0N0!p?ai4NH^4H{Qq@nAyO0-(ZK)u_*~60_>Q ztSgPpl}#w(i}F(8lxkyJhvK`1?mcbT_zHw!WhQJPQSl^H$0n+7*mSQFbgtKr-hLzF zfP27^3Febygw3Z**lDaEfZXDo#AI{U87ef-ILXQ8+|#slcX)MTW#Zl&kL(|HNJ~5Y zMe}1PP;X7nJYIZqdh4RvPG1InYW&;lcW&Okxpwn$=1JeyXBXS4OU;j*jC6Ny^~}nd z`$Lb8wKMNG&pPQG#Lcc`?`iGy+u)da6A%k43%_OdgLP#8-RrA2R&Lx^+atxTXy$2l zdTp+goo;2P9pQi@e6SshG{?@ezaQRhr`VNW rWZ=1Q%q!k;B7=d=iN#X-tcU0M-?@pu;}g8NHoTEt&;G*!>w5kR@mnM= literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_adaptive/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce456d38835ba5f616bffb7ac20c15ef0011d0ec GIT binary patch literal 336 zcmXv}y-EZz5Ki_7{9(@rxEF8{j9wuKB3Rhk*=!R+GPpT5$&%zww)Y);2A{c`u41g7NbGp%vz@q4A;gFF=>^K zJVl;W86{m-=06nMOWM!wlxU+~!@Ygd7Emcd>>A)kL|KC$1kr$xJb+(o2@hr7pNPrC zVRZQvhxNo~n0$`#Ms|o~zhsYS3#=0ctf-Apto3dQGKR&);)*%t+z6M~%)&FD9+_N) z=nNN1IU5*Q>4dDY{5zFRrv%2iwmNct-gf(g8{^cffm?r!tB3D}8NxQDly1n`hRi?7 I+#jO!3)=NyGXMYp literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/services/__pycache__/adaptive_engine.cpython-312.pyc b/custom_addons/encoach_adaptive/services/__pycache__/adaptive_engine.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b4c0fc6427aee56361c9867c23cd79ed913a997 GIT binary patch literal 5173 zcmc&&O>7&-6<%`5&w)y!xZ%wGO?PYK6rK&1{)NjkS#+kn!mP1 zo1K!Vw8dk|z^_C13AdO2vX8BAkS+^aImXQbhbbVJH; z`PDd*Z{|2fl~z|lrh#=FSW^is1E-?MIWCn;O9?e4=Nfn>EOnf+k~*kha*CUihgY$j z#Gru_GZI!6LpV8Mw7;E8n)}~5_k_4Nxn#7zpL;^X>@!9W5wnE+s-P}|ie)*2^cI6e zY;GWiv&2xrG*nP=Dw&k9-kLRbDiG5enA>u)U>PMCMhQqWed{@8{NK49Gf>>ZR za}L=d8&nYjsU4>2dYD*je_;d&ly59%JAr+9DS#Ehiw2eBflD#WA0Ey& zLU#$1)8>7;L&+mqXB4Vhyo zy|8e3Zf2f$>a>)*VXn|ZSlsjVz3FbtRK*D&$Svi*e<%KiB4H)ICT69axSSPH9HNz6 zJ!O1!{A654vTSr?r{g*4CJANoF`mdPs+<)>gyft8o-&*QQxh!Wpz}s5At`Z-BGl1g zbxrptB~`FYDa6h{2QVXzA4%9NUqJUBRb!}dq#PNqv`kc6PE}e?ZMRI7+*(VdZr!`}Y3D=bi&x5nGv$HV@@uc(y|o>=R+{~)De~cEizD_h@x|%#;BB``=#*bC`nF>Fn4UJcaE?0&w zYdr(io{37&#BRV94%R4FAov|ivEkp&Rl^gN@Wgi0WZ6CW3~Z+ojTeF(rE$4`2R&SF zr^2d)$!O_1>RWU2yYAcr0CH*v+8zKfz-2dJ;)l3gMOWI&91WU^dpT&`jp%hxl3Mo` zy=fAF2O0nZWS0AO>nhpcViqCOkd;^7f&jgSTYn|mMqH!zq6hr$MZNcFNF05IQ?FqekPRvf&dm56B#Xq# zs+`I}LdhX6E3Pz@M@UMf6eweqk?-3M@q;r}azRtXAI74U54VYG)CJeqD*eRG~IBHT>niEC0D_NZeqZLv}7>Rtp z!!aV<42haVsjweIh28_H_Atu`h$<3b;(OFCL$T3sBK_6K$x7s8X?BNgDTiOKu)|e$ zyuyxevy&yK77CYJU#^6PtD*5qXnZ>~Sz@$MWTWd|*XG)Gh%YfaBtdJ<;gV~|-E=2- zJE+Bmwa(sMCmr>EN6{W%%}e=1cW298qm}U3Bj1=7;YzcbzxmG9+gCRSx2}}iM<4sg zv<~j0;SYzkQ0Hc1>vWlgQEYR5>-Z<}kK<)_Tx0o~%fSb0ZmKP^nXY-L*x)nD5gRI9 z+4WLvOk-nJwztCeZk_t{7v;XwU$Rp>f#$n!mb)h^t&@)elUk(j_AHbb(Z2uv;*Vi* zA4|48SqYzb-T z+&=Op8?Vto|F$Wn#Rl%WH8!#lychg*{m+T=wYRtDgi6n^9<$<3OUF~npHG=AJ=;Nw$4;~#x(BO)?9^~*!3|T!GBOpps7ZKK&_eb1n>B7`?ZdjwDvyI zN4akzv5msL!b8s=rz?H0Y)7tuP#YXG1IOGZqIxFKzO`f*QwVR4*Rng^Wb5=YfWN)~fIvYpA=5Ze&{-1aOGK z3VRQlePJUHlA5S)JqkAFsI{gwmJbz-24&LK17Bd+MjbKt| z0%*Dspq83~OyVIuk}|4jyffh0;vlb742ii8VdS+^2V)cMkRYlB``I&vQ2)<|`?JIS zi0hx7>VI{re;$tkvmQG1^2OsoU%1438esMnqW22nr*ra66LtOOGf04Z1qkU@RJ=s& z!)JjFgb&~B!@*z2RT;q{$s8?+)cUbnjEU zcE;%jNa*gaHC|=JI4wp3z+yISK!|O5$@c*FEsQyb1&f<2T6MC6LcBBiwkAbOe@I@o3q>A{`Xw}WajL))~6Kd H4ORaFdnf4T literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/services/__pycache__/alert_service.cpython-312.pyc b/custom_addons/encoach_adaptive/services/__pycache__/alert_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..698c75aea74c6a53d670ec6ef498997fe85bc29d GIT binary patch literal 3503 zcmbVPO>7&-6`tiTmp>v+N+cyxvaD5NNu({2)KBf$kqs-7Wg9l^q()IxNxRr`R^rkm zSKVFNAwfX_>b5-iAh!oaXahN?NU#C9K!GHu`WT=WGHk*1wguF`gKu&aw17{2!{v%@ zq{2m4;LLk7Z|1#u^WOJHzw>(C2)_QG{6QLTL+EdWu|B3r?7auX8o~%uSu{s_Tb9b% z=4=$9=`5XN<`@dukccvk-K-7FUSuCqCN<}AEzRX+E-MO3Udk_Ui;BFUh^op7 zdCa90QP4z{(?lVa78On)`>FAiWe`z&1b#I9_O5~N)=-JUR0P;e^ZY>Wf0micHjuKt zQi=vC`jt`)NHMRJvX^WbV&yl!1!UdRGFxKR07%)tAp$J6V^*SGmYhMW)b}4DwCpH3 zGVH+>?^7y?6n5FEIjz~l;w0m>W?Q}GCCz7zm7I?pmi8h<+p-I^`mNbkzw9o#RqEdL z67!0)ww2l%C%6oIc}kv4M{5s@$^fOqx#sBwn`Q0t zk^f7jA7&T!;v>!VKIq+tX@N3XY<}3xOA2!8-c^RQ+YBmjvHs%EW+gzO17IaI;f)h-?}M0>=d?5cS6a?u z4hsbnz#4#M!Iv6$ySe5!Eo8GI=6+bM8ZNphZxN=iJX$oW`&U%D6(^C=lH zFm9=itD>d>UaG~;15*vFilGDJi-MLedUJx5jT2S3C9Pm|=4IZ3T)tr~PmF&?d;-;g zA&lW}dVrU(L7g+)CM;uK(2BP6=M;j*G1_p!>G_-tg+%ed$P2>9msC+v4VFy7Vh3S? z0BMK1l*6TawUO%J=7+wtc&tp-*St&0*BbW|W*|Snk(uzkLMXFU|9LS>xyBr93V=!MmoB1m22~!_+oPRFOT|xW}UNrdh1G;wYCE zRH#-O2iJTj4<)M5DqNNcTq6=hE-R=SS7aM|#A6P_v+o{ofI`qyX@|z}TMK!uun5Lt zg`lCqfErODAh>iIn(0O*#Grh{x-PRCzFbbZ0hRmfPk(O38?e`7L4#43uxzj@RM=G7 zp!4D#h13LvJT(mG3^)xl@wg#}SD7%4w5$Jz}#l~oN|%-=SgH=7}B*e{YiGMKj^ zKn>@V6`LN&5#EY(2pCgbAj&@W2X`jVsfJyJ(B>Jk|ZLN ziPVy+$vIxYSk9}7W)1>tK8O;qCwUC12{YH4Y<#g`v;z*LZb78(=VNj3uy<7afE>v- z^;?jIAD~?i3U*bx#;Sqwdf<&};Eh_~Y}u*%1C`)#)jv}Ak5&C+HUC7}uKPMFffH5V z$+|CD^(AY*u`;6vI#*Y!fuVX}xEdI)1>$ArPFLUB%KeoGO0DZe+4I!bqxZbNF}Xfj ziA_Bjtwb-@dS=VlcDi2QLs8cis(eWgbk_r;)xhYNfm4s)DbM^V)U(Fl=j)+pH59Fd zPCWYFXEVPanW~1S%CmZBZ@n{G?TnT${Uy+?`@_2|3Pskg-oN_5_KO?ki+Z?s4;}Mf zp;j5aw||3Q=j*+RYHwoIt#bo)Zmi0U>7o7yU9EX|&w1?+^v?OGkGY+1|atemqQh;x2 zPSnyeR^EgiwvaLjopP2meH&glC(SdQS1!Q>sT}GsG~hpq q`Xf5>XLRfzsB6dFQy!|jd#di94=>l;10Oj4#h#_WL5Q@C-Tn>DRCRO! literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_adaptive/services/__pycache__/style_matcher.cpython-312.pyc b/custom_addons/encoach_adaptive/services/__pycache__/style_matcher.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e93ce73fdeb0d751edb291df8c1c864acadc37a GIT binary patch literal 2112 zcmb7FO>7%Q6rR~1+i}`DaY-miskW7()GF~NJ)}@og^Hw5(UvG~kg$Z7&Cb}~WbI97 z#)%v`B8Nx>REbatr4pQgL#raSoZ!e2gb*$Tnl3$5;>4|Okbs_ev-YM=K}d|`=Qs0y z=Dqj5H~a0*ok;}i&dN{jcN#*!%1yNN7PI*#FzbjQf<2T+3ZiI6iIg7wQ{^gd?(%98 z5#?h{RH79XqLUaKQ85S=1qtFi)iSM!j26V^U0$`lAYoUDD|}W9;*8qFtrUaKS+_#D zC{f`$4%lt2D2L5qI9i9S@|d8!LU3NC8c|lz)s|{rhrQaikJYq{9_+}8nn%yr!YNU< zcyiLN%yPq{Hmkt32BX}sGKX?w+UArPe#PLTN+8_9HZ3k)7;}skD5DjJW*wPiv}CSw zzc~TqZFL=qNP=eC^;)NOTtrb#-&I9~AF3;>Y5^0xlK4!C4Cxcpif!YOXe6L4l&_s2#6J8Oj&lW_AqhGv&+-OKE61VYwPVSgVwg9 zD)HMX6n zh^KSsUOzo_% zm|)lTI2Zf>BZ)3)J^%zl{=FCV58dh;zR@>)ecxBk| z0nL9O&5I!UKZCiX)|D~zp5`b;Us`|c%)q4dUkW*55sRsTYyq8o@%x}jG9+#8}Mx-9hDb`Qoch67hF*?3byA>+s>>Z zd;{1_Hlwj8;X1ZQk`$0YlcSS~u|9dyFNth{5EIrd72?gVB0L5=KnPY7qg285;6=Bl zYt8pyaql*e9+U0^YyJul04erQkT&)W{+u4a)O~s6+US+h>(&p4#x9OD(&MXfAh-MW zuP!taqo0b)r#^WLn73BBhWhzQOVNZiEwjan96!u7%B-RtDh zPW?5!siIi-y^y`v2kd=C(~pFQA=mUI?K80;?)k-{{El_Ne4GZJGIjt&LEMrO*oD}H zR}RAYqcC8co4Fikhd?0TGJX=sJr!g83)*!z*}pn?E7^Y|*?;Nfo5_LY_=6ZqWjDI_ oTpDV09o*>ZSzBzR4s1NJf9?7E9eS_QK$)Qtx^Ud%VGjFrm6sX>hMt4K~vkd=L{mJ%}%gfN+>s+s}U^U>fNK3~V?r;2acov=KB1&b{NY!F8;*o&svyI>cM zKbvZy1{6s28Oc;-_W5S1#x7npE zdmUWV%b=}XCt5kv<;B_JLXsug;$Qm1dJW3QAi`F-sS}X3$>#j+UiTKKf3n j({(>guL9Xk>#ozdnei|AfblL6aSO*=n7_b0O*#4mT9{X= literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/controllers/__pycache__/ai_controller.cpython-312.pyc b/custom_addons/encoach_ai/controllers/__pycache__/ai_controller.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8a0af463caf1e19b140c5209981b27a01473f49 GIT binary patch literal 34005 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 BmIwd< literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/controllers/__pycache__/coach_controller.cpython-312.pyc b/custom_addons/encoach_ai/controllers/__pycache__/coach_controller.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a70bd2c05d4805cb2574ff51899ceb42ffc335f5 GIT binary patch literal 6505 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/controllers/__pycache__/media_controller.cpython-312.pyc b/custom_addons/encoach_ai/controllers/__pycache__/media_controller.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b7a5d79dcce0076c6116b36acf4d02dd1f8b542 GIT binary patch literal 11891 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/controllers/media_controller.py b/custom_addons/encoach_ai/controllers/media_controller.py index df152ac9..e470cb23 100644 --- a/custom_addons/encoach_ai/controllers/media_controller.py +++ b/custom_addons/encoach_ai/controllers/media_controller.py @@ -125,54 +125,6 @@ class MediaController(http.Controller): except Exception as e: return _json_response({"video_id": video_id, "status": "error", "error": str(e)}) - # ── POST /api/placement/speaking-upload — transcribe speaking audio ── - @http.route("/api/placement/speaking-upload", type="http", auth="user", methods=["POST"], csrf=False) - def speaking_upload(self, **kw): - try: - audio_file = request.httprequest.files.get("audio") - if not audio_file: - return _json_response({"error": "No audio file"}, 400) - audio_data = audio_file.read() - from odoo.addons.encoach_ai.services.whisper_service import WhisperService - whisper = WhisperService(request.env) - transcript = whisper.transcribe(audio_data, use_api=True) - - from odoo.addons.encoach_ai.services.openai_service import OpenAIService - ai = OpenAIService(request.env) - grade = ai.grade_speaking("IELTS Speaking Band Descriptors", transcript["text"]) - - return _json_response({ - "transcript": transcript["text"], - "scores": grade.get("scores", {}), - "overall_band": grade.get("overall_band", 0), - "feedback": grade.get("feedback", ""), - "status": "completed", - }) - except Exception as e: - _logger.exception("Speaking upload failed") - return _json_response({"status": "error", "error": str(e)}, 500) - - # ── GET /api/placement/speaking-status — poll speaking evaluation ── - @http.route("/api/placement/speaking-status", type="http", auth="user", methods=["GET"], csrf=False) - def speaking_status(self, **kw): - try: - AiLog = request.env.get("encoach.ai.log") - if AiLog: - log = AiLog.sudo().search([ - ("action", "=", "grade_speaking"), - ("create_uid", "=", request.env.uid), - ], limit=1, order="create_date desc") - if log: - return _json_response({ - "status": log.status or "completed", - "log_id": log.id, - "latency_ms": log.latency_ms, - "created_at": log.create_date.isoformat() if log.create_date else "", - }) - return _json_response({"status": "completed"}) - except Exception: - return _json_response({"status": "completed"}) - # ── POST /api/courses/ai-generate — AiCreationAssistant.tsx ── @http.route("/api/courses/ai-generate", type="http", auth="user", methods=["POST"], csrf=False) def ai_generate_course(self, **kw): diff --git a/custom_addons/encoach_ai/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_ai/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4664ced071288e7114033e195e8ad22ea02297fe GIT binary patch literal 260 zcmXwzJx&8L5QS%UBmSavP$1<3+c1yYfof5#h!#Sa2CV`R)U6# z4k;ZKvnagcoA*Xfnt7c}PC)c_)_aoqIfQ>zd$XI0c?Js>TL`#B9DF6dT2=^M-Hg6a zDh>8y?NxTA__)dv41p2tW69mtD%#>ENPX2W@GS_|ch?XP2{U zV$1x8t2sSr^W>r>v(1Hr($;d!SELNM+;eQTX&O=<=pUL S9t*x}M0|(y4>(PSl79h~^hD$U literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/models/__pycache__/ai_log.cpython-312.pyc b/custom_addons/encoach_ai/models/__pycache__/ai_log.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b634c653111fb4fc8752b775127dbc3c81df8f1 GIT binary patch literal 1847 zcma)7&rcgi6rQzr*Nfv_eiPCJFlki9Qfn6~MQTM+5duU5ZX{?TEv;6|&Hzi+yJmJx zVyg#N;y_Np;$V8J)Dso?Bideah$%hj)g*%F$6jWCBqH<&cg`NE2~NfV)DcEla8N_&(<9>ZobICDXeaxmR!BB%+>cw z#^th>X=kY^*YZqjZDMxLTdim$^0KC#b-?eQm`yJbx@lV^J!v{lnv*&#O3Z*57)%-y z-^wJoq`V?=O`FM|z#h zFeA_&m?`B4kr7w|lNGb%1erLm;Fm0m_&!T4L;zwEq12;Hn&L0c3G4##N&!nOMu7G~ zrb-(nezxQj>RU|_hX=ppRD&MNtVS1?SB zJ=f1Q57#j5T=cuonYIDPoGq4_GUk|tWo(XDdRrBdJqr&*4}JKx>ngJzy;_BW>E5(xJVubObt)oD1ac$Rl<~c(=CsBE@26N&W4SdYP-c!U=%6Y zw8;aefh=15ZxOu?8=+}#_+=a#xY3dSJD4rhNL{N=HM(zB=Njrzb^14LaC_ysHh8EF z{uNW&lE+=BtFNJTonB70%hj3VH;{H^`|jhVM@xIbk$R&#-RQiw(^tP*ySh72{kYL{ zeP_C!ujThgj(Xmy&Nuqs+LOQ5zS8zLj`~M_5_=on!#lU?P{=*j{<;J@WSMAHFwt zq|H}n8a+cT-+_F$zEoS<{rt;(w0*wwd`4m-mt=Ufl+S=k^Zef?8q5a}xEL15FH+4o i{SZEI!TbECKaLB6@GBZRm4}2kVJ~B~vA+?(aOJ-}WX=u% literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/models/__pycache__/ai_settings.cpython-312.pyc b/custom_addons/encoach_ai/models/__pycache__/ai_settings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..409a5e145ce883117221907808da7124a1877073 GIT binary patch literal 2536 zcmZ`*&rcgi6drr+#lL?*Y%qr4Bo5$Et}r>y4ELr=L`3ccjiH@g_Gn|KfFdGo&ay*J-`v+|$ucm%=o zSB5EjVTAtSM)wJxEk4|X#XiCa`&88Q)qG8V&EFJif)Dx81BCsr5Eh8=EYuC`{k{?0 zbuHKql!EWMQ4*LSw-hFBC`82u6Pr3Fs!{I+Atas|AMW^hW`b%yjB0-Ds|kKY0?(Y9 zy#WZSz{1S3J11gDZNwz>}QZOcovsD$V~fMX^y3r zw7M?WHy4-Jh-oTX!>~puG3M*KwxKlUjqYaRaf@h+%Z0@!%Y_xvwsORclVoLH2bZi! zFtXBf(k}U#XqXhJSjuIQS~8WJ#3ZyNl>8sXM$0VU)GhJBlPdha_FGYRr`%LD#frMy zg;g+K`#;9H@5}jHWpj(J>sFk5!7NlAGj>+iD!(C=54|<|X=Tp+DG8KcKQ@HPhPShWfus&6ZpP@3X0d)sE3hSWOqT1n`5jZppkK;xb|U^p!Bou4MM^bm%$ zsy`=MpGHK50X3cN?5g~-@PKH9$|k4^;=-^J<30a+SXmEuQ+^4$I!Wg$t@VBRH(MI=5ZTPk12Bi0usy%YfPIRaZ_n(!cGd z<#l*F#D-zxe~obXd!nRX1XHzgTkT{9}Z{#2aWjS6Jx ze$(b#Z8`*boEPtcvF$_X6|$4XogX?P$`ud9qv&DOPEOgmo2Nk`Cmshfoe&zG+1+@T zoj%D!n#fm(usQ%ekGi@U$}K~b z?p*|p?bHQ3R|eOx`1_CaTDK98N+JvJ&Qg9Mo!deA-z=7>Qdu(;qM57C$KGjOiDR7D yIgSZ^18s)uc9+hB3Ef1-6udfu&*%Fa6;Dv{R9x}-!~^l&SovhE{4e5`L+~G3i@*5* literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_ai/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..463c1c4cccade01784c4fa652a3f6eeb26c94f1c GIT binary patch literal 570 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/services/__pycache__/openai_service.cpython-312.pyc b/custom_addons/encoach_ai/services/__pycache__/openai_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d060a965c3606469004f273ff6c043db59384d1a GIT binary patch literal 20224 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 F|34PMJ6iw% literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/services/__pycache__/polly_service.cpython-312.pyc b/custom_addons/encoach_ai/services/__pycache__/polly_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27f98d1fb6f19f97518e822a7be363f1b6da300f GIT binary patch literal 4996 zcmb_gU2GKB6~6PgKeMy8*WSgf9h))Wn2rAuASonPlf^c~G&qiJNN|--hn>M5XLrWE zGmG(R9U;VnX;KkOm7F%HHBzMzfmB|q(wB-TeLzYo?RF!1nNTThUfMSYsG8E3o_qJt zIF6c1z0%&FbM8I&+&kxd=iL1`7!(ndKSo^RlORH0kU^z*%ANZ^ht3Mp&=k@bjZHFB z3~kvdmPI-sOOh^3H33<#)CKqH!KkM{5 zRxmiJ*6|r5q4)irNE&sycxu5F4q-zzW31~rt*6wa?(($u9JN%_R9){e)p2I@ zdDk;)BrITi$J4g0CzGxa*9^yq@ec*v>^*WQLz?3gw22?5&B$n?q;jdQ+|2zKV7!8K z1UHAKSdE$DH1-0T;x!IxK?`ca1!l?vw?l4*+=_Tv&;l3Wq*@)^1vBMa;A8c!M9(-; zI#XtE?bMT#6Y^;b%hS54W7RRtX*p@wj&72kepXG%YFaa_zC`&(sd}W(!SB9CwaYSD zq)-N_vhao65EFc$VM9fFa1JuF%M+I%fgJ*wIXrf%_7cdD@s(=2WbvbVtWA z!R2)GjLX|;&2s(Ix>Mr0qEhR7l|<6eO$WXk4`1UnZh+lvat2v`sP`X-FKzcPfIw57 zNvT@@9JXflgk$f0a_=+!mS$PBdg@^RDK+tiZfgCBwCz|aMb$LRwEJ~4VX283MK$`% zHe>hC5sOkPCN#I;`V_@54M$Njk&R!XuR`8VRO*5194a<#TjJmL6qT%&=2!_psv6r&QkKD6_&Q9PavoI zk?nvZR90zB#U;9(|_kplemSgRcP0NuD({|KkQrG0ap8Khc)8@1CoH17+ z%XDHUS~JH!b>3FgL_)W1%8un7xsC%jy9=SiOP)LR(JL*VNs(f7*Po)JtN8uQmCXBZ zUU@V3%*gG%g|5-1qm(ngk#p=eE_97A9fh@Y_Y;N2S98*~{D#RnO*fOa9L5;hS8e2zgUfm#jr{Ai}GY~+2a(U-KQG5Ht}LcC?5c0Fps z0jqb#qzVx*v7n@E*8@)Hq-{5-6Z=t8;7#hZ9^+{g!6A?U#)EZO;QEKpCiFQXAy%>@ z+)LQrvNYUJMgo-UF>Qp2SeFTR+IbmpbU*QD;e z)LoEz*QEVtws(@cyz0L{5;W!)D2S--~9lqaxh zIt;5aMW-5}zMU3XUk2iwCS+irik&Y8AaasVx2b5JY@l*Vh>#*^cR0Zw*@J z867(`IhP$vE+^+SCzVevIJ(^@iWG#Q8rPjPHtlDt1j5jagd@)z&WzkeS9QsI=(<>s z+y$`+{M=ETg*m+o#?;D5CouyVW&#pSyQ?a!G4!6EobcrCcn%hc)*Q=@miCy0}b zXs&0tZxFW5!~xNuUU%Ot20<6VL3>Pj0m z#0Ow+SFGuV_XA-x7QjyshX2INBZI@rvG^G7Bx9ZgJvUU_Ln&RJ%Yz1*%NeGFNsxBA zq;BH9v}Zdw7A%E8p1g@Ux_Pj#LArdK@a3b)F>B>^Xdx&ui(1vDg${YwFH7bwk)JwmnhY z-d1dGE4Fp62T-`@KJtX?mWE)XNc7#de7I{Z+>;OY6vBNVXj}C1{$C#a*}?aoyV{s< z?Y`>dTlN*U?O!@V(0AnG$UDi^BcDn=pGVt^^6u5w^YXr8wEb>-$Lj9)j4%B{xNaQ@ z!Md*=K$Ha3WkHq7x?c@m5C1y)LG)Vd4V;f1yg8ZQ6EEyObnD0`6S-F=KYr~~=|oWq z{d--2MGtM_z#m59PY!y}M;`xB6ZcX5^FwvqAL<0?S1}eQA(9VMjQs>U{}p2)tKRBy zmSwJ25n_?ca$BLP#!jOO&J3YTd;-P^_Vt|zL4FPqnPLuKLPHn}rSX=MJT*z0_cFiC zzP+0VS&M*736`O~c@*ewt z>Jh{R@Hp9&IkP#Q2goD3ymC`AxPe0+&2|Q=bLjI>WP`yM>mzIRo%#CC8wYarorU^= zC4Sw5wzaIhw*1<=GgsM9Bi;7}u0i}ur28FaokQWsJCn=bS&grrzA|z%bo0RPT61Hs ztc@Mdj~&mQn90p13uCE*WELacUy^0(i1Um8x`&`k75{Blyn~15vDZ%1=fWu5Cdmb2 ze)4c7_oFEAq*hXvmQIqsq$od1tI0CQt0R}f2* z$a(<21T>IeS<{e&Oyi?uME(SL2?&s8{g84=W(6Zxpw9u^L5P8o6fuR;lVAiWR3WU9 z9?54*8NF|ybl~seS)h@u#kQe>1d3tqpsp`a-DfE9x!AhYwI;Ua#nyLUEQp=wyz4y2 zG=9dntcxhxzB-=|_7}IyS7Z6${#v`^YI8pL6o5sLJ?H;t!z&CU-b1ARYP}ixnjlwW e8jHcu`NL#0fC3W4f5FEA50E!5av%B`sQ&|xHn{!( literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai/services/__pycache__/whisper_service.cpython-312.pyc b/custom_addons/encoach_ai/services/__pycache__/whisper_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..31a17369047cc6a93f80adcdf0e2b7f0d09003f9 GIT binary patch literal 5667 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai_course/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_ai_course/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..065e24cf2bc9e878ec88afea639616bb8d8d1e7c GIT binary patch literal 244 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 F{})gr@_7IN literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai_course/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_ai_course/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eab880a68ddbc0dc5318b2cdde3669aeb0e51a55 GIT binary patch literal 294 zcmZ8cJxc>Y5S_UT_(cjU8^Oxr8dp;Yf>>JG*`!&P+aX!m-3hyU$W{IXOMipE#o8vI zjg_5{E>-3vHooG`oA+iI=50LQ2f_2xyStV8H8g*ywqkWG;sq>N^bl~0IOs}rHLVc( zx*2_=j5N4BG)~VbQZmJH)ShQz9*OD5m;5ifYw9JWS~k;2=oMDNuy*P`Q_8A0fuflQ zW7Q(@1GObj&L@|OE%Ps3T&YNpdK;>?%Y}nB)^f~>V#}tTYq{NWmollqmV8!PyXcD6 hXN!Kldo57~XAoNos;s>03!fD!(eggyTQ>p*} literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai_course/models/__pycache__/ai_generation_log.cpython-312.pyc b/custom_addons/encoach_ai_course/models/__pycache__/ai_generation_log.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0cc580c4be9acba804bd56274ac87ba10f93aeb1 GIT binary patch literal 1611 zcmah}&2Jk;6rWvtH|vkJW2cD%CD=q&z_jv04oFC$QradZB&nbcJy?}i+npC@!+O`9 zT_@Ow%1Ak+;?P7K(n^R%oTw5Bj{O_p(nywK%>^XHfty9cr6*=~y>Si&<}mX|iwe`ob^<501-?Uuc-8)dWy;fsQ<4Z8{l41K^5W5_X5tc8ir5l9S+cwVJ2sH#?~vW>le;qLitQ3 zBSEzPV&q&iSIX0|ImdJjb8XhT4h|5*w_In*t+rl+&|WsIa`n_xwwWt8yHFf}iyWOG z;FTL55U-_p;1`{SZI=Y9xDIO)@PRcQ2ZW&TVZ9L&P#1U4+#Y-K(Tb@mw78A37Yb>eOS zrpjzz;#LCdVEWv8voDbhPg^9sS4fI&H%g;a(RIhDfv(e}uCw2$VRJdH>pZW%M+zX! zh`}?7Rp+0D#908UEE`U9+I4^?J->m$@pTK+#4X0N$x$?AGDbYm{bn6#dNr1nl%MP><*xF2Pl{cTdos$6o(#oC#@dTL z1*zlP^A8svEPlPr;$$bbHy+-9aDU(EWZ!9j+#R2KBtOYK&O9&AcE+zfkB@fqZ|zL& zX}j9~#b?P*{%U)%t4?g+K2|4=)QP{4T#$QdH2lUsK2hb&rS^O;gV>EAtslmIEIch7 zmu8MiGo9Q=EWP3LJMvy?H}#GB)dIN~6?dZ~(Kx4%@Sz+wgtW{jaY(?s+!~-SG3li; o6Smi7qA`^ZIgd}kUQ7^#Us2&i9u?kvboUh=ZX(iRpuXtr zzTf1=dH)d@0%7@>|h`f~%br@Z*KLrPH@F3Jsqd2^am4`uj z1hhvRcEufb?*&z32g*J;Bd&b2!+O`v&X3^H1?Xbmd5#;OtJeAkg>g`r0B+seHi!Er zZ`=P*Tf_a1wdPEcUm7(FmR498(Z`8lvs=U@RI_!ye z5ib%bC5xnB3v|YdXcD#?iUu*6*D8ih6OdD}n;D5-5;q}L##EcPxqMUHAdi=cDU7Ns zh=1wko&ee|iip++ZbGPJuy3kK2nKT!LZtxG(+)tpfjFJ%`(y2gcYb>77an+Y(hLd3)U7y&Skcw8wU5!kyQ|Vm+EAmx1RSDbTfEa zp1iA>*tNM1g{CxfZOAeSk2ZYPF%K|Xvnz}T$4#3Q2?d93o0Q5nDhHc#~05?Qr+dOLz5Y z;CsoI*Qhw9ok7^i{)S-#)nZqxqqWw->g4lS_vYAftotz5{Q}9ofs+VIwx332rK37} z5<^PY=GeoD2NT~-0so!%9`!#Rcs%gr>N9_5t?SC8z|-jC=o96czrEISd8>aXx1HM^ z_%(9Wa-%v?Q+hUUA1ghFO3w=vNClu+bN4PjRRZzB>exvfHTP~VKfM3o{;qbEc)$92 zEt%fx*hy`te(v}swU;{13?F8OkCLBNzo@nKZH*nb^&PhLL8X4DQYX}D@2XBgosP>} zw|DMr-}(NV>U2ZK?=4rpouD7pUwt|wbHA{divN?_Sn`zkDY^Ds6R5-f7@}99VYf}M k(@!B4r!Ny-f6^pL(jO>w8c0cfyZt{6{xJA2g3wv{AJfnAKmY&$ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ai_course/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_ai_course/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86fa689f4475cfb86f4c620e6f1079bf376a26bc GIT binary patch literal 316 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_api/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_api/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6056dc00a5737180df4ffca60d015cba86e7a87d GIT binary patch literal 261 zcmXv|J8A<{^v%O{A=kSl>Yz{YU-oSvt4jir#voF{e>jGgc>*@!2 zq{dzKqN2^JhSWUOXMm$Fwq8OF4UNue`(Fc09I>qIDc`wKiooMkO zyxquiDfAE%IjM{xABFXrly0QzTcOFPKwX!&O4<50NqN_g$BUICGj#SbT=L=kV!USh OEfMhxX5TOi6V88HFh*ej literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_api/controllers/__pycache__/auth.cpython-312.pyc b/custom_addons/encoach_api/controllers/__pycache__/auth.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c047dc667446e99713d37d344562880ad2e54fb GIT binary patch literal 6515 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_api/controllers/__pycache__/base.cpython-312.pyc b/custom_addons/encoach_api/controllers/__pycache__/base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b84fd07ee301aa4a5cee9f91bb608577c3c94fac GIT binary patch literal 7891 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_branding/controllers/__pycache__/branding.cpython-312.pyc b/custom_addons/encoach_branding/controllers/__pycache__/branding.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d40721c199aefa346525a8ac6d6e15851dcbc27 GIT binary patch literal 9983 zcmcIqTWlLwdY<8Bc$Gwnk|>#yLtQCau_)P=Y*~?IT`gxFZQ@JX$S_!%GnPp6qRfn} zh)X$X5TGg$U?p?`*+l@$+Xbw^c`)`#MIUM>#>R`jkfOU}X1zeRb%Ewhj=b2d_oe@t znKMJtLpf-%1MuAMm+$-k|M1_+%B%!@pZr%Y{O1;e_)iqUpHU9%{38U`2%4bDC^0Sh zVV39Tz&EkX`|}LP z`zXO4S>OXG8fF<%JWTq4dfLPdaK*#xU5lm})QUMh4sK`#oHz+7-991rr0 zP<|~K4bu<`@QJHTJcP%Be3Km6pn{8B3xjaE!0Td|fHi%p{y^DA0;c`SB~RxBl3DWl70bXwz~ zE7W$Tt&0v{rBFW}4<&-3*%3Avr^E4?(L|hQ6VWKcCVl?kT-eXV`7poee$ylh2`W_nyiOV1YatpETQc9l0K!6;FDC4pCa+aSTdvx z5lcaq9K>gZv-4;~;)ho8t~`!&uNs@-m18rejFB?jw(8SHno5yZ^l%1EUzl-!OVkXp zWJ*zE#3h;_mdq(rq(ZHOLn(8_fy1f~sa0wWhf0*J#`&rb^=s7_4nb-i4y!(-Y5>s( zB&P!yv(VPhD7^9{@#z%UNr13)+OGDF8MwP7UiZ09tAa)Rl2V;P@A?6AjKxhnL3OxyCxnC|>hk#cq zDyMm_1jA8={_Z)9+UH~qs4qPeza|*Cc{(9bm)XPuU^vBm5axJ}MK?#FI3~!3W(5ka zHxs8>v|-{XS+qUuYsm2+rwKU}ID%#TgAg;vhZAwZ6o@8fW?+66MoH6iJnOSUpG@?M zG+*7-1%Z;*7CIN#STMaM<4H4W(irBM7$=Z1fn+#@6CUMz5%XW*7?$%d!g|Dmv#}uU zpJNjdCd6}xx)1gF6LcaWIz9dVII|FtGyS1?j!(n_L7E2U0&EkvI&fJAKYvI;KhBR6 zyXF>!%9oZk*;x`eyIv}ct|IpuY`{mvw%Kjzep1u0c5(G$x~V5qb0}AHG*fdlThqTh zk*{&DU0S`g-k+^G2r*~<+TiNo&xW43+SA_t&BIyOP}(u{w6<~W>gv^W^T|x@aISVD zQ#+BZom@VZckN%hzIr`h)p&zjKb@}ZN;~}d+O};YQP;jh=s7kamktlr32(F-i`@;EMM1mk&B$EFIG7^ad)?4~8u#41ysH*6r$r%E}10n|?0EJ+R z2mqaR@zWGYBmz*#1D7ozrxFBEKu%PO(t>$Bhh1X>+Q8!ma@u=rCXt->8k-3Srcxa< z4$)@XB9RjY(})x2sXiVbNdRe?QwAWd{{Ygmq%0Aw6}RHHxblLvwy9(r0`fRVz=&$p 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_branding/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_branding/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67e50448e951f7ffa6410a56813c7fb29aaa0625 GIT binary patch literal 237 zcmX@j%ge<81T9amXNm*q#~=<2FhLog1%Qm{3@HpLj5!Rsj8Tk?43$ip%r6;%!kUb? zIFgDI^HMVN()~1fCF@;hcAW&M zR3CB(C$M^OP%1%BrGk6;6DswBi7T&Gks7I|_LPeDl2d1Pz1T@WZTB$y=J$T{=I#5k zfA)G^6n<8}{)N9|r>Nh^#(Zp5;b064MG8>BB2XDi%963BtQN{jU88{YF$Ef+WdWak z``KJJz)XaF>@?br`5bm+{$5lqL9bK7Fzsm5bjjdd*7u`E{|%dN9oj<}KDaUb63J=T_I z$9u@~{U=-gV{Q5B{0bb)^4HzibSx`SXDg_)dfxrU?JAUN{#Ql_Gr|i4@7e%OAh?aQ zPM%Z?IPsWDMHZVAA0OhZLVlfx2Q^bEG*r z%>jt(&xzpu9FHK-oRWwu5h`%W(KU2+=={WR!lF3?!^*rxMcn;6yS&6^sG9?{m1EHa)l zz@m_E)E~?{qN&Zs!P=n7ti7vNtZ!IpuIWvw&Pv$CYHw`&h~_qJV{L1VYf5$6HWRD8 z>$L4P)RasuX!zE5n@Z4A$cc)c)=XnLP0yhf< z)~IgHjSul6i`!3tT9dH>P);L0tMK@=D~-!o%CKo!P6RX;6y+R(tRzB2QiV>CkD`fn z6e4>Pd2~_-XC+C{XyOx!5WrD&2t^5p1Qf-{LV}0lc)@*0%TSn;Ndqvi=aVxsL~?Qw z8yC6x3M#d@B+AL^AYsi}lQe$4lIDIO zyQsMpiRH393;49M6n$%44b&;ghsi(UB~PhN&#HgLUv@@b2E)bPLa!Q$ZM3hqS0a6- zNS_*wZ;Y*vRiXo>=ztpQsKk<`SW=C5RpRGL@pCHEU15ex%b2c84)VQ7_vaUzsH=}9r`Iz4ov5-tIhGXtHsH} zpE{tMY%U`VBmz?jn?{p{&?9JM$##?cPcs5EM51&UwAapyM$X632v(4GlgV&=)nKt$ Wex>4n*}E++91@`*{7qp|Klu;*_geG- literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_core/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..35acb5d4b0ce2da761b79e75e31dc5acc63191e1 GIT binary patch literal 224 zcmX@j%ge<81T9amXNm&p#~=<2FhLog1%Qm{3@HpLj5!Rsj8Tk?43$ip%r6;%!kUb? z*mCnzQge#^G?{KO6fpzERx*4B>HHO|A6lGRRIFc_n46lHn30>9qF+#ypOuk zWTu~=lAjMI3@!EZQp@9^lKRP|#U=T<@rfxZ`FX|qsd>ryiOCu9$@xX8`tk9Zd6^~g n@p=W7zc_4w7MJFv+7)pCZ38)`7{vI%%*e=ik3pn}4afliFYr8H literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/migrations/19.0.1.1/pre-migrate.py b/custom_addons/encoach_core/migrations/19.0.1.1/pre-migrate.py new file mode 100644 index 00000000..17156344 --- /dev/null +++ b/custom_addons/encoach_core/migrations/19.0.1.1/pre-migrate.py @@ -0,0 +1,13 @@ +"""Placeholder migration script for EnCoach Core v19.0.1.1. + +Add actual migration logic here when schema changes are introduced. +""" +import logging + +_logger = logging.getLogger(__name__) + + +def migrate(cr, version): + if not version: + return + _logger.info('EnCoach Core: pre-migrate from %s', version) diff --git a/custom_addons/encoach_core/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9fce35a028ea0064494039d832d22f5f0b6765dd GIT binary patch literal 478 zcmXw#Jxc>I7{`-)Z?P7ngNR++x)|*s2;xU@bIB5pOR$k#awONv?S2P8gP%p5g~GXr zgPYK;lTTus;g{d@&&xydHX02PjOXtU`401!FZLta$%ccxAdWazsKyjy?-6)Jqu?=k zOyl4QctVrlDR@fL;2C&Ev*0;+PV?XectHz{y1{JtgQ3+7uMdQ-Oj#}1(g_Ro;l38S zm2C$}VvQ0o4;x`?>6|p$r>Z4TMW2ZtWPF`X6#rz;BE(?$Jq) UPJ49JqvOCykEWmK%#L8kAENnzIRF3v literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/code.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/code.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00b1001512c76eb4b261acda809018da47c2f13d GIT binary patch literal 3263 zcmZ`*O>7&-72Y5IEPq5&Kc*~Mv6$4UvW_E4su7^JET@qyS#GUE?I1Nkwa`Oh#{!Z91?ppq7U-cD(k38wilPE~@=dPYOHX}omt+;0 z9znBj-hA`k%$x7M;a|JD`~oy%yq^A*R}lV%gI04lg%_7Vs0c(LVpd4tSIUYxDIw+L zgq(9FT%sTea{`gq1>&Mo#Q_o&$b+Y;4B}?)0|(_R_x0NoNlSd(yWqv`-r)N7jWze<7;&^S}i? zWoW78X}H~DkUE3W6pjWi=+ihA`ypLQn-uHkLvfMx4mLE#o z2ZvfU;C?ChO}9kWkIO`M1U}C&k_>NCmBEtNwDJV}bMF;LK%GT_DwJ{WRYzb0xaJL9 zBeFjDqzb)`U!(H89g`L?qIhxF|1)kj}1F0^XF?B-2gY1d72I(iLG% z>clfP)>&`0d6)6D{QUo$!Mi%tTHITK{WJ8dwEcFdp6odI?U1CP?SNkSNzNFc4Zp<#uSpu{3UcHVK3CPxw5fxcXoUF!O`lmiR$2Y9*^Hyc^W!*NBr}4&H z)%VWTdZ((vsYW2QdH(bBcg_2^@7?}g^!LNR9o`+Esg2J(9iM$NJPXhVKdtpnR)dp> zocw(9?)3eO_bxt=zY0DKJ{dY~+nTENp05Va?;ROv^!4xdjnw)^p7yEF-EzdgFUUSW z>w#^3qdMZP+e}A>zmDmx`xP-04(16g#s=CpZyilj+kwL@3g`~{PIh&8q5+Ks^-$}C z24n{gv%${#OxGckFl?Q(={NK$0&I17_(6+-J=8#ph2>Bq;uk*qolt#TN)wyP+~br> z?oBbOSq9^NhtbGl?y?H2lzV}~9|3pSDKN+tpfS4&dNlx8-OMwZG<3=)VA3(^b4(^7 zxBN}3AhUOHwJ&WNiw4VS78X}vJbGa7;#%9f53M^&jDhn~*;&BegK_cL!FS|PDxnqg z7IY<{p#(R>8{xV#u-6lN1jAS9$St6W0l+G z+q?a0tzX?6JH0#h!IQBMwp_cBSS=FUjhw7SPSzu*{y_G?$U=Dm@i)siTPBYV-4ERh zJ?{@9(}PW>FQ`Ykl1%FGv?i0>pG?Bbn9rgdOeQ~tm!>)6wjrP-)J(DTD*lpi>WFK4 zSz}H>mCKr5n7|;Pfzz?G*s0h#A-w`mTgqN|4wT$GuUm8pids9WYzp>PE1jXyOQb_g~90o}UL2o9DmG%mOz zOsXCrrI|)#c*|1>m&4WA*yA(x$ZTo8(H+~0R))*N+sD4P>fMv2OO2j4x4vD8m*Y=+ zzE%2uBNE&4IAL!1-mZ>(ud005hzz}S%iW&R{JtVYj^DYyd28d=wpI_nQ@Yp)41nLM zjj8Q7>wy#Kvc3M_lFR4c_Y2*FFT1?<>WI)i1RDyJ1KTI+k&)8;o?H3FwVz*mE(P5F z7qZ|9@7vN~$n8`o`@E``VJdSM{`z59pX}>shU_v>Hf!V9C7iD=%Xy9_#f lvrYUZyf2HQ_;(@jPvJyOIPubRTJ*#DPnA#oM*z`Y|3Bq>(18E| literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/encoach_entity.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/encoach_entity.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a246b098da5cfbe85f3cc0268ffa459b80c6b267 GIT binary patch literal 3982 zcma)9T}&I<6~1GS|2-INFcUN__$13hSy;BlW3o-c9ZwAF|IkiT&u^lz$En$7IIxd@#NBqEVXqYRT|GM1zzV@+BaWI>mZ zXnBN0tHjJXD--vBpIOWOq-~Ln+x|n9xRuy5swky3VxN|!w5SoQFfXU}Cn4l8l{bEv zzkwu_WJHv-h)mKdT9T}2onewT3zF<}b+yyVeUTN}=eB2-vX*rINS@2!HGa6>3=-|% zFtDbhx~9kAwtUD1mh%~7?#vyzv+KFL%Bnk(<$3O{vV2FfxEfadk*vBJR>P4jU(LDv zN3oun*G>iu#>o$@P-Qe3jQ?k+pusxC@?yQ%Fk=z@aQ4b;HXGcJKim^6zi+LO!RkAN z6%ZT6CNU^B!%a>9PKFKkPY+?Y05=58iWj#V%=3pZTVelj^^_6dMdxVP9B5*j*j{CI z0qfY@BHWmgQias)n4-)2;!>SdR(m8z4JQ57z(z}Bpg)m6d{g9Oc&5tOWu=7srrtS$)YCEqmzhz^?oZiOQ) zxv-@5WHq=qX*LbamkrEQl*dwrIbeJMWgTL5{4ZTivm2UFq;v?1ekkHO6gkf$Grmy zRa8|&oEc0g(wDqBm`K3|)eJ9)qN-?#is8XCr9`=KRI#${d*&B$7i_uIIaV7KJ%?EO zIMB3C5IOWZ(EI~pT#4n8f3`>Sfp6QsZhO_!fF+&q>u0$v0UPOBJG z`w*WdrBp@SN2yIn{T;~OGZ?anXp%z|_J2u}AfKj5kQa?4NIbB-tng4TAR9H56;aYs zSf1BqRUw{PLF1=|1sS#>jga~vziKqcNrEQvH1dqBNbEvNr^SF4{m3{kE&1@m&K==84oR(u6#sAOrVcNe|&Yq5nBQ9 z&|Z7}Yoi-i)~}Ropq1>13z)it>dvbE$Lo22$we_YV1F9jYB_DS;b+d0T+`SX--VLAG z!lh;kw;(Q>Z`|uVx6^rUw{z%4Zz)9KR$%|7FVBAK{o4B~e7Y2-U>o9&J&L%{X6$L=NutzAb=2T;<5OVX$@mH41%Jr3&FnJ^D_4`|ch35Wkwy_wBZ3dr)pM?zr-r|l4C^})9eYg_X++X69G*S7r2)!Qq#;mBM(H(vBbmKXMXksV(o z@7X>*{x{F|)a~sVrQlQH{Jsvj&%>36o4?t*|MFbHcNMUP$XaltW4&Yhl6P)&^0Fi52?YXbN~PV literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/encoach_invite_code.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/encoach_invite_code.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c91ca5bdd64b7c590d484572d0f4d93894c0d42b GIT binary patch literal 2856 zcmZ`*O>7&-6`tYm@=r^Nj%>#cL>WqAB93Ugu?)k8(uSfF)v}UCQh>0D7i-Q)T4uRR z&o1SVNfQDUP{{~D8AvPV6g8LBu!<&VfcVgR4!MXH0TGiNg7nb(7E~>e`qVc|E=9Y_ z0GxUA-kaGs-@NY)zmCPi2->0gS6a=F(BH+xZ7_G*?o}Ap5kUm&DAyiw4#V7|dy3wi zx9H3HivFA*BN8OuWt zw!4SgFYHy1yYV0JI>zXOBR*6?fA(I-xAAn!!-E#hGin1)`9)L9Q$Wr$dXi&>OR8R4 zRIh?fpp;D39+>Gli!v)+QH#`27mF%MmzY_gdD}XD^7L5RB&O+fr_QAfdR^%l)A_Px zn?*$>#5AllHS(sKUsUoYqv`e~b#`^+4b?8;~U3!63;XSGXJ#%kiQ)|hEskXuxzFo z3tU#MyrwDTQi-y>YEd2_+JXjv_zI?Ga6eOx1qwg~bZRWvi>yz4M&w8G=S+ry_dOgL zI|xdV1=dOEAdqk6$9Ci=8}gHzfxpCV#~SjP+DolStbTU&?DjzBi@CdFe|@t#klBu8 zwtSggSc6hQ=VI(Kp@z+aGi^cWYzoLx#)GqM0d#(q6h)lB5ChCZfNRMVK=Dw<6+tf- zRm+AWx~gjYvZF}$I{8&V*@n%;AT}d(iRvam!$T9Um=`g+&E>-G5~SfeqDYWB=OH-f zC7ztmgQ&j{b)EM{;w8RiwCTUoVVa;hcRR_k65H%^sgsj`(o62~iaTD%_V#ckm*cqs$Kxqizc&(Z&prph>#@R# zJ*z8`IO*?3evk|-quilNB6WcGXWOKjboi42`cxAgo{hFSH7Yn&O=OLXAYZcW2zO8D z>_eqS+=o*Y1$0moyT!#l!wh1AX({X^`fbd87S-o1;g@s>@j$wutHrBC9j`wAe_@Tf zwj^}{#ri&#N^76vBHTaC_5PyT8ydt6|Y zsvhZpBWB4W)UM=Jnk*aIwK5%j2rGe;gVpySh=N?`q6Lahb8*AMF243ivv382#pO|t z6|~}wdZfMe21MOnBRyh*DLVnH_R-tU6D|DrV`D)SvPYU5_gfIN_+G^W@6yHDl*Gf- zu*!@orUAuL&D+`%<zcWEiA&BPJ8Gy#>#){2yS4f8rn zfvzWaxTIOilB#QDzua+cf-xhWlP$%*kulxi$RU-CsB3li(&lv9eTuZ}q(mwJ9Hm zhcGd`HYVQaKMgk%Cu&oz{^Z)=`q0gx?fzr6U$$aLR$i-LS-r9`(Tt^P7r#r4tc~p? zMjDBcjVoJcUfoX2)TVZQlK+5nbIuu3_`b;hRG5jBcL>jY;-85Fi*rFt{3~_J7t4ag z{g>gU^fnBagh^B)x0bbUf1JGxIzewM4c!l3jPW<9?;8~R2O4Rhk==j?PvC!rrGuU= Xl=%1HL44p=;N$2=(f=S2oelp78dRoq literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/encoach_permission.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/encoach_permission.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a70503b64584cddd461973e5d815b643710b430 GIT binary patch literal 1537 zcma)6&2Jk;6rcUz;gEy(546K~eut|=ffhd1wg-~8q``%|Hy zBUlRuKf1bv&~MyGmoiaC?|?Ey7-6A}Ji!z^(G)$&lmsNA%Lt2m2unn0X=!1$A3;yP zOr_%;@CEe zSl>hDY%f>MvolTK32bNkDxsbmhHl{ZOJwY-ccy$ze~qUZQ+cNyJ0e>F?X4INpn0t- zFpZL(u1g8-e|(t+-Hz*T8Ce#oZ`BR5YkMn3Hzah$Ab#XVP;SGAw|oywXw?Rb1_2~> z?B3W%NhhEY^q03uyVK8aZmfT_*?g6Mwc0%T)0Q$g|l}Gw+jyzYWGTiKUe47RS=Em~L4xYq!nyyk+fl?e-+1Bq`vWMq0H3iV3Bh0Zd-owrPeh zldqB8C_|ZYsxf^Hz=^2s`VsWvcV~^MN%@2S0nry=qh&5mrGj@4JrH{+&KrYfTwWer zi3^K^_a5iwZ>}C(+P`#HewaHycsG9DE-l`AWmr3`ee>GjgShz8%`Xpb?B9qB_7h2* zRR`~%XlU;It<^{6rQ`C_-Oqo1lkg!nfJZXF_2dZ2VJZI^Gvz~= zzdat*07o|bQ|+xWj&IYKA;5_hRzRFcf*|~gmX6WV6LntDzg6$#Z|DC+peDtC0SaYs A_W%F@ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/encoach_role.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/encoach_role.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4a5ffe66e79a28e98876c931406c5e86328603f0 GIT binary patch literal 1796 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 D{oZuH literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/entity_level_mapping.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/entity_level_mapping.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..171e3861f601fb64c15f2ba8ef42733cdb7769c5 GIT binary patch literal 1145 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 RG2z8?jj8(78$hOR=HI6$CXfIC literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/permission.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/permission.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04faf1e6ead48a60f3734c651594cf3cda4f827d GIT binary patch literal 1260 zcmZ`%K~LO96rS5utT1iaPcZLmMfQk;~Uiq8}h2lV;fjP+2e@a@8J*F+R=_9`S`ZTY%EC;CSNF~Bt@Wqdt9N~9 zoV9;@P*jzXYNN&D>T_Ccg~48nF8De9l&@4!s?dwUbkTRHHk?f%2=&{7Wj=3Wo=P`} z_JtV=L-aG6zrq|QgWwl189%AtAgiz?kfjPGAVQ7XO)9iFY6ia0TAVTt8H0wr#i$#F zl$GIrp~_#eQE)9RR8H$VT#~N-vtw_|8oTW^Xz1-WJYqLlRHJ^(m+mbs+YyPP)GR)* zL;BLqleP~HiW;s*NEC8A*TeNAM(u1C?SVE6&9)eeBe#ztfgkVB{!iA0|3Iz*L4F@h z2PL|BGUl;>ArK^#`z&b2Fk?)rBh-~$kFjxZ)82_voxbq= zwi^&8CqNi0@cWo~K^Q~1?6I3o468u;SHvb|>4Y>=*VM?1`L|#WP-0d)t4U?Pvw2>g ze!YD3@bKY@`pe_9@?z(4VqSl}cC>N0@%}MhGqOkJds~(!RHiP4 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/role.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/role.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b8d51fd2bf889904594ce38bc51b65af7bcb323 GIT binary patch literal 1609 zcmaJ>&u<$=6rNe{+UvDrI{}A;Bu$V=gC#3YA{2=h8kHtN2{htIL8>LRYAW8b^t@b^Gs;f_WF!_Yx(M5pg;y1;UP3S*LQ-Cq09Fd| zvjKsQLI?6b4D@`&XQjHZ6cj??gGeW>sLy=53sXhW18tv|LyUaP=M4nttVFSccxT_9 z|H-bW!%CpU7RV>7$xMpH797(x%=Ncj8*j#O049l#7Mv@>H70!5GLWeRZ&WOT(PpAe z#7@~NS6Rd~sA(Xakw}Cm$5hwh^~Ghp+1F;4FezG;TCT%lZ+3LbmkrZ0v7EI!_{eNk)IYIUT3qMJpIkJ+El@b?^(g@Cw`M5(t?IQ*{=}{FSsdux+NF8^ zBVPS?{5;r(rnCl3>HQ%9K8Cko!EfomGby~2>h7sacSd9$%_BkA?t-5y?{Gi#IX8I^ zuVfS^S%@jNaRb{-4Q^s-p2bcpO*dzWHDb5*{UW2_eqlq(UpfXyA}YJ`gLz$csFr3aXgSY8pwFrspIV2 zH`%#whnA1Bb9)>2roWzjF#GA{-Nnxq53_SeL(AUa$nNOf(Vt`Cl=cLKquTGks9^YY zNX0jBU+cYmLAyVk;BtjOC{@=*Rdt*kZ;YNh1Nvu+tzX~F{ zlF3)r4MNgFRj(RObw=D(zkpF67P*Z)BXHzZmzT$I$e{1F@tR>)`K6H&j=uyaTmmvI zglKGEh#lyMTxS@NeDvt W0~q}^+y}Lt^Nnmh`y1e@ANdyoTz*3U literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_core/models/__pycache__/user_entity_rel.cpython-312.pyc b/custom_addons/encoach_core/models/__pycache__/user_entity_rel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38f20051f344f520abe977fb2cab894353cdcd11 GIT binary patch literal 1067 zcmZ`&L1@%K6rE%@+3a?ATc}!D(FRd5R5xvvLZKA2E~VfWl=hNKjF~B$Z8Ec+B+BNr zhaU8#o?1_yr9Jc{9z6V!@L)p?dM;OtQNzLI?8m{-5{r-~TiDQYsYyTV$r| zTonQM!JWa9`rvqxfgJz=6kOm5hTw^YC;$;G11N3-m_b5Q9weQ-_cAFqvhA!U{p5}& z#b~t=_=>nP7~BR@}45)5MmCOfxQ+COhWP<+x~?TcPFlccg^E zf)M#Oby|T#FwHVGu~N5idzMv*bA3T^ekdr;@fMge$}d%1SR&XDsO8`w9yb$upBiFk zD@5~0=B z_%z=w*E`F-vB}r+&gh%buj=&2yPvi0*ji_$HzeYNs9V0@Sw5;v?cVrSnL4aY^^|Kp zW&T*oT#^s76O>=bq~xk5#aZ4>GM{vyQl0;4sjTyyn6M`pij{@*cou1exdMCqi_HAW Z2!ik(O#YTf1bKJv-NM_2KY+m`^B?hFBD(+p literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_course_gen/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_course_gen/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..072db1d1b06161198b14c95f082b7807517cd3f4 GIT binary patch literal 265 zcmXwzJxT;Y5QVE|7XOybOaw15iKQC|f_MZolTDhYyKqOkyO!=5WFn7X=ovhVvB`oa zMrOih8(Aak3toLiJ*f9Kn;n7b`RTnSonPbfuWARIQ-v4s;4whN1>(q+aav8ux!gAO8gi|XJW+dvjXG={-4(skU?V5HjMmdC%LBWv%+KeS zBwpmtF0Lr?quCwF^`(<&toM=%adKka(m3gJVRO%kjA>Kb8FRK8wg=Z*sSkXU5B29* TvrN@~YDD~i<4-ur`?~)Em8D1P literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_course_gen/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_course_gen/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8aac14f96b7a102312ad9e985a3dc3ff3bf2c381 GIT binary patch literal 242 zcmXv|I|>3Z5Y6nuBEo`&9%37#7J?ui!Oq4ege2(7CL_r%vXw`$^bDTG+GYzID?7o? z%EZqrX5M?l%$swXwu#4Kf605k--7rf`jKbHlOvHtLP0bv0Z1KX@g2OKL6ZoqtW)zW zYKV=!cOuWQ`9ivI$~szetqfmlF6q|dMv2mm2BR@WiTEkQ2{mfRenToMSE6QIN;Hlt zBan+V`=+p!GE|@`Efz&M&RA~plCl1_ezm3=WmTw|ZTbB0o(tp=1HhGZZQ{in2^K?$ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_course_gen/controllers/__pycache__/course.cpython-312.pyc b/custom_addons/encoach_course_gen/controllers/__pycache__/course.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2baf7ba51045286d1e957e5d3b65cea1d4ddb17 GIT binary patch literal 29739 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 O!+8&9pKxmT$^8R}TVw_R literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_course_gen/models/__pycache__/course_extension.cpython-312.pyc b/custom_addons/encoach_course_gen/models/__pycache__/course_extension.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..286ebcd9202d42b64012cd440b2398bd76cad802 GIT binary patch literal 1239 zcmaJ>y>AmS6!#^U>m_aaA-+q)bR`sQdwp>?}nTQF#H0iLIhVLY=VhF8vt5gYWmA-}C#u58uaZHUrdp@$`$g zngHO37CI{xgRRR7v;hX#@IlpZjcUS87$5xoa z8<|449Jp1x64V(dlaB?V+zV(k9n^}YP**U+Dk54(zO-(JU!}28T?DXd}I z+lpODsH(|c8@~9# zT|Y9rIJ2?e*c`JqZP1_FPMd>++9LxF4Yf|U&n%yLSzNrnacsEtsQqO5$>(DuYv$pN z{-KuD?py9#%b$IJalQZQvuSp+Lu#gwlBQ0Z>EA=tvD8gn?TGjZtqrYDDYRo>ikg0z jjVMt+bADWHn@PhkzJZ}_YrvQ?R;<@OuX=t1jYHqRQ20wR literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_course_gen/models/__pycache__/course_module.cpython-312.pyc b/custom_addons/encoach_course_gen/models/__pycache__/course_module.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9af5bd4dd8a21fb20b419840b4d58a6f88866f16 GIT binary patch literal 1995 zcmaJ?O>7fK6rSCz*LEDoCJqjSrZGtr)ltC2he(JDDKVr4!jDQCsXnlp>`an{^{$y+ zr;SmOD{+7mjyNQoK%A(OLysIeBK49;mSWANm8u@NSwJtG`et{XrX|fBcHaBun|bej z^F01F9`8gj9{jm$+z27`hj7{hd~duz57Rm#h)59!hh z_f4A}zEf0Im2Bv(aI!L2OE#gV!_`HDn#9rfZ9sbgTapM!QBfkOC=;pJLFA$$BO1Eh zwSR+elMbS6g*Ij1D~3H@@&KMn6cXNw>?IcUn7yAemk^1*kTxL;F^Vydcg*+pe@W+7 zY>yT9SfA}*_wCI9Dkctz*Y!doaX77AMbhIA9dcTa$2h1?iF9uz_D)J25;X}?kAQkT zdz$om?6FVdlGMIh)BhX0_g}I5Jl>fDPCH7{TYY;u9$!6{J1@JhhDWw z#iZ4v)CW)N9(o%3N5FBPl<`?_-#~~tXfMSvs+30Rz=99Vg<@&a1`Y}#900BqXBbifK8rUO>U z&txSYCUg;3OgGyByW-e1HAWpMK&MVMK4qGjZ`v-bCmh{|=)7I}$!qr)C1|*7C zuwmi_lk(_P+XOsjSQ-Raf>fMp?2?ta5jbLxZkNhJF~XyTwh4IHxnq>efQE1S1{)B8 zWp*4UPwcnim8quxbCnL&UBkAj$u{2Bh)4gCN8+mEGQ(QBmhI;eO|x)`Y8vmJ78A&&wep^nasvIxNxh|iV6GG<&6JRZ4)wK@4S`N^D3Y}@-xoXuJEdvW7pF{f7?*Dh(8 z5ZiKc!L?|CKu~24G>6wa7a;x(oG!02@&0=sA+#gG%lQB`yM}8Qo2jAN?C-Jk!^y|z z9-Z4Lyc}u7ahtTj)^5GL*f^T6U2FCY)mPT>t}0-R&RS=^uNClyS8cLCL`n zQRPHtTj^_cqQ2q!;<~wJKCx=on*-w;^Ut)W+V-gnZ>o)f;_}q2#gWBOl^w_ZPL9RyRt1{&3~-{YUqoFEkR_+Skn^nRgt;w})h$}*JCjJurUJSv*MNMC~DS>+I0$3j- qU;4V9XEWf6KOsl_vRfUJB>jd4Kd2|AS!rYR+4$4(zmTxKy?+DVoEo_R literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_course_gen/models/__pycache__/course_section.cpython-312.pyc b/custom_addons/encoach_course_gen/models/__pycache__/course_section.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2356227f95a567bd6c78fb78901157d516974e9 GIT binary patch literal 1268 zcmZuxJ4_To7@pnR*By6ohl+_Ippj-1!vZlxBe6k5jY=Xu;x?OMXE+x2an9U9j)I&C z1y*1MRvIe}6qc427A7{Dka(F!qp_ePq79WZyUR(`DdxWaoA00hb+hjag&g2(`THmD ztqj07VH_+q1$!4cSO*9o$p?XCOMz_55|F_-K=Lv`87$3e2Tp%}H!}&gmAYc8JHjw! zrUengK4sdphkZodKY9RK0l#u~9bjNf2-q@`>wC0{LoY0|?DYf4 zd7WU01gqalfZ!I0SB<%Q3E-STD;UlR(wIz$)cpE%#g?Pb94=uMwt5M)UgrbmIX@{INsWJ{N9*Vy> zD`nDN^;hadJlc2@)zKQ?mO(S$*BEOaIo-J4EF5oK{?gX9GQ4`>(S?oC7k%4pR^w8$ z*t@2!cRcQR*7gd$xxZbUXk2aPyH_rM%6EUvcmDuJkG2Plg5DV0?F7Z1mHE}BM@!G9 zwmZzmm1gPWTGx8-bKuD)Hm|L__aILPCssWL^>NyN7!X}Zb>iv1*4OR%we skfVKLBcm;($LJ5_85=fR5$d)V-nOr1PzDuYAQd=84z4{+0 zxooLj)hzrg6jSC}5K-_M*Va7nDRW=(gp4;iZcE~WKrD$8OQw>gP}x#t0)=+@q(d%K zg{rhb)qQQC<`%1%vDH)9BGuPrWQ_r)D~4rc>};-`oChPtn#hRxlWV#Bl9+rWQF$XV zl@X`qSE3X9<(KhRGp_l1G+3QetnIU}llzkctgsl?Ot)fA@!D$WMvi;)qSLt+M{AxB z+cS`x7T2B5VrOi;o}?7Qq=8^#Od2t;#gswJZt$Y(FxR1ADqN3YBlTjST#rILb4Y*} zJe0Pu4UCTOxDeo0+_*Lt(XPUl6L57EXH$xGjBvX$4g_H@>2B)`l17;NJ^}^;ro@XB z)|}K&u9~x4x9!jgz_xkGwz1h#U&v+K-bfvPv{J|rG*V!0>~#_^3S-ebT)*Ok-K8i5 zUSfHwwnw>f9m978#V1&l#xB@Nw*$O*DNJA;Vs4DA$f`GBD?#sDp6}aOJI3cXQeeV4 zbFw$VxfKFqz<4!@I-YydV&qARkLsT}2_#+sTnVF1UUFkV1GSyx5jnz+Q*2 zmEX}8MlXCsJ1lm(vACYuBr3&3@82cE^1Hp&;mo<-mrrYr-MPJbzy9;WZ^<9t!Pnm$ z*1qjs9!@uRKX@|Td_3J8>iC;KDkx{QBaPJFdR|m!=6YWo>7-WQ)%Gg=%3sw+@6xb# z1~*#hFWh?v-RmFTzx{CM!Ol;24%9Qlx0}1S_jdX__fVT1R)yPCf9jxd{`U)q)z5|R zD2QL?eyu;MKQWgdo6Co_Prtt$i))ZYf7L8-Rg@+c4^)2ag)8D!$}@aVSTp*4lwRn| mc@wR~=TH^bhKZNpNRcGzA5wp=Riu^s+QagL@_z)y%=3TGc3npR literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_entity_onboard/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_entity_onboard/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93fc161d8ce2f5876be92cbfd1752d3d8441ac72 GIT binary patch literal 271 zcmXwzu}T9$5Qb;&0w#vEg5V2WrdWLGG{<{3$tkUU^hN9QRks^n2X^b0 YZqi8Z_Rr?A*l&%9pK$U8r|C%Y9;FCMi~s-t literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_entity_onboard/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_entity_onboard/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04e4a7ce3937a1521f5db4765df09159f5390cbb GIT binary patch literal 254 zcmY*TF$w}P5X|0zh;ZTq^a0lxwGagH33fI%AtnJ&E?G$;a+Oc8^bNkn+Q!1h%1*Ge zG7&ADVs~Z-cIK324HB^5or_M`w z7Rarf=E;TFG#nO;eXLP#N;R?d&>>cJkvviWxRSQ51@Q*| CB}l6P literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_entity_onboard/controllers/__pycache__/entity_onboard.cpython-312.pyc b/custom_addons/encoach_entity_onboard/controllers/__pycache__/entity_onboard.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b21cd6639168deba4d95dc595ca85fe473506006 GIT binary patch literal 13004 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 F{{cYOd=UTu literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_entity_onboard/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_entity_onboard/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..57df094b8e5508eba4cbb5d8ead1e8e57202f362 GIT binary patch literal 289 zcmXv|F-`+95Zt|s1PMw*ML|J(4Tcm*AjA{sXws~VZ7Gh<-jjU^x{4=I@&?{QO%n+k zDmtWesj`QTEoNtSN1Az`PA4Gq^8Dd%WPkVKe~N)@PlddK1&cKVoFn$U5MIm+gs!Yc zKPZ+8HxrZB)aaC55_N2nvo5w?*Cdy1(UIcAb zlX&S&n`alZE5(-i4=%4&bWb!qm09JM18HkHX62$`Z5Gr=wjFVNWSy)UqO&6M(YHkB gO}9I|4QyAnyGvs!(AUpL0>339e!|HYoTUTNd-Qct%K!iX literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_entity_onboard/services/__pycache__/credential_service.cpython-312.pyc b/custom_addons/encoach_entity_onboard/services/__pycache__/credential_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c3bba297783145e56f23171ef2afb308817585e GIT binary patch literal 3376 zcmbtXO>7&-6`mz``6p4PE!I*ji5exA6*>wTD?m^wvQb%bW5>2qL`Vb+4Hm1Nk+c%I z%g!tyCfwW z1=hh$8e4G4Y%14G!jDu#E^JQVuPl0HSC;;1jjK zH1I%b&X$4!^cEt4JBS1yc$76yJ2<2nh}nCXq^zL_d%C zj=CMLD3x$I2|6iv=Veq;7SKz`4*BvK@A60OFNsw`&($F4pW^Ewp&RJ# z&o|Mn;0?4XrMt8*!3E$?&8C=9o+)z5IE-|Q5sp`wmB%-=oIzlp;Ms-uF|#&#CKkh9 zyQJxBSTNyLYI9uBINt=;^QLASmZ{}bgN$QM*R7&ytK2Fwot_^Pv9n9+axu4|77IB` zBV*$&iJD2;47O$$`S~$Tw~d=Zg|UvKXV@yAYOx7@sCjb=ze6lbj0|R(c{nL^h{QEU z6-G?qoWX5utzcs4p!%j^ui*_^;@H&kbR5&XX5_|U(qTwp%`)j>fu1b}nZkx?k7Ij{ z!s)_37-}GY)8t~2Q_St6NZU^Ly-V#PGmn_zd7rw<>27RDJ2>s*pGI2|b7Y~kqqs^t zimRuCoURV-ofDp_9d37`EzhPSEDQ7@Fqud<24H}kh#ym@=WrZ5=5CmrXv-Jn z;U9wYAY*I`Hx2MZidQU#M|nEr$h=4_C)C__f{;E=^wKSz7KFc@unKytQU*f(wR8k{ zXl}&`LUf&2JCf{#&{KX7ve1cp{!-mUc7hOTM|Q`;A}?w2({ff&^K1#cW@>ABjbsbV zTBnc*6R%CYk+mR+-0s|D)}))Nx0%(8+_v(nMu=tdEH!lt@?Z7rw#;QqV z=;Gm&>aAr8CFfXEMb+~rFOST&=oXr+nIj}Zcm8|mK17W{l<58B&DycyExF!5xD~JW z4n09V(M4%%wh@TO7o~dNz;@|g>C>O?_oZun>H6SsHMD!RK7^}%yFYG!?l0~xRu_M} zyf<{Nj$f)?ui=UMnW_4jbM=w4kB>)RIdOoZ{k@;ajU+mrswQiR(R=a63*w+g3MGaf zMh3t8RzXQPT!KUYp6J_8jMNe%4_}=9!@{2yzgqnB;@+kA{+f8d5fuARxd_rPXQDF$ zfv*NK7rT`|c1h6dohU2v%|-5uhmku781CZke~s6zas;Sf6g7Z=to6=n0Y{3q-oo4F zT=cgj9*_XVp-wz!mng8_LghBsXNZJg$1SPtRWX8{@UIjS`CQbY;D59wewb6tD#`<| zTHOu-+8=wC!mnHsy1OZ(QZyYaf3`pYPTP6dL^S{;3qxAxO5W`xE`)ai)Bgmn;+_HE zcR;HPi7k}ESLWah{}Ps?0%0?vW5T~>d;{tOzGTjdOND2eMFY1l2QT-U7Ndn+=?C7; z%jj0V9GNa$n4=oQ<>~S1Y~cb-4+-+_8D7&kUZ&LaZO(Ya*972A;qsC<|B+Y2rkeW9 zdj$ZL_X%=T131^$G;@{Wl2F>mNUW{cPzzTK2BpPCQuma!?1Xu7S>THkb1_;KrPYZv z$F}7}mn~9K*X(?59+0>f+~I_lMVX>b7>q1vW~qtE0;E}w=-|ZwsK+6|=`a&-3wBDZ zMEoc?@^#_bVX@dHysQFb7AbdRG2udx7Yc?2O+tuL+quHaFSdQ}1JhBOG;s1Nbbw4f z9mtgI+v%z$PwywwwPboP`O1EBqL!Ta;`@8aX@OS#TXT;F&eu~T_cwMo_EXtfD*JWn z^266J*9YkT>0qg;~_Zk0CYr$&_FT?TXbHe_C1q=Ow<5cab`SO{TmhWG?XI2z>B&j$Hfsu_^NPeSL0IU3)O4Amk-J9_o4>f|?( zS6LRe=Ao!ZR8>4gRMm;8YThEnoEUej>Q9PVuDQcTfYw!*O~B}P$Ypl*V|^dGzyRx(X;K?#2a!s3+x?slT^et?S%F9!Cy5Yp#MVsD6%(9b>M zX=J*o)&({RYXVXE8R(!&Nz&g?&!gDD*4Tb*pcWh0xx5z}{V@Em&_zkgJVBy&<@_5> CT62g1 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_entity_onboard/services/__pycache__/csv_parser.cpython-312.pyc b/custom_addons/encoach_entity_onboard/services/__pycache__/csv_parser.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5424bd94274fc18fc5a385ebc20072064b06980b GIT binary patch literal 3034 zcma)8OKcm*8J>Mn=3}7HudSC)Ku+kcc3KwX4Yfo*_9t!kAMRLVVa!}D;a#N)MMRV#uOD<_S zZju4^pMU3n%s(^#eE(p}TG^qgkm zOx>_fxyH|KKQI+!pcxLM86I=j(Tsq3pyHCCiZn9jT>F7e9D`&U6Z?j3Kn3`Adx2Jv z8@NLr=Qj0%P)WDPWhLKk55e5shFyu9LnR(Q!DXKPmW8c)u({D-B-f=LVv(p({L zIis?yG}_Z-&Pg}_*x;<0Gqi@Av_kYn->>5m)0$IkqP()?8uxpcGTZ{O9&m!qjH@h~ z?!1!pqtJ-G=p>cLbEe}e_N>C>j_OC5GzhWD{X&>a9c{)`j1=72qoLs1$qCN|FIyQZb$8RuTq;#RQ0a6x=HdG1-uB*2Kg;8fp)fO$Zz2vNC|A{+`kh zHZnFgsE~24QF$D;Xv$v{zl7R;Ha%}AXG5%>r`M9g#5WMmElLLpN7Lg zwUL5;_a#YP1?YEDORz3WpU>+!wLt8w0eN!b*op6_Y;4;;IsQb-G8VOlFqJ7duASF( zjBU$F8CJ&DGxHi;0n=U5Z0i+UCpZP3ubCOcNx{x)el%osVTp!=8&d3P7N5~zj4ji7 z1Iosm=!+iI-gh&1XJR9Is5X?`92#948eRSA`p}v3rLFFGIaEvRE6e}t?yVeHK5&Qs zF#17s_0qcX#CmtS9NOwiY<4LhcPX`zN2|wwTs`)awfGCw_7}EJp4mJ(xps2$?}>A( znVXr4xorOI)y=--T3_;BpIS|vE6YGW>ls;@S?fua+dhf*Y#mT)`%nE&{6pmTk-r@L z>%Kpy)=y7WPfb^cp05sG{kJ6ac5Wk~qw@d1wS*u{Tz4b)Q-~QgYdV# zAHv*L&?D+clWSdPs^K&L-8qi>&T|gCO@A7FY*G^UJPgX}5+#&G09P@($^P=m~o)s3D>-J_&@%Eo&;gYAjI+u1o|XIy4J6*_a81__~c}IW#YqUKX~@e2p2wOPIRfoNkwgrykK1K4UD6$hm Ty-!wA>_4F=xxpO-#5eyRVNJ$c z+{yWQB}Mr;IjKd(ews|T7>byI5-S-#gS7uj)ekKOO6XT6=BDN)X5=QO=ob{_XQd{W z6dM^Bnd#@J&ryk0@&FAkgB{FKt1RJ$S$psgU66@wTbm>C%v?=eUgu>m;%#s@*M literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_session/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_exam_session/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..13aeab1c13cc5bbaa34e27790721752e73079768 GIT binary patch literal 250 zcmX@j%ge<81pW0_Go^v_V-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zJgF6lx$(uR#l@NVd48Hqw-}0;fif!@K7;iCD%1}xPAw|duT0EM%}dP4O-#`*D9X=D zO)e=mGB7gJ&riwE2NQ;t`gy74@lZ+qu*uC&Da}c>E8+mU0OZVK5aR7fK6rTOF`o$!|?xFnERscag4Vn~3Bh5!mmss;}DvNGPmv9Wi}?3fVC zpcF-FI3Z3+C8SpB2_+IeQmIn8_mZtE*&R};65`NXXwnO(&a8K1hq_$a-a690c{}gT zyf^dS_hx=*ZS?}$7G71--7WxLvLB~OHnVx3GD|=ODwhTETF=Ef>z|JcwCA&8PKrw$ zlL=W@&K-AifCms{0?uOf9(q=|+F#tug9|_v7l0~3DYLt-<8Uj2t?8fR!mi)g&t#Y* z;ta-l+Pe|FRe%OgI{K`q+pwDLHU!MoIInUGATCg+#Ei9NTg&cLUKLbPl~!FVVr@uu zFMt(W8h8EeycTPor(vGAVV--=7xt6R^LG-tX=oT}UHe$qFw(PGh?0DR3vSA@y>1dp zmH^%sWg4~YQI*?Axr`H^ZC$YKaE7h-R#SQB-0$)w-r(j0>~U0@9Z8A9t&SYGIb3F! z!_|A|n4I-hu}Fog^qAUFU8`;%C`Bve(`jHtaY1=19t8?$mC zO1Ez(0aa)aMDlY)R#H%dD1l*Z4t2da&@_P}f7N8cG2)cWgZ1{kOI?q;*1Ctx_M?^d znAsjHx1XxCkD2XbYv-?(+vAI_pW8aC!Or!zj)$cOrRv@TtHSEo(@Re-txS{$V$Y75 z17}VDM^(SPoZ6CvfOi839`7by9Ta;kzoX8EM(LTJN?;6gc}xR!2C+jVB8%HNJ7qkV zheS*i@CN z&3gZCpf&?bvsG>m1AscPT^1>{o0Lt*yJ=7YnPA-mhx>Ot**+t&!J7`pM!i@0l28&= z;W58r7bpsDak99_!Lfl0D%5bqPKx5;WpIeB4M>4~Cv9MZcx{`kQt)XNu_8%4nvRtldO=gs9%~YUnhH@^LTp#WTTfcT z-<(A~Y*4Zc8mzw3LJ$feb~6!wqqD_>%^}&S!|WMfQ!)>>Tp+lAY4FkDTF6y?U-j=48+WVSY=?u92hAF zMi-^^+S+S9_9C$APcph{Eu3C6z@iD1D<56{8nS{kCKq)cA_chpedQa5jzaU!KO&s4xDqzSa2df zI@1{md*4D33Q;f6`-~i9q?Zwf8q~+gAxgrcjgxv3pnf_|-1dOMF5WswcGdl02~_NB z4wIc)%&u{tk{v)fYRbnd@<~%ZS(ZmC@;OsJ_xw~@p8RJ(*#^Qy)xU3fcthYP84h@c z1K!5LWVnU2D2hfeenlZ(Mak)EA3d~>mJpNgHEpX(U+ttpludZ$hoa=+vVvFS4lqk2s zxQ&hm#i3`rnc@|uIQUw0)f8)7%_=h(ZYA!lo=T;)6k@jp5$Hn#v3rGx?B!DP+r!uh zdrj9KQ0&!ona+X;MVYEwVQWA{y!Cf$Z9hk;xW30XEu*zFI)g^2fL&z92}(8uj^kc{ yT`z#|B?!I(oxgzYU%g$6{S|MQ>Frv+SoR*8cW=24aK7cSFQ>kk`U6nbTK7+2ZNL%$ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_exam_template/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f5d194e89d5b2ffebce892922feb8fff836da0c GIT binary patch literal 268 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 tRVR%_abwY3cfwftp6;2}NNb&O5A literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/controllers/__pycache__/exam_structures.cpython-312.pyc b/custom_addons/encoach_exam_template/controllers/__pycache__/exam_structures.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92b4cae43fdb473217d7f74acb8efd7d09c763a9 GIT binary patch literal 5233 zcmbVQZ%i9U7N50u*Z%E5ip zwxNr1x{*BdcILgeGqdx4zc>DSdAS`y`NuX@+);+mzsQ4Ln7pu_03nHZ#8VM8kZY*{ z3Z6|7(};P%Op!iwgdSlA7z&w?K!w5A<|0@Ys9fKGm8Wl`0UK}SncLKW-Gojfp1qBD zi(n2{Z?;2d!JM}%8>cwix8&hGN2&BxMHz+Gf`yM_f~ zVop|wzE;AlE*0CbwJ7V-7$uuv;gr6pe)Jkrw9OrK;DnZqDax5f_Dxwtq6s;4lFJu1qWdY0n z@!*IM4PG4y^8QgQg@uqJcXo7k`6XVGv})fW|CM0qnh@pvp_r^lBY_~#OHtV`L_<GMHMVXBE+{gA}cr+Qes$;+egP$dw@(ga7E(BaRtnSEK}}= z>K0lvnHkTjv+~}=orwpnD|LI*b$eIpI@5KX&*~08;WN(el(qXmtB$Jg5XE@1PWQ*Q zH8V&rWhdDGs$)O;ljAsL{tKd@4wZhH!WZlS#pEl#UmV4$$J9dJz8}F(e@dyWtOS*q z%$agq>=_AO6LL#|g^j{?2ry&=_t*`UOssuATn>#|u~83KLZ_y*4TM{0)!|uj>`Xg$ z&hbyWmK}#v^kGcS{Dw1VfeupE7okcb0g<2?FhPKrjZPF#@h0BP)58?cJZ2a2;m2EU zqXpsx$^i2UTk9rUTZt{ZrLA3iuVa&KS&6M>yqv30Yfi$U>DN!jTZJ<-QRNSgirT^1 zTRb?Jgr7>s;J~Wp( z2OtkMOih~NRJc?JhDqT~dH_zE<7V6tH-*W2Hx;r#MaMG~H|sV-1&Kl>rL-42`w7^kOiNyqE38Ip|WJ8XR%5i;a43vBgcV+(QE^eGj9Qi1@Mx z1vaJ7-BlVX&AR`%HE!X{9~8c>Mod-uXpWf37run<{;fbv73Vp#$_7JET~j~C<+ zXU0A-z%9fDBVitJ0dW@9B=Ra91wzA3WW(B#?_W! zR^3(i-%DPcx;TAiE|}TYmT_|lcGcre?w;D6YV1mT4z755(w?5D*O%T;T@I$in<-CE z#uHCiR$Vno$CM+r{f)Hiz>2Fk?do0Z%DB!ZnCC7}g8ABAn>e1Wu1%cII$ih1KOTpq z!QH&t*fJZQ3D3Jf^M2~hH15BDdW}Wpo_l?F`m)tENq&mY)_P~z88++h`0VB%Z%)5E zdwJ&a?BMSP7wPQ&H@@ipynFhi*_$&rSDO6Kn*56=vfCSG&(55EwtdfhOSZlx+qwUX zw$Ixh?3jIh=JmOEAARufgXOyRMbitXwXWg^WG#2DIg!WveG76m&NEM$bYoA(c`Ri; z_Mh*)sJ0pM6?b#C(f8ZakgvF#U&;jR{%UPH)ol8**>TFxeA!Mxt$5ANk?!59mpHi}yNogqvjI46abf9%?1d=p%8OcN~E}rEtG6Vky2%*o z&LO4-mWAFNFuq2{8ADhlnw(R+QQ&sskU*@4$120eMn+{!QhyD_@jj3M`!!D4(wPS1 zoCUu@%nlF>TD!9lI9KWG!HAsW7&Z^lBs%hNoWo+BvT^W4GIo}N_8u_g0zWnZeS4Q`@mxQ=goenwZ=1sO@3f{GlgTGA)NPHHTNL>yqKA@LbiS+K09CZBKeL%?C5p zKY3weT=oRLRtA2OXQs|fU(Qr<8uYLFUYq;r?<*1~?$@Ww8oqJYChMo_Qw;~w?yeR0 z(X{*MQ$FK<3lQGfkoD9ixhXDNRhK+BbuQb{wbJqCvyL~Xt5>{S+RLqY_dN6NSp+<8 zoORAPpVjW2@5~^eX!)VX4Gx92Gh4hrF}>jE5X z0Nii^EQ=aCWCIuzSl5a%7#pSQx;0!biq-(nV&T1TQ?;JQBt|g7wTa4p{d(n#N{Vj? z(iC3&M2|hyBF91@L6$FYY-w0r!O{&`P+4INQVCfLBbALsBVzO#geHjwNPKk1B&8#< zfsaEalN5=BK>qymLPUV1t)RU1`QNPhF7ZaHTgd3FMKbPlke@iW-J85KdG{CjP&l4y z>0R2tT=`C_?47K&;$Hck^1DtrkkjMyJ5r7QjI$$U?a1}p2KSQcEUCzW(R^uZ#pEKdRYZ`!2g^fF-T94#5 zw+CMY8#sJOJ_Z%!K@{~ha(s;{{*AW%6E!@y*C$$6?Dc7T{q&iPedjI9cPveL)+;Eg W`+I9IMeUpBXQdhG2Sj9TRsRJD7dK`A literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/controllers/__pycache__/ielts_exam.cpython-312.pyc b/custom_addons/encoach_exam_template/controllers/__pycache__/ielts_exam.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7bed2f2264d4facb6b5073b6ee80780addee37c4 GIT binary patch literal 25781 zcmd6Qd2}1cnP)fdiv&o31Oe~>Z-S>tNfdREx_C$=MOh=sau_=thz(Joc*qS<2MpTE zu^TF@w*zcL%WS^ORvoDHIImx^Q2*!Xr+FfPF`||YO{6QVrbv*y< z_f?}CAk-l3Xf`h;p}M-d>g($2s_*-KUwzg5RYr!6g7A(19rgZ)BNX*dcp?O4Jn`tK zkeHp(PR)8=obdSkE+uCeKJOpE zQ!ndbxXgiJ-}o4u`_7J!`8=F)z{9fRY$79bV94X=3!NNiE^^v|v+g19nA`8UrQoz9 zUZ3AH<{cZtJGdE=IL~_hn9%sndfaCqH5h+R(o!wN*ycz74ACqVq=rfM+6Z!GYjf}n zaurYJUZ8z4cmp(CRi(WugR7c#uaa@GwnUt=9O@d@UcocS&3rO<*z{x`qqwFyO1YGM z9L3^eaSHc@f83?vWL}0-`n~=U52y5<@s5mendB{b;f)NAPmKAwOuu*3Gce*E_4)@! zy<=RaZ*ZK2E*%*4_)m{B(8u^*#|Ax|L9FS8H?C#Pa3j`&Q4U7A7+EpO!^nma4oXgr z#c59N^9=g%Jvl$~HyrnQSYN|M_o!#geR|Z*G@NC}hdqOSU(=?h=7w=*e4Ip$+Z)C_ z=Lg~!8wMwQ{_)WPH^ab4YJf(Ky9ZAXcrLg{2mGGVvm-EM8V1M5{OtJ12-1hK>GzTA z^=B_~rU7VyAD`SmKEQYf{cIt$#t1*32ck>Vz09mvPhCD0%d*VcW^D1pw~OXZ#_R=A zdu`ZWyKHYum2#Z!FId&8rIMRYmh^!+Et2va|-(Dy3Db9>I;MHKR2f zGRSCcgBSO&Fk;q?%ip1zAR3!4(p&~I$2o;I^b*M

$C zwBI2V2+{&CpOIZLDxkz9%_y&B9EB83&dyUVRUexL6$lIXy-<_I7P~SM)0NW;lVt$7 zgU&Z`5@#N!wVpBH6&Fdi-ve{Y!(v*`czlDb_bkpG;1}b5_s9U@8iZe*b^Ck+{?owU zPmhlWEsN%uvn=Y|9(HbDcJ5z#Hda&`E!q|?+7`>sovoRvi8VDxoA!m9 z_I+g8zi?zFr+nW1o1Cg;%l-$BOk_HlO4T19+Nqp&+K1EmU3qr9J%0@c!kI-l&OAd|^$B7WB`B96OpO8m z#j_qx0l;UJQ;(B*=i`*4ZuX3i(=pytr@VtO#V+!r-pEV2K@aQq0vcmrs&7GR3WQyp za%9}i_&8(t(ZhZ1o9oN%B*Ui0~$;$8N@GD@M&2;ml&UK?IYDevyz~ zGncZ&2`!4%Rw!K$Ki_vCxbKsqN_zQQ`W3%Min#Lh5TIW?8wYWEZaO=HB%LHX zTVK9!v;6HQ8sb676oWdRdUS_KWe+q zn=L^_pO%U_4Hb(76+>DoIfTlSy_+jRB_k~rYnpz^lc18BmWnOS6WJxG7%w_p`JBCj z2h9f&8Fzqa+%LlAKyHKkthWK>B@dh%20`KSdsyW7oMLQz3|P`LhmRiXbSXFm&!Ire zIL)bfO~J=027TxE_9w{wK(uSqj95sHh3kVNw>94U0l0K3Cwth=6BOo~DFM z5G(>b8x|Do1Q~JqO)An*Q3zBfl|eZx3o3jDzcBqlX=YTf#aaJRD#7N5CBzt`MxAFE zfLm%1o^=?Njg;U=W<)|zF0@2APO5^cVN|nHftEK)YnV6a`R2^g$)7PwES$&dN0L zsIl=xFZvN$ksy?T-h4sqO~V)JO~Ww4vy>q4grFg4U>xT_31sqN?iiQ?rV#!WG0tlW zskZ>73xsD7Yi2^t;f6yKu?BQ%D8HK4MCQyApVfIvxp9 zCP;s^aFxJoVh)|ue2JQ-uS^MG8X)>Ep%g&yEt47kHsO4DuaHU{nNs0RKubk_@82(! z2xbV^nKGfJgR(E7dX(`psNMYWJT2VcRo=&|tf+ACYB)Yqpd?Azc7hV@B-S{moAo#a z6Y2eFkcxqvxIL>LC2+k^E0BFGZrO6ecygWsn;moiyHNf!^P2L!X{?i|{%kQe0o5T+ z$*}HIe$X;VtB@h3s?;gkbPW{w%ppO#KCWB`G)H-D-FY8ck>2)qA0?zq&8hKmz>2WG zrO+i~Q3YgCc-}|d{ys9}`}juhqtIma5OFGY;w0-Gy#FDb1k6P5aq=L=dCKh_@i6xv zLz`SBESi8hIhd8f>gfl|1&jI_i|Bxpd&bUzYBj-(bE=c<_<68M%e`O+Re3Ier5TJ8 zanyrim-H2a4wC7-N?@>-S2(SxGDqtJoEZ(tmkYb<|*iXO^%lJHg7Dp$GMhZ^b zabeKI+hNoLBjZCu9?;}GVxAlt<;sMo^NgJ0WM|HE3N)xE4NDx6oJJU1EHZv}0Q1!G zmx{*P3!EC>^#J2JMGU(f?eQUwbFK-*kir57qXNb0F=aj9nO#uKX919RiCWd{)^56M zE{>Q>r`o~JalPtl)qHEj-Z<40%dyQqH}l-wPz3EJwF@Ot%jU3UbHuWBsw0+{e_eA` zGw+Dx)lD7zow@La=dQIPRM~UqXvBIXWIFPRwQ%;OnU_MPJHpnTQR|+tbx*{)FKRs) zwjR7|GEetJOwLDgI}LOv2zJX>mrL4~jwGG!Svnf4+7zwo2v>D1 zR~^2S8?zUKLfb)SKB9CM<5c@<9%U<-Iv6urqsHQ8V=?H^S><<~WjA#JDj^Gn%fc1?TF-dO?7>2%)8dVp#ABVm4cSLWpxYQNLkB6 zN}FY!>7Cv`XN_4LvwbstvC_($+iq-&6<6JK+;A+MSkl}!-+u8I*4x@pb9bb;N4&6j zGE%%fR^9kU&8?bHbLSm8Qr(^YR28W{94o82*>j_3QMYvTcH_@Z+>!mPFH+X?z^Ez9 z{R5@Ru|AMPV;<*HrM0j3MoP9nq;$}>ZfILhYTGKJ#f{iJQr)(ahr`bx72V><` z3yn8UEXr>5fo&e!pv|$a%HgKa*%?_;LwVRxzGA3^f%>DmMMb1!>!L4W-Wf9N{Pgio zcpJP~|8;N33f)L&m4k`yI|sqIkX8OKkJ~7d?I9(DQEo6t4FzFCL8x%^iebxLbIFf3 z&%gM?=7r4>bHi^84ga#Lgi@dRj==2r+TOz62I?2Zdo6HyyLo>G9Nt$H^=44-mv*?| znw>B|&PXjG+n8Tu0#=7KN%n2UfI_l{)z_vgwo{zz0xm zur(y0mMe&0P{Kq7%P*=^PpVD?REU;B0tgg-(LyK%T^Ugk1VA9(+m9<+Bm~9lj8bS# z91tj8RuDh{$0R@i*7$=^^Rvtjkbnv4%^rZvfQgr0Afn=;i#-n6E&~x#>~oN2zl2dg zM$cnJM3^WF*i)D{gwbh?yb!sR>@cSLFgk+~Vel_P%7-tCFmRr6KMSXU!gUxoH0)KZ z_f?3HYip5fr{|BiyCUXZVCZHmve56g63)79$sDn^hD@!Wh|?%yZVnlmKmEj*mpVl@ ztr!~9P7#z_U)!tSTSEOJ(~NP6c3+YF7d5VZcKO>D8q#mul@N3CXO5>C)_E}4|B{Dw zP%dQzXB1}uW3$PVVXZ|%oC3ncnN*yn81)Znux2QRMcV@OUpxrqV5v#N|NA3O<6D9H$Pl8j&kXmM)y$jJD4@XMgja5Nxc zz?(jnum}X~35>_Dl&Sb8uZ!{cA~&G6?>MrQSWfuJfjgxU zYhTFJ2YiI!#)mT6+DT7!-79z9?7z|f!{?*seOHgo9hs*Wk1SRG=jW&QPQN(Q9y0Hn zY7d+D{my8PnJlxq8Qt8L6_YcS8U68*p0ezxKYg6}MFsahcv|2}`whUA>=?U>A%0tD z*soH(ZB=5N?}D6nR4R-O+IFq{og7!YLjF!04e56kN{9oS)|J%6p#j!q>&}jkkJJ&L z4QaXE{1?vPaBlHI5>F^L!V{AUMmdCRO_EWvRY9ecd6iKyYUvtM>xidBMnzLzYEqRz z3}CJS_5w^$$!LJ0`jmW#M#B{t`V>-VBEb@ojiMfVrC32Fu|$<%ULZ*2i?KhEy=}<; zbSX$hn*Hfh+23a-!2%#GN#2t4tBrIkr*gw;{W%YBNI-l*)Wm=dJ#S#34&XrLor}H@ zrz-_YK>O@j<n6Ne*I;!RK+a;N?R`KF{`~ppPWS<1|OmB@Nvc^e5350bCH=;Nzqs z#C*JZtKu`$^T6yUA1qL}4s?35_Pr$Ci+N zE9lU`J74+MD>0KJYAOkvO6GePOBelbz4GQO(QOCA+YW|GyH`v-_j0ULop){JfWb1_ zrj;>U*@6|yO@yjiLzQh|TidiM=B$c3w}zct7f(f;t<$RMiEn3szLL=fN~Wb`z9M3F zg$yn!Ah&(Rup=#yD~FyymgxYNxz7NHcO2UGJo!6iu6DEh-3%Ji@0yhm2dY0mS6ssn z5hm;5_vjh0H~b|7K3pw^MX7Y$Od-k50Q^bU*od3K;+F()V?=W-@Kq&i0bV8oO6bFQ zVAOC|WioF}LrsKbxNw!0ng*z;lBp#iV;Z_zM&x4x*PK*uSWBNU_KUSN8%Uvy4W*Da ziHB=pNep1|>zS`9_^uKbNBl^JgrE+9wjs%<%aG*LWf0mW`g9qBdZfr0uZh~G=;37` zKsjHa95-@{i&n$M!j;64F$s5ABPo#8l8|KN&PtIK(njv=R7t^J0zxUGfH;nD3h?6f zu)S~@43c2nyiZKfufRDNd;cBQx`Js1dmf7@iCbABKVVK~qiY07_6Cp{pN{=HM#P4T zsxJFwj1b`R5~LMVQeq@i5;#v`anx&gml(0}?7x9L^h+j|TK3;#2^96bEJl=&95a-k2>wCEkp`1-qouaJBoz0lZm73j4ox@Wd9~&((6JPlJf_&jP+O ztPT~nu9(_BG3QRRv*%{c&7GQeN32yKJ*L|4CS{(CSX~iw^;CO00e82cV*bKn?hA zrxM~o&H6G7eYESqd(ty{a>TPnh@rwqgxI&hZu3p^U$PjJ7DpS}E#Lw9AgK)So)l=a zN(ryU&p{c`#FYV@W+{Ov0}{3m1_TMTSE7cL^I)=w8UkeiY9b3u3GJ{7`NEHgY9P7x z9rqE?gQB38^ph}yN@0L@NnRDyj4?W>gq3^6u;>t+Xhu-WWPk{Y8*?XhL7k+{#0XA7 zz&b-OsbjuRT7}Au32M$jPq1y$ zeK=)4MKhLfB;Zn3nzm=b{WVhbvBx%Q7mO%0L!|^JhskBEm(4h`yrMZC99C6Q)Mvxg4x1#CSMq}aXVr5%h|+E2*)HlVZjsdryFPmD$>~r*Kl~= zT*x8va1DYn@&OkFbA639G>#c8z--PI<&QkDL&t+dIP0XW(VQ z?jTtoc*DDW7jMx7#=rrw3cn?XSo=QH>>6>8o@Cr@fgS6h5`3ruL2T9U8W|r16Ji@A z__{V=AdgUsxI`@;dF%N%pTGTVcx%rkibYoObj??ddKmA-DEl`+iT&HPjb~@!{At>4 zhj#no?SApC;G4nQ7sA^P|EsiHaoWu?|9@KTfL60}*dN%v1a994#dn>K{u?^oNV!a( zqmNRz=sp)spflif93g0e0ek}XZgAs>Z=|@yFC#r|pI2g^<0{>!m#8K8&zYYwcWOgz z&&E5QY#+N%%{P;K3zjM$j!o~-7?|gA5rIXH5wNTov}@D} z`v&R+awA^BN$3>lJ;!f&!$}JpS%{5_)12~-fNdU(>+(_e1#~F^gBZi2%;w}Ho-y_U z)+2h58dFjlh(%HZK}Cc8w@61T%shs;X%ORsrc+yk~Q z!7c%Kx$yp1HH}ZB)jY9ka5!}2Sj2ifWICQsr}%P*q2$vUAzi8G7OLwCY|#`SpRT z0}IcFb{?G@h!h-~*4?uf!=9or{IBVWSbL`xF4{pX)CD8vviWn%=DL`(I_lgUc5aSrc{bua zF?}#*aYikbVN2zLHq>-zvH9=!-!?>c9SUzg6sqcrR{d4D>aSKTNAH=eMEQJqF>7(} zVlcF+J=D+bixINcGNG z*`^12RY~^$p;TGs)kb(TkN41Mrrfb`F;ucWV%`xl?2ximZdoyGO>3*fiU0Mz`ferl z3!@$5>H~QArBd4?lm9Z))!i!p2!s+5Q z=oJiLx|B8+iiRt)0xe}uRC*IS0vHzA?S7sl#FE;eY9phZl&gu9FS&sBz`K8mVQWxCSawL&|SDSp$WZR!bvncnaxz z>CK}QB(*EB5#KmDLKnf3Xbjlp_iHZBut5xvRauMp0MT|z2xWO4+` zYxE{$h$IBX(ZS>j?T+hBhL;UQZ-Qfz-ei43Z~6fc;xw?U81RzU&Gx`)AS>>Kn&c~W z3G$_^%WM-~K;0*xLceJ57}2X>yCZ(cfJJ=@KKf&n77!g3HADm!WTv)|z&Hn|n z5tZ{cX7q&Ajz)x7!Ih^=9& zJ7#svUYNNsuUps`u{KN{c%Y)n8y?H0T~(vGec{|bblC0wj`6Xawid^>w5-ah49o9~ zwj0|PE8nVrvwo#%AMp#>v9v#8-4inH`63qW-x+h~wq0-iyH>$Wji&4qZ@h5pg;3$n z71OSJM(eA=%fY$c6{AZif|l&6rCs5s1EIo$E2eI6#U*79uNZ5EGOsMk7oS@i4{z-Y z6&_wOJp=cN6_!T}o5F=n(Zc3%Ve_>9V{>85VxK)Ub7+3cLf+y|@Y7wf?D@oAe7)vs zO{k(JY~LQWw}tI(5&NE~y(?@75R`juaK7qh?Ty-n^GmWw$<9dOF6a-(0s0X|JKCmt z9;*Q8#7qTCXFe+GUdmc=HZB(b#<^v=sC!i|L;JT3?cXxAe;0Ls3ZBnzu{5mN(Bnl4 z)&#{(kGNvHUc1;*xNZ=eASR^D-|&PIMsW$(!(=~PQOpTYDcyEOMm3ZGe97y!YJaZK zEJ2KUUQG`pHbwz-+Mr4b^J*X3CCpNgnMYir` z9TC}ZOcL3~Cqy=p(S=XQXpp^5|7ov}ct{eHOTZyaTohT(QTS>PI!(HrxDkfrMRi>2HqOPCb)^FqqhcSh|`h-0T?erwoeaH60G1sMP9nc3~c@r z`g#<5_Bn_EcIfh+3U=fcNNjrHkwna7hh0C`{Hd;c;Jw~9)3#zRoj-r`l^d@_E4PO$ zw=W(0`H7#MSgvd*fTHUTIIJHEnGT6a#!+;=zP+G!<9QD zdAp){d%}5prVidSm|s0~`OsY3!jVOKaeJt?HB{3UvhQ9o?13h%lr$}FLy>RZ6*BCS zvR`1qw2~VkGOk?Lg5=&?4~Mr~w?X{Q*1gSec&}F5>5{*<)zw)hf4`81^!sH>hyxYt zOKV|&+8R5C4sL~G=Fva@c|@`twC+DiB*Qwc0)Au8tHq2G7j9T*nl|CL0Yvc$eIF0s1MmOuC%LhXHNd*8@=QBW z0{cOHU9vo#vus+L&>o-+d&eQxeP47NBlZK)c~xiw+>5?)`3v7epWN;%w-ngd5_&(p zC23b*Q7cXVmR{8k%1+~s2VkXWE0D4wz}^Rw^p$VRt`sP6_q*0Fx?RDWM_PJt+|r$+ zp{^!P>oS6RvdbM<9tPMW4zv;=AZg@?7BqeYfRmY$$-E}MQ_&$zOEmknFu||^OfU)~ zFbzx)`w(2mP`E)@SF_Jbg$V%*+3s}O?E^L58AtOzUQlWU@K6$PlsMx>MCl9bocy{? zK*e9==!SsKDP9j)#X9))F+dZb>cbuU0cY|pi6a^8vR+fdddLgJ$A+9_>#fkN9Zr{= z{jczduvCLzMS@R}op-ai^5F{@1xELUgg99k`Z`c#7ce4b0i2}#qK_3*l^7AD!62rH zB$rwUlC~239P8Z12qii3#h!4Fa2n5rvt)^mZNThI=-UC<=rKUP`N%suuWK;S2u~X* zT}PG+gJ=@>?WSbF{^C~cI8^5=F(+zXP#;Y`Ea!D2X~6!;Z#fNAu#5Y0W*eZSKgocgEH1n7wqq>*k>whvs*~ zB19;!?+Zrktd2<1Hs zmWZ6^=v5V!R}{6@MXYsC)(JHo4CQqr{a$+2hK*ekD(r<_ zF1Zp0fQA(V?CwjmJ+&JK6u^kiW;6h7g~Pjwy#_eEXUghqRJ>P`iSZ^Q|DFzqz1Ms!h@@jla>XYhs@Q7)!j-=K=DR3Xjd0gSzAe3)lvlFI)qg z2RITXVAgQ4a3ygBmqYR6Tr>q=R;(93#*#v5%cLoZlIX6NM9Cub?iyHxqMC%D=tmDr zBWq!i>17kKp1?85dXk$8i(nbTKf%PU_?+gX+Yfu1;M=MO_u!xhKA;NU3Ss@6E`A1H zBLS<2|5O|QJs6%Z!sn9x1WIul0W86$Z?qhMSByxXy#pEShZxmh)C*BSGk&(7+%=$s zRJ<_zRk*~d@dGE&7?+CQI{quH^Z`a|2?a{`VY8hh?|(3X3_f!Wma=SM5J3fxH-q43MtIZ6mofDth&VMs9Jk-kvcJYG5kPV3ID+GW z)oHxwg~*kaWD_}qxx^eoEFtgX>DuSzbbARH#SZ7x@uz@KSi>7rl85Co`Dc!Iqz{~N z`2J_Vg4Bo=1t(aN6@^dowiFfLAM5U`<%_(HSSugK94^l^Jq^|pjT*vNR~AbmWY3te zKohan;7+o*$s^*}Jk`5)Dd!WL^Sa}zBUBE1#CAt*?O|Jc#MTK*Jh|4XuHPB$F-OHi zN|RMQy+39tj9SXWmh$*FMebI(7D|73I##tMROQbgro2^IcGhwFZhqLU5i zOn1br`Ln^9;CElX>)P~&8gn;#*d2_Zm3tS zK>9JDz>-jD%Ti^iWM9O*KV;bd>0>pOSBxJHfoBBE5rEH7*}*$4A6bs!H$;xp|MFP( z1WKD5Uoq6D1!>Q~P{UOkGlH~QIJ~oSUsYE<^?q3^#2*wJAnSwrq5~%RoeUYI?-*%J zo8*`_YY##?-*r$g|4>Oo`a``E;y#y&(+muZ!AIH$1~}aSe#v=a1k;8A_~@&9gulXn zA5zJVPryGEy@l7`=tj-(&PHMjt_RD{fLPz>M8Ov=0(K7mWOG zfQ67!nJyjsX8%|FL#C>Qb4#5uThW|megc5Gs{Wob>w#Gck!|sqd^}Gk`)scF-q-u4mDmVq)p17HGCCl1MaJt%*RB2x<$1z{AxOK7e zwi55uMUz`4*XjaoBDLBs>1xGEH^XXhzS>JC-L93d*SuJDI|pxffWKW+QoRFE56)L% z15x7Hwn^7>rPPD-)#nrSVw#>4Xf$pU?zQ{dke zAVZY}Edtyq@w^`Yh6RyATopOz|FS@RT=EXUhq>x;vsV1?34r_rK}m)<(b_dQQi+s8 z`zNP`Z>IE;Z*s9wyfTCl(ea6)eiNSJ#xqX0U!=*8_TS>AB8+ebfEzYH)7sd7gj3-E zlW(2)>`J&!4J{>KtL6W9~piSAI$TkH)r3 khKDL0t$JuTLR6MTs~%UKQ_-8|EjNp96#aq1G`a2n1N_p4wEzGB literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/controllers/__pycache__/templates.cpython-312.pyc b/custom_addons/encoach_exam_template/controllers/__pycache__/templates.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f38f2f7bdeee99242efa4b7d59d3ac3c218fd89b GIT binary patch literal 6816 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/models/__pycache__/exam_assignment.cpython-312.pyc b/custom_addons/encoach_exam_template/models/__pycache__/exam_assignment.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..510137f6c2e1f892148093650ae9e6fec0f5612a GIT binary patch literal 1219 zcmah}%TLrm7@v0A-R`mv3BH0^7V(iRhpl2lVqzdf77PI{zG5%U*cqUtkEPQpyO&)P z4iFE(2|P)>88~qCPcZSK0pq3@O+0xcf)`HCwEOZvoWs}O_s#E{?=_uIsZ;{cwO;+I zzvcn>$&}_28{l|^f-Qgm;tXJN3TN^P&jB7x0>rNX6v5nLwCU9T?nXka2xTEJ{$fg= z_oJqbutEIjoQ@4dv^F1rRzSe9fEXwo0t$~fC4zWG-~kpFlbsGBMiC?+aWC2m7(0_0 zqdaMs7Rr_)oym)%L7VTl*SJCqjcBx$a`>1qkvOae$4tNmuaRJ zTreS$OOCxr$zJ@Iz>&Ga8YVc_`}wlPNB literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/models/__pycache__/exam_custom.cpython-312.pyc b/custom_addons/encoach_exam_template/models/__pycache__/exam_custom.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9be64d32bca66fd8c0648efd43419e5affd7e082 GIT binary patch literal 1795 zcmaJ?O>7fK6rQzr?e)Lo#4*H82To?0abjvP5w>LmzQSaWG5E^v!VddaD8c5NpSggwl@_w6@t=6&z^ z`OjD^jNrNd(_eZ}MCcWFdXLmK-kt?x9btq81672gQ1KOg0`j465%%3h*iVGjKyTCj zd(-dPMX@gCr8nHk`&gi2VPa4gSk{SwX=$I2Q2)T!0zZ(TqJUA+hlQda`--9u5otAg zaD!)KKNh#7O`qo#gDx-m9$o+kx8y!AbR;iyh!;MR7e2&`9Lb9u;zeEF$h-I3>_Wx3 z%lP;MjHJt$_y8m2GA7?;;3$r*_;7qH(N|)~<$nGiZW35f3;q;`kBYd0@W8JEPC*q0 z`$f;V>}hZB!4(hTbpPbz_2GPm4a}J(ODmP1UJ%$b~>a|H8h7bWJ;WzSu>2hz+}sW9wdM!dSqI=xk^e- zBi;ju>F7?q5wZy_)F`njKT4}P787S-1us$2%$jDXTD59hw>6`YxaRpBRCGq@d9)mxB4_lx9G0K|lr zY`w~Z*f10j6VI15n@OOE0a8Pn^%=_~EYedK4q@T0gxn5!>bbB(pt8i~ws?))aaiO) zcow{1I%I{|Ebdqii0SBX$%<|=Y2L6jhsCQJrK(egGL$U?B435VdFc%S2C7ok21ui@ z4JHcEYejA?ni$|Zy{T>S5~>d41B za$!gEp9t&(P;z)T=>I6QEgsvEQ8vFZ`Ka))@Fd+H`C?nlbYi3TuD^_pK97z5i^Q=2 zP?DL)L%Sg{{#kQ=CyWLsdWn4f?D&h+!p{pf9~!P0i+PEOTx^^Fm3XZvUFQEEo?r?` vUG_<^_T;a;#y)GG0+)|1%BSp(Ul4@9(b#TaShyr?1Rg~nM*lBl_L0!!SBu=?Sq)4bIX2$DH1gY?0=DqiQ@8`_; zr%I&^#JBm)ulR2rfIp;?e`a6UzbJ%<00O8*Al5uB);(PVI=Bp=ejmUB(w42<>0s{` zGTAfQM$_DtN>k@nOdyIFw-zvpAPW!p0OUdTXEd1*0Z)U#)1l@SpzawuK<2V@*ddc) z0UFTUwgw4{idj2?S%k*6-4%_>&nvx>SK2OjMGcBoR;D3^< z)M6=#=TVqqlB}IX88V3kG#M&vlJ&uQ#vPMxW4TBD2#+s#F$`E3KqL;?rs!r1Qv|t9 z5^>xpMY~T$IRY{mUPIIt$}W@^jSk7JAfcd@5^j7fR(Vlq>juRkw?0?9u$VDk6(P-8 zxzUR9=0%7Wf>xC7%6q(4%PYItLQHnY$7EN2)|KDy%Fj`sqKKDsD~5b%fM7V+taID< zlORUE&&$3qZf+}*vg3;gLDWY~MG;1bSV-}TOiShPxjh>s?J1HVUQ|_x1jePMfO0d% zX@t1RzQ$3+i=QPaT11pr2iZf?N>W};vB(|a7^i-W6JDAZqg02+t1KiGCyRcJ(j_A1 z%*4b+^N5#J(pY5X&LAF!><6$fY634;-Kz{y=C(y&Nw5?L&|RTqS;S>iXQ$4)1QMc_ zb04`0y6yKtw?D!FLXt4IKWAU{m7;hh3R2`|Z`(a$;fnzgOQ}U)UrYgi_NH6UR*}b_)U7^b7%T9=8ub^q#Z{V#L)`(_3y7lDF<2!!=Au7**0GWA% A!~g&Q literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/models/__pycache__/exam_structure.cpython-312.pyc b/custom_addons/encoach_exam_template/models/__pycache__/exam_structure.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95c8ef1601c72a122b2ba29289582e064672803e GIT binary patch literal 1234 zcmZ`(y>Ht_6hBgw%*dvsex+#(M1<=_g&?LL3^*||G_lhbjSDpC7mbFv@SbeiBu}{` z15;U4AcHlzosv$?*uwq;`X>}9P= zt@5c7TDqu2lt9Qur5ivf8B{Gt zU7ht(@G}4U)K?>Gv|bUfug5;c{?7V7j_xHa^^=rA|1uQX4oG!}PxWtp1}Vo6L$DRz zzA$L`3~&M-k;Epz{nKA%$op~_1`qlmOa_nAfC1^(rmo{8NV2}kA+h5$3|pEoX)Ff^ z37isX-O`vTKmC=D?|r&yhXGG)+O_3uQyG5`GTyeKv)!?`7G-P_#M_JQMTLS`@!v>) z#twwN{%UUT)3_UKU$>JW0@k)k(Cr3(8YWrW?qSaHHrPH*p1K`#ktEGiyl1Q=77PZ+m$FcXHt3-d0H zvt=5CxCD7SynqNZh)F7Yo(bbV>?dNb2qo`xQG=NKfYK1K^o#u@cnm+IGwB%pN1e|( zFz#g1b&Pi+Oq?F0yWl5$`P%Y|LkXohd4JV;i2Xf?iQ~&iH1aSZH0I7^Hl7;0mq64D z0#OC3%X*3rmCb@oVkDCu6HQ*!Xk)^1;gCjp2>ww|-h0 z%{znJ<3{tl%Cq|S^%MKrFV{znjloCb`r8MO51$O5yeN(8OM?%`wYLtshkL`lljfJB z+E;@+W9!Pn7l&KJt&^)?k1ThvF}B{3iU-37FK&;l*0&q1d7jE0B-z~Ze+s!w A2mk;8 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/models/__pycache__/exam_template.cpython-312.pyc b/custom_addons/encoach_exam_template/models/__pycache__/exam_template.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f92e04cc60f54e54f259a6fa109ec76e8f3cdace GIT binary patch literal 1819 zcma)-%}*Og6u@`aYqS2sHpGTzNpYGqs%zqs@C* zXzWAkN;$v@EDn%UIktjBj`EC@7GH8Ig`8hM}*9orRV4w~2%4n_pFAmPe9=E?%*%ONb3MS&yX z#Y6zV8*vDWJK=4Z!&n2vdAM>vk2ZB1ABqDBsK^%sTmHj4CH90fpnU@byQ^s zyW-l8S*4Lle}suqe?INOcyH)%5~TCDVX=K_KYf03(K@ zIrT==B6i8OiDk1Gk?WXLya7FEsVXvDq^qb_v&+0 zm8dF>sVdw-S7&lURUd(a?w7ESfDseBVrey&s>LoP6(<*vMMcI@u>v=kM!$tUpW5u?!@J2o5yu_vE zwAcSZ^P9iox#jWIYb)0_Cx5=&jw{V6@6a;Qjt?_kULJoHmtV$ZPx{!ChW5ju3z7W@ zm&v~A2_aw>EX4=Myi$C&5yqLqMe>;-a4eV362y3w#hA`Pj6(yv;vfVm7dEf_RC-o= zo^7B1Y*!rc`YxsNpL+ERi#%@)E`WIJK8pG@bBhVQUHOQ)74X7%Y&klspP nc24|t>r+tKFTfszZa>8H{A+IbO=N)2!@48SM*iVI^k@DHCTGsu literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/models/__pycache__/passage.cpython-312.pyc b/custom_addons/encoach_exam_template/models/__pycache__/passage.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fcbdbe77bf9c27077d6fda78042777b25cf169a2 GIT binary patch literal 2385 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 VPorliJKq3GD literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/models/__pycache__/rubric.cpython-312.pyc b/custom_addons/encoach_exam_template/models/__pycache__/rubric.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a448d7cab02a00dbc34e1321d2d8235d74e60c1 GIT binary patch literal 1028 zcmZ`&zfTlF6rTNgd)yryQHhBJHe$04s}v*#Lt@}S6QmG~$u^sHXS`e3AII#Ta7W>p zP(TG%SQ;x0*8UA9RwNiM(`aHvck!^Ha%N{wXq@8h_rCYNH?#BJd@Gd(0A2g9zk8|( zz%SSOieq0Z>B1n%Ymg{2oahTXIu2lr!cSB2j|~ zB0nbTOAq-lb}#h+$eGjoLct+Gz!D&^L?~Di6fIc@V2e-*0$=06BWeO<9RU=&EH61tJ&)}A(AV9#w0 zBJNJ&%wKUM?1fdG$IrgfO;+i}$g$T#M8jyK;b8# zWC%DJFWv!;JHM5m?6rRt0+X+@$CdVUPzN$hi5G>K^_IwUH3t)!=}3MB z`N(B4qQvW-?-O|yZ6!pbDG9=!L-J_L3GAdCh|SBRpzb>fGWlGZyi1eyCT1g@ z8g}&9qh<$milgmH=h{Sj>1SbNcY1$jZ|2?H$2%tlvpr8^y9=kq(c|K1M;q&CdRLLg z)UFDKZ=C0((n!0~)j;{y?yLRnz3un&CqqX2QKzgQsHbK9xUByM@@=&T)p-l zI@GQxKJ<{BVk-xy;?RmyQ1S=#$PtN4DjBhwOOX(V-Xc;iIWe=g+oA}ib9npa&F{T= z^Y+dB8jnW+8{6OirhV-P;7>joj6h#GE-|G85I}+ss)8(3eX>sgKJYm}z6SvLv9J~# zIKBGrvv_>SVqGi-o^!S6qrs|)ux`^}MZ-F>Rc;;(v9BDT2z)~fWB~!$hXmP=e6r{R zIItEQz^}f@e<1EN4?g6ON2PkR*Ch%tF1YXO+2kRQ%e+qX^!>g`j-E-xJmRg>F_3^l z2jQ1{CH|Ki`VW`%xcupOD*#1)6uff|@=u?c-8qk#I2{c|4`MItm3bp7`$kmm%$!Ef zBu4A;VuB9O8>*?OtIHNv?r6r!oI+3|i+jc?yKkLRxj8+6@^dwu=j4r|K*I#D*EE9B z^Iup6SmTMd*1#mhCXKL-oxD-gbqqS1Mq&`2)NT_^E&90=R_rvy0cU~Ps0!zN)t+w3gZftINm zj!na5#i-Ai2BryJGwxsnd7Yq!=uq!yp1RCVt#W@FL0YAvsVwh0O?cN65^P&6GNz$V zO;g8;L1T&rSFnMJ;$TF>ie(XVgK0^2jU5}Rm^d1{(uk(|6pIX59dU)GHxyk%3f~K2 zLQG=+1de%Io)GD#jfpMQS)mMNwW=VAg?n(dfX zs363Wl=}Y-;=4)}I=E`-EJvyL&Pan^@oF$-)d_#8Ji+U1|HZ@u;Ks(A^X~9O^V%QL z^P98VrLEHAOWo*u&ClG}$mYWK;@0Bs^4_IxY?@)Iw_CwZv>n}vH?O*xvDQLovAwuc zZkFBbh1ORc*oKD}FaO-=X1{DMxv4P*C)>%x{PdGgx~T=`k}kAzzo!dN(}ll*I37F- zgLL-Aka#ZF{NgAAas?LSR{Pe@H_Usu(32DjlP3?A`3!{`t3r(%|TFgW*8F+fFL zS;8OaUb_X#{8jGN=6!DU=t-uXgfI7+w?rg1<_spmOzciPntV9< J4`8b2`7b^VnYRD{ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_exam_template/models/__pycache__/writing_prompt.cpython-312.pyc b/custom_addons/encoach_exam_template/models/__pycache__/writing_prompt.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee4a61bf1f0be4e6d221630bb951fc00113fe4a0 GIT binary patch literal 1730 zcma)7O>Y}T7~Zwl>-9%sJ0DI^lEyS8!X%0lBSnISNKn!eXbTdlkbD^}o{6(zKit`M zQoEw~&_g-ZRu68)p%LOxl>C7H2QG~;sx=poIQ15hAfcXkXFt-Q61Ah%%=wHckSnszGFz&yVbw(lr53e+77qD2e{L79*@W7KI;6=| zHw+aQKz0+BZ5QW@ivbB5Jo@=i32B(^r|48Rr^3!x~Kb`wakj}~nijWyTibS15g`$6P)Gt@}sx9gY)30ChlzAz4iUA9nwwBHb3cQ&$ZS&X4`ypt($$f z`FU^TY-_7?vwid4w@;*@-sseQ`C;Ng;)lL{X_(FgskoYtFo|cI@_&JM03%oU55P;; wI~;Y{vtT_}mb~ML4tN;_t%bkvt+!-(P&V^kC_40ZcdYUnYFJNB{r; literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_ielts_validation/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_ielts_validation/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0febde4f6b9111b8687588be0b74f42dbc3ae79b GIT binary patch literal 238 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_it/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_it/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b02f48fa5a052c2651d930126d82c6544410c00 GIT binary patch literal 246 zcmX@j%ge<81pW0_GgW}}V-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zT+aC^slmzlMX5!8noPI2lY!j$Vlcmm8K`6>!)K5|zf$x=i&Kk=^(zx|Q}YrtauZYZ z3ySiyQj<%HjSP&;^z&2l^TC9nrG8#&c|257Ke@EHBtJJkF(oBGuUJ1dFF8LkIU_!^ zL?38cS!Qx-v3`7fW?p7Ve7s&kHq)$ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_it/services/__pycache__/code_scorer.cpython-312.pyc b/custom_addons/encoach_it/services/__pycache__/code_scorer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cebb30210c4003c4f454890afacc99862b301e4d GIT binary patch literal 11120 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 oe7s&kPx# literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_math/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_math/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7a27c91d47b4ff5294c23c11213bd2698fecfb3 GIT binary patch literal 248 zcmX@j%ge<81pW0_GgW}}V-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zT)v4V8Ntc!)K5|ztZ$Wi&Kk=^(zx|Q}YrtauZYZ z3ySiyQj<%HjSP&;^z&2l^TC9nrG8#&c|257Ke@EHBtJJkF(oBGuUJ1dFF8LkIU^oq zi$2i2vdrYvV*U8|%)HE!_;|g7%3mBdx%nxjIjMF<96)P9jw}W-J}@&fGTviQE@A_6 E026XW*8l(j literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_math/services/__pycache__/math_scorer.cpython-312.pyc b/custom_addons/encoach_math/services/__pycache__/math_scorer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e8c7c01e35f981e09da4c22c3cb650a352b8e88 GIT binary patch literal 5754 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_pdf_report/controllers/__pycache__/reports.cpython-312.pyc b/custom_addons/encoach_pdf_report/controllers/__pycache__/reports.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5bd2aadcd5fcb00a69bbb7177344632cb85f5409 GIT binary patch literal 3151 zcmai0O>7&-6`tiTxglqiu>^ix)fEK_z#C5r9Ha#TCE{8z(pEfuYK=wi(oiKNI~ zdUq*_1Xa6*f$CNWDXIiT5EaeAfqYO;O@RV+Q6wq zqEg4{0z2=`dv9mn`)2l=`Lo~eMezLW&c~U1ZiN2EI`-qVl-*x|vW_sqTn;5o$t5}H zJ93UZpX51a<8wmZnRGUFA?M1ANipwEy7Qi-C+|&q^KHpC4ml9vvfcIsElK>FoY_kT z9Oxp#&U*;E2%jBj#n{>=Z$$=6Tul5Y>s*U*R7e{}0i>vr+eM-qF(>t9mkfz@GaA7( zAZ2w`fxcc)6`jyS645kOYZ(I4JTc6mTPiM5k5rK7Gm31Glsz|-qSe{G0m?ceh(VEb zKxupyApGA4bJ&4-EX;G*`M|Ylfl8cMyoWZeU|S|#C3nn2yQh_uDyPynNI}&M{hX>8 znwrZIt$a8k7cvRWv?s{2oKKw2D8?z-Fi5^&NEtkpDBwAbK|}>bRS4xTPS0M52~;pj z1wsY6Xr!r_Cq`PuIu%m7HkWc7$hi%4_U_KY80*M`jD2VJV4P*eTn}hjd#minqW#)d z_zIu3F+1R|aQ2d~2o)jgIpDHX8x`GWu#B1y!*bKgW9I+lmi5_RwdB`k>V!N3tyo*j z25qe+E6%U7E*wE<#Ra~OR-~(>=l$3l6<`y5pI?2%d$>T>`Av}M21ve_E; zVgLS^Z8%VA`z6Bu3J2|>x1B3K!y*9KO;P)smaKSj5VzxwiVxyLZ}W2w+-VHieq-3y zDqb5!Th2M=`3GJ0%rj^R8HerY7m@bLir;`$GoS2HTWd)iwnySnYah1euIy76j@YxL z95;aySNuQn&scJaTSCkHO|-3YLG2+($TW&vV{>V{9HKKEBQNfv? z11>QKb;>xOQRtz(tQ$m2sTxoNFjKkxmaLQbyrvcll3oH|o{9zm@&L9NzNr?YSZxlL zmKRA>PNj&hM-4Sz}yLymd)Y%)5R z$q_})lh+0*H&_nX@mGm5Z=@Ncr-_V-rkA_1x}@Y(8B5JXVD#vm3?Jjn9s?CpCqE0mGwMqlZqz-sJ%qlfG(vy~Tsfj2(u3}Y< z%NWCn5w{jif_W_v;_%I41~6q%!0BP(riIx&omQWi*_yBcDMO{~kSgTl6rujSyg*t< z5U(2=)~^&7q`K#tSKAG zdUyPt)}}rR4Lyz=u8y2~|6DzCrW!o+cd$>cO*TS9wa`!_bfgwKQV)%;p5KlP zG$OHDB-V%=t3{4&3BMJ8Bi14(S1&yYcCH830@cB(YH;dv#I>K?4n^45)xqQS(1{%< z@^|gH(F+6b47@dPf1=j&%IcNBcJ}?s{oa-4)Yq!lXX=sJYH;=+zT|fIi;eDyTKB~7 zNB(g1cSj$V>)kh2FF)xUYV^fxeep)$c&%^zFMVgWN{!yjwcg8*h92ql-kH^_+dab@ zxs4xgy|k6wy82M4My6LUK`mwl+rgeEohP@uMyv7j4}b9R$|JdY?0U8HyW3sE@9Gc6 z@0T{G>LaJBos&DF(9^N!6gvYuNc0E(z1M+)J)a{7py~@XeEl_Fe|6y1k9-r4Lxb;* zZ`}U%iTmUAP~u}>;y*i1hXoFtii`y}ahQO=nj^9JMuS_HOaw-fC(Xx>A+&?42HE)j*6}@_bDetPZ2!zLxGFzKUDmdKW*i>*I{w z&HP<#5=LMeyJTwYzC=B6VZGYq25pKN%?{6T+$X5*6BPIqb$yEZ|K)ISjxP{2up8U@R!17%-kP`f%}aIf@Lh4wb(9-> Q(|G63TX()dpf)G?FL5s?K>z>% literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_pdf_report/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_pdf_report/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..488f78005fbf4aa18ab54ea3dac00aeef1b60178 GIT binary patch literal 258 zcmX@j%ge<81pW0_Gc|zpV-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zJOL?b?x}gHMTsT(MShx0w|EOu(&E!$B1OzVWh)szgADtXqaRwFT2!oGnV6fJmza^8 zn4(`$l%JKFTvBXgU}UDBpOT*sCJZh0^HR&>p_2N^rNt%rx$%i9DfxND`l)%z`H9IH z@gRGOQVa5nO7wxImSrZV7VF2yXXa&=#K-FuRQ}?y$<0qG%}KQ@;s9C>a&9q*@qw9< Nk?|gbdJ!9t0{~9gN(KM` literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_pdf_report/services/__pycache__/pdf_generator.cpython-312.pyc b/custom_addons/encoach_pdf_report/services/__pycache__/pdf_generator.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..429b0ddf47f8ee1aa63aa8384cafcad2f8ed7f41 GIT binary patch literal 8788 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_pdf_report/services/pdf_generator.py b/custom_addons/encoach_pdf_report/services/pdf_generator.py index 4915fc78..349536e9 100644 --- a/custom_addons/encoach_pdf_report/services/pdf_generator.py +++ b/custom_addons/encoach_pdf_report/services/pdf_generator.py @@ -71,9 +71,9 @@ class PdfGenerator: score_header = ['Skill', 'Band Score'] score_rows = [score_header] for score in scores: - skill_name = getattr(score, 'skill_name', '') or getattr(score, 'name', 'N/A') - band = getattr(score, 'band_score', '') or getattr(score, 'score', 'N/A') - score_rows.append([str(skill_name), str(band)]) + skill_name = score.skill or 'N/A' + band = score.band_score if score.band_score else 'N/A' + score_rows.append([str(skill_name).capitalize(), str(band)]) if len(score_rows) > 1: score_table = Table(score_rows, colWidths=[8 * cm, 8 * cm]) diff --git a/custom_addons/encoach_placement/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_placement/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e88b4f69effae649dc3b19a512d7862349c0d822 GIT binary patch literal 296 zcmXw#y-EZz5P&C}Jz12q62Uic8>3eUf>>JG*=!SHGH@&TS(2Qxm5*TQGx#jlHV0>8 zWhY#Bm6PL~;>$P5%rN9*I^73~*O$-!md@{z{71Eu^(o047%MM3kGc>YZAt%USshC9ej?#T8!zgt(OovmB+eZLU@NY5jGFvp1P74 zl|!%QP8l)8@Q6C6+4<~J1QWs*7gxgLv)nxjy+}DYsf-Ce3G_NBJ(q)38fj1#Que;j kQl1Utrn#mS7Zz_~`Gm4|IwbsZ#@GsuR&e|UC$XWcKSOU%g8%>k literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_placement/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_placement/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0388c7f3818d71b62006adff96019d87f0e0cc8 GIT binary patch literal 244 zcmX@j%ge<81pW0_GbMoZV-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zoCP_F$*H-ic_n_DOt%<{n1RA889swF|H{)3Elw>e)~`$i$|q*zCZ^~Y6y;~7CYKZ& z85o)A=cnZ7g9$@R{k+ujc&Ma)a%pi%er|kXN=klSv3_b^a(-fRMm*di{p9?-lA`>a y9FW=Z@tJvl%+YeL|P){;mEQT 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_placement/models/__pycache__/cat_session.cpython-312.pyc b/custom_addons/encoach_placement/models/__pycache__/cat_session.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e63fea9893bd787e3dc2be693737f3e7983ef2b GIT binary patch literal 1726 zcmaJ?O-vj&81?MW?Ci1|*j=)aRG9BQrKIbbc1w z16eNJN;&jaP!A-hpqvtc)Es-PdhG?&jad28N+#rD+QSd%R$&eSH5wwK(Ev~*ga%bmswkyz<9>`Heye%kJ(cExUGDR-O| zZMP`^<#eEUqt$I|mH_H_te~_wMdl=N=l(~1?y+*RZfBqyXbabZsIzT%*)vsLZK_g1$_YEIAd>`mA7pt(E=*&L?S^4yI)Zc@W0WW%&Yo}ZkUANb6M zCU&sP210F;U^?tmOz1pMn2?$fVLi$(WuV8k`g6>h=|^SC9@y^YQ=I`tP;u*o(w zirIkc+qSNdq}Z>n@C3q((6^Z$m41XKv(_+ICxTWmNz-#GGA825$q-5&ECJ>xPD;Rz)No}r$ zq;iQs$AN?=ZZ(16Qfr}ndM*} zb-i^dgGA)gfQ+Y4GAnz@IdO9$>7L6~A!0t|ou*HSj7eJq@hRIA(oD#+Wy~P&2)h(J zJn^y1@De6Gx9Vdm!%+jebRA27#OComF&+BMqi_uy2r~E-9LvfP%l7q1(w!IJ4y<~asL!V9$2@|#f!&0A_da3x`Hag4z8 z!<8zLZ(C5wG}7myx(^!Z!P?D6{%URJkLuBgW#(UYisdejBZ4{lCv&uq;+$=AEz zuFW=b{hLGE*S4{f!yC^11Z%zL&`|T`wKRoAc zJn%Ebrj Nqx8e{-$1}%=D%*K#OnY6 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_placement/models/__pycache__/student_ability.cpython-312.pyc b/custom_addons/encoach_placement/models/__pycache__/student_ability.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..196d20064414252e88e573a20b1463b983019f29 GIT binary patch literal 1482 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_portal/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_portal/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83f40bca8f5c7fd0a02d76922759c690fea2df1b GIT binary patch literal 238 zcmX@j%ge<81pW0_Gev>)V-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zYz6s6C5btHnoPGCikN|7D;Yk6bpFcL4=qkDD%P(|%uUTp%*ahl(Jv^<&q_@$DK;`N zGSkmb$U#N>>4h%Nfb`FSNp`8hct wgX7~f^D;}~&iY0^Ao7V5^NWzsri)e(Av(v5rNM$5mH{ZpNIH{{S0 z0|aUMh#<|B^;3iN)H$mQTfV`Y!LXh;jX)*_?#Q^1=sP_tN3a*R*QnyF-H@+o9bdDG z&$S_6%R0VR6`y-UzBb^il(CSC&yyqG)eU)HCBp4|&FNG;9gB}iLJs1rT&OYl@9AGd z@iW~5!78t=8?wYtL6fsOS=;9Hq%NzQA?SUqB-R8mE~|;chvMG=cjGqIBdIE@z_?@m zyHP^!Cky@b0YO#|!#51_&Ukv7W~eCqq}XS+^i)KA5H|BBW_pUE`KIU;O-;pUDmn(* z9Gw!hIXV+df}Yc8jd%lBl}V`6h*BRr*&BfM2;ouV1uEb{TTXf&RT zF-$bd;OB-yp%0%Wx?W>|rfW7fNu^?AlQFVuicXJHahB7vB-kjB{+Pp4QqolIiG;?N^gvvdvgnF&`cUF12R=>&3S0E*v# zNIdZb=7XGP|MD9JPk+u_ax^Ty!8tmfbadXkdiUyb6W4LH*l~jEI8o?0RqS|$>v$!9 z>2jgtwcMGT{hV`4$yJxDc?wMt8Cw@kjV2hDqG=Qp-aIuuoJ_h1V{Doo z<1N>yVJ5*+amg+tFM;!p>nzBYTC&E~5{Q&=kvc(UWaJPZ3Z)`57S%(kiiY-6skJ#h ztMoo@)u07s$?6k2nI2@zJect%XppAVNMbY!@&l_1pPH$c7AO*rO|kK@SQNi4Izi3y zL?&3dcoBJicy~2%*d&M^T?=EOT~P40QHmA2;mtIaA}Km-pgs6TKXHwB$PGY849+%4 z99@TRYvfLVd6ddDRSHGLON2}2M^Jo7{3g({Ffl)o-_pYc4iy7Oxxmpv;KgF#EEhOi za&Et`e`?SN?K#J{X2Ko3@&5Jq^Q}E4XX}z<)u2COe@f`xj#WZ$bI<{3E>qJrL(z$m z**(-`ERn2OXq;?ep)WxN7P`C)nhQqE{-KCjDS-jy$Ixbra&ewpGsSI)Wx_V>c8qx2}LVW4$G(@8+e2 zEAv+t2bL}s>UP59^{<;eM^`#EoQ~0CA~nhzr@@3&Od#4&VFG^(mCZC|T(P}CEL|Y` za+P?Fc4=skqFox+8W$w1*K%-145K>I_|PQl(wsrH=xB+mF4COUXAPv~wqE7{?XwO( zla(pLu+t=!Vk2NLM-oYjx8NK_6C|%Y`VETH108QlCMFYXrlCp_$`kuQPwxOy-Xb;f zz@pMWd?PBMSv3E=K0yj%^1xV@5TOD31)!BpzNCS!ayO!^v{cGU)$4X_Aq9mfDeql> zujp#yTx~hy6K})9?)lxIYMl2_(R-Bh9xZrZEPBsy-ZQ1z;G%Dlyfb=hG+(nl@7!_! zomB(j8_LA&{Pm?^>zc{X2f}7RO*P1x+92bLO6a;q)3GGO8^@V+3RI#V zX9Epxg&5+(31avUpeUP(;pPT=P7lJPA#$XCwCqwCSViz;QJgc55_2ZOy8)9;n&FQH z{#b8Y=ge8dDdMgFB#1dn)}ketbJnbt(S730TE{iS5Z<(DzZpmSTy@Fg$r@*Lz}c5I zj-#!vy8iI?WH(1g{NcRgzN+rwmb8&}S*_-5S<^UTM%9(IY4?>ij|Zzr;TEX1pKH$Q z^X86p$Rm?~N#|`tc?LfDFC&pPF#!@I5d*#>U8EcQTC90UFRVS*e54;F0BWN~kc_&l zDWL-c5*WU>SSp=N zkIwSC5U-17EYRt2Iz0h+whz95H>SWf;f)D!Rp`U;AmcfE`uycrLl*_NS7?Mjg3nz8 z;>bd$#gWnINb`=D%e~Y6NEbM(>i%-Mdy`-&!cLXxMAe|Xu^9tHvAms`9!7^3tTTNa zpPG{CYv6+$z`4cP8de}q!Te86frmqP07ckdwy?bQvb0FNO{Jq6_Th2ff}?^C84R|;Es`$LJMycHuQ2*3Jr&Pv+0Z~MG+odba~$9WthBFj zp?AJF-*%Am^%Q-5oUgCo>(5zB{^o@X^B3|RNAlZx3;w>G?TO3#@pR5ua(i>8uj{rf z&z0Ib^G9AT`L`}#D0y2}n$~P4zddJNbrSxT{~>HPU+!ed7g*?@@6Vm$UA{%*9oyg8 zmdJaFyNP@0yXnIAo)z}1?I%la|AKYiy6C^taI4`?+pV@j!>-5f-KECXJK+(KyzS2UTj%cwmv?^N`B~=* z`{nExvtNGj#Rr8KFXk^@Ep)$GXnt$WVr=#Pjxc(Bs}306nxAmjeI0Dg@9cf_7UzDo z6x^BbKKXN~UM&S%mgZK{oO`eoY|3{Wee@o@U$vR)YICRI`#klFb$M4?-r6R*i1k{) z!^CDP!ve+GX$2p5GnCPGcEEqs!W9*&Y(SxxEzg{B0}919&6zf!08El?8Q_ujNX$w< zmJKKX&y-fISu?FCZ7CgT2m7tp3SP2?tSM{F+DON3)0{nPp)awB)WVguunN}6ZPE>_ zf@tGznX>$wwa6pP+DS9oh*Y?uMJ4U_-CHc9y4)swmx*-3T@CiIiHlk*1b`aYCFAg% zBkRyYD?|+KSrgn;&qJ^L4Rg+{llEqv=rl3ojE<*{n@ z04Qc6{on$lLkkxqJL_O98lftzbKtfC5H2{#8_`_xPBunk@R+1#s3h-3cX<|*0V5Q| zkzj6XnTfnb`~7!+A++bL?Kxcy+%u2Fb}zU^XflWB-o{{-KAm42cm6;CjLV7z{KFK>@iBeXa~It+wDYXSn( zop`$knQa0v14xsQnyrn+g|rI{GR96bykjImGw_w^(L@S!4Epp0ZbD3 zn*_HWF-C+*I}9cTZQ+y{0hn3(Aogh@rzfWvfG?I7VgM1%OxI`#>v?mWrqE}oDT9<4 z23*EwU&G=G7O!LR1{OF8!ccgpJT^!fF}&rX7`=!A1mkRR_z;t zl}z#qw8kVwtb*866;YI2o*OgQXKs#s{64@^uwh|ler7RM2=2)_OHD0z4&FML-?G2Z zbRci7FEupX3ET?gLoY0M6dDfYYReA_4SUtM%k71R{khs-?>KPl%F2vHa>AREJhw~d+h3ZviHE}jh{8H3>NmDyXnlg z?D@(adE#kW9DI24vF8Q(?c4dj^M$=H3j~}y@@q#!DZD3lezBQzZvTyDkd(8O;CW;| zvUK=^>$Z;_MQa0RZ78*dOHCmNpqlL8V(hePC4x=&cl_h72fOm;-{xG=yfrFk zJ|<_o$QUywMDP_6lal%PE)kP9maz(wVcL__E4g^X#7-2rO{}I-u$oE?1yUkiiX~ET zLVg1g14LC|zZBFczZrobeN<0cAKDa~X~-IwI#qa&>8z>?;t$EDy}Fr|cYLq$IyW9K zBqG$KHEuFrHQ%TIQG%>h&4_7}K3w0YkLRrke50F09K)<2TytjCdT5|K>4S8O5j+Mn z;EhpUNx+l3L6yk`K!{U9){OT8W+d3z=lOvlJ)J~_0C$Jhu%F@l*FumFhB z81IIWJb*|`wB5ojZ-c;UDhWwcvTX97)pUUZDVU*x1{BS2(4}9W2#T>79kAbEHZS9X zE@)^o8e>Bw#l#`g6M^TvDNO?=WgzGh_BW(_x|~dkDmoiBmJ>U?Mch1KAVd@UV8XU4 zM1gpN0zguug@`X!nj#Z41V2LNC~T>M4Bn%BepH$<0So9k7%lxi6bx#+gbE@ac%;-< zd9<0TJmflp_pqTsEi8Zx5u_vc=NrQJy90nF+IJCMkPHUxUf5u<=T~^55|0`^77p*b8y%L%{*) zM!FOmu3_IdOU??r!Lq&BEIn(1_yVkcMS9jYNYgM5n!y5fUC`)fmINv2AdOO(X|GZ} zMa!eZbb=ZI{}a4Ci>wQRx3(AfKp`=eCS>JB)%q{_E{gZ%G6 zv2n(AALrd)^d9EChYQ}`qW1*nJ)t2zD~B=XdQv0jdK|^ZUk@(BDHNN^q-$M;je}h? zW*QPj+JZC&s{8*#kVqpq1K=z?v?$PH*hHAE0{H!(3bX87%o$a%r{TPiHV|VYX|E7t z$2u{_4-nDmBdiH>+#-XWWNag`;Y1P;F@jM~avj2yWlvgY$f=_QLv$nXC1BfGkaLrk zoYOfVWf0j^aY0~Ro8m^pwvD7->RF(=iw&Z+_#x82dm!(8spR!79$qzx8ekB19jruM z^TN6LbNSGVoc~zSf12~3F8BwE{z1+^xK4v$Q?bsTvsD;f(3^%Wpf`fKt<;-F)Eg0z zyZRC-_J~*q|Dr#x-aS;T@Jru8c{bmh(8?dF4myC(`@G`|j9(>)=)Y85vfbX)8x{{r zpd?gXatq@aMOIz7Gm_N_xeYvFB+XKVa%lPJXyc9RZM*|oFQ?JP*+;3LhNJ;_bHc$3 z$=Tzr44#~V;5w|Mv&h#hsg3M;N%SOmPl+U0ezW+1w}=fgVXMm1!UPp>9;VaR7>L5D zcOhJ7cv~vXMn~YF2Pp*UqMs#c(Z|3bLdH+A_LoppYf(+b2 =D_$-m`_G^No$=H! zG|e|HUgbRDq9?+6A_dP2MNbds=~=NAJSX4?g{$ty-1WInJ^){&=-bBmwiSG^L$_Vo z&O5+)4;H<>oVT~&JzDgh;=HFywGE5=mTdW&U3us3W1X7qH-t*qgE2My11TCr{L*k2=m8Q61o?ZNJBZa!p`So%D9F&Yqc`b15%+@ zO^whs9LQm*13s1qC#yk0?BU{G>_1#OJBG#wHwYdx~nV z!arpYn!EfW_WtmGOq+bafU{W>Agyxx27*gK+F2MMs6B*9kV0fA5`x2c8e*nQYn7o; zzzg<>@Jxh7675WlL>Lhmd3#yp1s^oymfw$16geD=Ppmr{g6a~LVc9^VV<-&+LOz*m z{RYDp8Z8nFX!nMJ%Gl1O=sS@2hiVZ&zXV2 z-z09R?d5#kMPCnWs}(SKJI48rRdZAYX}#!YgH418&0@r}G)4^2jPmgYhu~?8nO1H8 z`nNENn_0gNl5xN(UYh##M+ww^@F^NqLS;7$zMOc;1gf-7%2w03@hSMH^nR#SgQyX?Te!4Ek6)aO!I31RN+!*eD*p%KO5Wp@)zePOUNB=!O z2tiSKs!u$DCN;6~2{bjqudtDJD8wlj&g>m8IfIK0pt3?#T5)JE?BlJ`C>|Y%MtOTQ zDtcj1cSfV{OvjSq8{wp>c)Zg@r>Efn_QBHl111n@x_V2Esg`TgB?CyG-R;8d*N{=<;LJkJj`Ck?I^!L3Pz$ zrm9&wvmB7xvXT07xm3Qx6-o7#;bl7YP$sIy<^@L7EwQD)BGV<7TdQHE>^rt!` zI|Dspef3hA?k0}x;G_MIO)stK>%~6L0v%LW_baVcP)Q?0Djb<#p~|~=+#gvv_;YCN z;+ozmHuegTL3OoRMb-&Dn)4T7I$m4T+eNx7KnK;;dKKNimFZgY}z{dZb#AH#Mzq`UnO5RHDgvi!C=lB{ioQ$l@qYEh@`QPA&G+WWL2v#0-=#VgV8>89oC^hF_`rp+FVI z`jv^fsd-XJRT~kpIlm8lAjx&n39s8 zSFE3!mz9~SdywAAD@|*SrQ+wS5Wzj!v^T0(wtPgB2J*KAXgT1 V1BnmJjEszT8AR?eh!wE|`2Zg@M{ocD literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_quality_gate/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_quality_gate/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2478ca39a6ef1a84be3ae41047902409c8b1cbb GIT binary patch literal 254 zcmXv|yGjH>5S-ZsIfR2t`~pojarA-%LHqL(|J8y1;vzQSBN9+TVS?6@mw#f2qxiX1T`YY!b zCh`;PhsF+4QUD}MQ4B|$(Dv{+pm$}2J1lHMBKBecTyzECbUp57m(?6RU*%anKD{av O`DwM*pXxXtRPhTCXGm@U literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_quality_gate/models/__pycache__/ielts_standards_check.cpython-312.pyc b/custom_addons/encoach_quality_gate/models/__pycache__/ielts_standards_check.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f395429734def37eddf4ab71e192b00e486ba58 GIT binary patch literal 1384 zcmaJ>K~Eb;6rQzrZR6UA#lfi}ik-TVvZ>^4b3m#>kP-?Nltz)DiL{5TCOd;!SnoPB zV^RB3SIVJ10qTKk+Dj7=sXwGABr2@Ev{FyGp^#p3>YG{HL8a;(-oE#}@4Yu~=I#7e zEanlc-EV*Qr_u=hC5_=S2FlqyCLoL$#sL5duWASXpMCrwh0ojNxyXRt{sY~rUSyuDXLiP{e0*gw^djtSF4I8pHGxBd8Q}|?)Z6ZUKoegbj$80L zAA0Maa!)NUuCA|DM?qB;wQgx~j?pJ=pHX7zaBbNZ<{UR@oV}kYfEl<={3tf=$Pd`# zJIoh;*l=4cYPLjo{9$5O?<*S^Mc$%#TT(pOVYj$8Fsln-T4`XI8xd<_;d+oE@NwwT zuDPV3>cR*D-o#_*60!vTV}^wvh24p}fIy-V0<6n8=& zInFMJf;K3N^Iim6C|sY!V{0^^o+QPEAuKvA3M6?WuF|u2qbQ&_j5G4wDT(!U`i+PS zl(C3GA%XoM&V7yr6@HV(=`h+E#8cv8@dBO6v3c9Ezvh&2y8}Ihc(aL#4R^Bz<@wD| zZqC{fi6SLF{mc&Oj=VVOw7oVLQPahQL?O2a6Qp|fMaOMGSv&cSZ8cTyXsTS*L%r2u z@nC#Bj^srDKf*D|Mh zWKO+#&$v|Xt)3Rp0tTN6!|Ii#K{p z{nE_d?7^-5TR-0Jt@h0-6sqi3o|k{Eyr`U5b4S+Pv3dKu7533^hxaTa*5y$!`C=tk zXM81}sicdVL>2oQXm4|K$so+L>tM=vhrbWvG_7gcAE@#sGpWr#EB`Y6)AZj6R2BIT Dh;ekH literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_quality_gate/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_quality_gate/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e9f77ca468f3e2893ac756d3a0a74df77f52f468 GIT binary patch literal 302 zcmXv~y-EZz5YFswaj2)g_yUVy^a?=`8w)$Z!seO~lEIB`k~7IF+xreagU{jv2n*VX z#dX4US2^+SrugQY%r`%o_wjg(k-hwUm@D$%IoMdSCW`|iuS_!yEweBM$h>F^TTV-0 zeOXs?AW03w?oB6KllsdB)dL24*-_plbV=OFgx7U7>^-g|Laj8Rq|$+firgDp5VED? zw-H0+y|n0LW2NS^;O|kTI60o2a<9Grhm$kz@L8;rTy-&dE2P%mMUGB+sT#2vm^a|m r_sJ-XTnOV#65?pqFGuIr>#oI%kgt*d61NF{O91#}hhJ7%Q6rNpsZP$+DIKKoF*eFElN+fP83l#|gQAmGi{;s!v$Ej5kW+%pn|_j1xZF!DtBXoP_fX^j^wL_u#7Gv zB5xuR+K~gB(vY<9pF+tSzRBl-A06gE-$oP_B!UVukqRLq7s6B_p-r?CWE3Kxho94< z4MmH%={ehSsO2o#b!O1ZxD#UX2Q=LIra9` z>yACG*J{jOrCvbs+iwKjf7j@?Q#4ErDFol)Pr$ZOQ!2xHl2{V#&u0YzTxv*;(v5CP zMDC7~WnY}ZCY)$Dz8vXF$7^?pO;nB@Tf5Qv+#b;r9P~s}KsWKx^q4r88!hQvcO2$M{6@Q}r4JXE@!Xa9xoh~N+2wgn zc0)#myD>(6C~(miRei>?A9KohwxI)Z^iowPS?GP48VQ{9W!Sn=!Z+%A1z>=S0IV$3T{R8LvjGS_>rAcTD&D{3(O39RdK6W;8~ zSs3Clz(Zu7AR?0x34bSdGbGfMm*6AH|Hyjr4iOSPy@M9ZGl51oTB8<$H+2c-ob)k; zxuZLEn0Npj!UQteFtBA!W}?Zivc^n@Y9ZDuTq$9S06^-1MR7~`Rj@u`j6;ozKh>MB zoSxdTHv`dp1sIGjJ-9vk)#%-ekJ7JiMcRq z#5%obB(t%&uk;^ZRTfadM|8kmkx^DOqZf3J7g1ULjf`4q5DNRp%{DES2S?#DA*Q+x5uZaj1M U%A@$?M)aS^m^A!10_GL^7akhNMgRZ+ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_quality_gate/services/__pycache__/quality_checker.cpython-312.pyc b/custom_addons/encoach_quality_gate/services/__pycache__/quality_checker.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86a5458a1669b5049d9a8805d969141a5e59daba GIT binary patch literal 6835 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 UXXka>|L_-R%J~wJ+8FA80hOw0UH||9 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_resources/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_resources/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..78503b813b18e947f35ece1be3e164a5ebc221d3 GIT binary patch literal 229 zcmX@j%ge<81T9amXNm&p#~=<2FhLog1%Qm{3@HpLj5!Rsj8Tk?43$ip%r6;%!kUb? z*mCnzQge#^G?{KO6fpzERx*4B>HL+XA6lGRRIFc_n46lHn30>9qF+#ypOuk zWTu~=lAjMI3@!EZQp@9^lKRP|#U=T<@rfxZ`FX|qsd>ryiOCu9MXAO4rA5i9#rpB_ snR%Hd@$q^EmA^P_fVP+Bq}mm60IdYMs2Iffz|6?Vc#lD(hz-aA0GIzhmH+?% literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_resources/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_resources/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3c53fbacf4e8d529e67c0352f6c3451587d9c0d GIT binary patch literal 249 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 asPTU2wQKYr?K-K`?3E$?A1E9rCH^-Ra2R3$ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_resources/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_resources/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0793c6c47e520c8faa77b4def4194989f11ec95 GIT binary patch literal 238 zcmX@j%ge<81T9amXNm*q#~=<2FhLog1%Qm{3@HpLj5!Rsj8Tk?43$ip%r6;%!kUb? zIEqq>^Gl18Q~flVZZQ-w14UOddnHiMj23}Sp>W@Kc%#~@b32IK$$JhVbO literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_resources/models/__pycache__/resource.cpython-312.pyc b/custom_addons/encoach_resources/models/__pycache__/resource.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e491e17fffd0bc4fcde63c0fb4a1adbc7765bb2 GIT binary patch literal 4187 zcma)9OK=m(8J>|wZwWmt%eLf)%o>OQBXEqD<>3Tl2$;t@JhloQc519{+v7+hZ_mgZ zy9lKN2fK2>+8ktWsIqsfQeg`YR4&=$?rD?C1%axhnoFok<-kpaHvVG0(@?7uX*}vwI&0daNiS`=Zdb}{gyz&)-dT3zq4EZAaMH{-SO5rrOi?CR}#Co9~- ziZWI^A39rni2W>9@6TfOp~yWh)xX@8=+^z`m2^%@&tJ!CE>F^UC4dd!2r-f16)X`& zR_5X+>1Kl0odkcDmkCA*8(ar*z(w%1;5=9AK zz-f)5*BcTELwbP04uof=d`4UGn;xq98A@Jps#uFF`Amkol~dr3V-2tPOq!Nkl+&=} zmNX3_MLl6wIcM;ktSFf1&WVNu7I>K_S&U>!!@8Hb(wH%;(UPR3nbi$x#RZW*l2_K#_8RE2Vr5Ae=)qvTpyJG|O3#e{BqwiC zZOLT`e39m}5=ufSX(-f@qa$O<9LnX`aO|U`fBv!B%Ggn_yTPuyYJc19ooY zemMe@3$Ml80SJrv3XCk~t#1St>0?$Op1zYd@&5xaL%V@BvnLqa*!U+NSzx72%YhXu ztTz_7iSVF!i-7|;ygd`P4{-p)n^Iv1SegdJ@v+yZ@7Z#=+uy@MTm zg9=k*F)JkObHl#S+ng4kJzA%^4%{|XyyY}6FuF~4^S9+RA28Z+v5A`c@O}EHM7Zj*a zx}YsDVx7}{W?>O2Kxl62?nVt4f$d_28YETs7$V)S>ef8T=+1db6=&rP*4;>+ot4wj z36}K$$`eVGbBdUimAnRImz3A$bA+DfX^6}SudIrT`I(HY&O`AAQM9knNoY8%AM9O9*A{xEJrn{GNX=z5BkrbqRC0U%q&^Mq#AagIlbS6rg?xI$T zRB571cVk7(L;1@oV0fC6m~G@EaGso`!znt@uUzsg7<4Oj-=2l$2xp(Ah%l4OWpsg_ zO3qQKyl=ZWxl|KI!@LtDwsWHoyDS@iICH|rj{>g9ah8{w_~&Hif7p>ofmx{soJIA3&Q zbZdNbyc#=Njvajxc^*4a_tT{S=L@ZmmQEB;d@;U3>OqQyIA7NT!O;9?f4zfZVNh!* zd=^bUyk765V1)AxYzx)+@pAlly^A8Uq+uy)_W)x1?}H_xbflE=`T-z zYpKU5*30=~4<@(6e~o<=d)_--@1tNp^S9cUEcYd!^__WgvOYlJ_#3JRDY*AF?(ruh z^$#dK#Ki_^RG5*q-gvclxZFEj>+aq1ZTe~_$Ezo&o}HZ97^+4OmZJx&(a~~rv=SYA zI(@y?)3?>L+4E|c9>aCH+~fef(rbwU-6^sJ7De4Hitt&Ghm00=uPA<&mohZ9VP<0# z01;NxL|&xVkO(w`gmd!}VcD&_ZotPFd=F075T<5;^3)S#YIXv`=6ZYF7odeMyT|#H9a22vRG`Joq4HO5S4vu`A zsst|w7 zs=>i>aPSpp`2ZAKLXN@|+@$XP>r17(#k2mS%_Kiw7QMg(Q_QKv+F}A(865IzScMPtN zmBx$X5BF6%jux)e{C%rS_wTOV-NqIF;ljmQWN3Z1q!g8hw3eUf>>JG*=&;wN$?^`=1BIGt$YMapTTFbwmCQ( zD?8!3tDGF?6kooX{KYUIkZiLjZ9dx~W- zs9>X-1!crM;iJ`ko}5oE1scRHF0Mqh&vN%E^dk2dq%sC$7B*^BdM2~Ro%Z##V5&f|D;eP7RIz0GLiry#N3J literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_scoring/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0e4b5839c4410e6136dad6c2fdc41c05d388640 GIT binary patch literal 313 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/controllers/__pycache__/score_release.cpython-312.pyc b/custom_addons/encoach_scoring/controllers/__pycache__/score_release.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edfd648bc0561df213540789b9896206fd2dfdf7 GIT binary patch literal 6703 zcmb_hU2qfE72ehE>R*;XMg}`FvLzcU1j*Q7enSJc!D$+k28RSEsYcdb8_AN^++EvP z$dG0-Q`6}Tc-pB=lMW{B3}nbmXV|ZfDShD0)TGVOm!7-Ym4uN^ zA9_bV_ug~wIeUN4ch2=+Y&J6m>D-yGqdnCW^>;`NA$)tCBcrK^nE(=kE&4G&4B*H6praY-71+8O`(zSP&65qP(=GS$qi~{>2FY& zp%6uuqF)D7V`4_Ntt{hdUdJ;$J4Ex`=lZMaq9Tqrd_-MU`)PTDCWR!DnM2)u2mP$fN)sbUX2YY>aoLbS(s6+oWi}$>!HBx?%2KQWYJtC{ zqbyll6D28ZLSnjNu~>*fujMJG?N3>Qw!V`(o*tqnnY6CbPT`g`6C+<=mdKh_mWWxG zb%p96qa9_MlI&W0nvRjVElWJhb63@QX;PEybEWjW;Tb7z^_Aj{8{pfku8m%DYQszG z(@dI8bG+$uvvy+NgKsro(QT^{d zE0~Uxw5S84V*%Z@&+5jm%KS>-Ou{{`+dwKeChpA-!@4JYCk7M7BNTK}{uZB$N??Gsiz-A5=dCADfj zd=%a`X_4BrdThH^D&>5YCJXmzhsKw7X{EG9Yv=9St%&H30VGXYPFs$s`8YjJon($t zt|%WD21g_QKny(9je(1g-1rPFcyx>CX|$-(nKiA%erV%W&sA!Lt>_6R*a_5 zLvmi9)S!Z442aSw4+4R(B%#EJlv)!J5+iXWAwCqAJUkL3fJ&Tzd4y%kZxv1%2@5Dv%Vg|6lZ8pNSE8bfg~*IX3lBFda3NZ~jpw+@rbm0C*>Qe7|4U^p5_ z{KLnvGJZEErdVcBa!h7NMVKlpj`D(RE-s}g>tTTbA!H^Bwx5Y6C7A(r*hB<%Q676p zfmLQoPB?r$DgnljSz~gzaT6irK;un>kVB09gph-a^+04(_sIwvk)lFUHiY8B&=8CS zR#4?(f(CHO5IcH1O*|Ok#ajGlt+Lc+id+OkQyYt+cpP$J)Tr;+5+w7?;UDtfq zgMSR>+PbrC-I@A>cO8cwI9=!Q%-HnU?BHB@p#~KAr@HQyF$WfE{EF5GF89pv^l+we zPu8_J=h~lj?O$+pP93^ezv+tMnrps#Udp`ole_hyvxld8&ZGO)uBq;P&Bi6lZgZYz z@{V;g)@f_LvFUR2rDl=^E(LOp?b*imyl>Ox-b=kX-;S(r#~t6x^KJR9+pgDrQ8z1I zJaysJ#nZnzeZ!aU*mZsQi{Uxv<+@9CxrVko4Q)4Ye*4br?|<<=Fx{8jxrVKG8n)hM zL0!(bE$iEsZ}#V!cV?S+mN>)KnPJoyLx92OiZ`)vx^*Rkg;s$iUzq zH&WG&`3?2txBdnAJu-3LswIl6wl7kg&Hnx4D$23ppOg-E#Olmh-C3(UQ{Q&i+J4X3 z`1|&`6Tj=Y(!Ssfer*l@XOV+mPecMLA0BEsw3+&9v#F;q+ zRw<9IHa`wV;VAXhO1LY{#nx)IQjT|4?qA6(sH~xqPc=qAHD3d7EX|iU@#eTSVVl&` zWX0U2v1ldmVDzz#TCJ38I{@RT;In}@Q11ISXmY%Tw?&J)t9SrK4@U6-3{uf|i4n`b zEIs7`6n9=CmS0I}gLZPB@c;~`4T=W<`BNSMCXU;aHL8L4Bn8PcD2yighra@Ih}S`5 zYNOT|6_s`k^)xTx;d$tq@*NXKJzEj@kaI5@qPvq*ITw|3~(IEDgzUJsVcQe1zo&_C|jq1E)GB$6Q4@f4`5*&LR&pL z32uR?z@4I6fw%&aZY8}t2x%uG7J^5C!6=IJB7Tip%)xx_8*+a-) zAbul$nUu*H!TSh#1&C}=ZAt-AbzOb96WAh&iZzJDT}nrFI;p1B(Ms)hfM{{UA`+xp z4|Z_{?8pN@Ih~yAUvRZf9m)fq?VH|r*Xg}i)129~d%km_=9P@&mAu_`?)2HynTGZ| z_I9PI=eBpDrZ?m0eXtS)+Fd!j=Z@Vo*LOMeX$UmuoW88nmve5)IyYUB{&42AGr8b_ zEc~1Y?$y1R+5F?ok)sQBZ)d9C{)e?KZ*`t~{p{=cT3>!+!^N=+V;`T)Z}eUqzcBvD zz}8hgrdXT(u@zupZub=_)3|NHxjkdu{`~{{`sFYXxN8lr2m@qmKiqHY@={+qY6;!E ze+OiL^8NtmO|Plj!`yty-(APtT1P|qRvia4<$Vq^5ZC1?NFc_WT*IX~4H95y3Q02% zlZ-@;yOJse=_*WAfPtch6+oa2CO9xdWE{(qrU78WrZp{t39gb+=UK&QmSmm+2>`81 z0eqQZozy>P&Zg&v;D)pzRt&Fj3KrmxXHp z5L}E5ds*VEczemDLts{?b>JQRno^5m?2AFNV(g7lF$9h^Xi}w|U#l5&&|2IJ$*c89 z8?|=csX>|=?io)T6=M&1nX#|#Rg69E0S)+7Aby=<;2{JguU34jRx|XGaFPJQ0PP8Q zu=`TBLh&iISc{1rUIrQXFyXyH2)T>}upm*mtdBq_3A0t8f<#F8O+tu2SP>CS%Md|k z$s?+Q3%HL69Rng8530*mKnCLFX~^IyK!d(8^px*;$e`FIkQW;)Vw^^lebo%JAC$VzP{;V>_Y6XJx4R%_G`VF_RefWSHAhJe69DM+jsHZ3-9LK zTe9vgId^N;-TKI)cLN&eZT3Y6WveEbF}ri_Sf)03*V_8P+3*~Am=*3?11qA#W>~8a z_t$hes4r_b5W4L^9b`8hrfwT^bA!Lz$lTJ=P`+j4fcE-LvN04Q;dm${n?s?5z>mgB z*%}I+7!Ah@ErrKk4hy4jR)|}Sy9qf;2zfUDj9LOpDSL~FwN?o6(#21Kd_*mpDZS%^ zzMu8~v_Io$x^i&d1%c75VGccJX#JM^+?q!^Ki9g%Q2Mn?9B>x(P+feFE|cn*KYF`4 zzhUF7ac-1I1r(_bWm17fJyaL>mI-a2KX@BHwM?k4T}}>4im8u9b2Fl}k$Q1zdC_ z{YZJjz&sfPalvGB>G8d=oX1I%GDhNAJu&Vr?9)Dc0;&X<#r;4Q8JecQp)B7}Ro_zU zzNOs%*6C>7cNCCCBV~DEYE#Z!mo?YT_AHp2J}^AikJ5DOT-W8pmkxhNk+SlM{{jvC BxW@nh literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/controllers/exam_session.py b/custom_addons/encoach_scoring/controllers/exam_session.py index 87eec2de..7466c941 100644 --- a/custom_addons/encoach_scoring/controllers/exam_session.py +++ b/custom_addons/encoach_scoring/controllers/exam_session.py @@ -369,6 +369,41 @@ class EncoachExamSessionController(http.Controller): _logger.exception('submit failed') return _error_response(str(e), 500) + # ------------------------------------------------------------------ + # GET /api/exam//status + # ------------------------------------------------------------------ + @http.route('/api/exam//status', type='http', auth='none', + methods=['GET'], csrf=False) + @jwt_required + def get_status(self, exam_id, **kw): + try: + uid = request.env.user.id + Attempt = request.env['encoach.student.attempt'].sudo() + attempt = Attempt.search([ + ('student_id', '=', uid), + ('exam_id', '=', int(exam_id)), + ], limit=1, order='id desc') + + if not attempt: + return _json_response({ + 'status': 'not_started', + 'scores_available': False, + }) + + scores_available = attempt.status in ('released', 'scored') + + return _json_response({ + 'status': attempt.status, + 'scores_available': scores_available, + 'attempt_id': attempt.id, + 'completed_at': attempt.completed_at, + 'released_at': attempt.released_at, + }) + + except Exception as e: + _logger.exception('get_status failed') + return _error_response(str(e), 500) + # ------------------------------------------------------------------ # GET /api/exam//results # ------------------------------------------------------------------ diff --git a/custom_addons/encoach_scoring/controllers/grading.py b/custom_addons/encoach_scoring/controllers/grading.py index a37f4ca4..108dd147 100644 --- a/custom_addons/encoach_scoring/controllers/grading.py +++ b/custom_addons/encoach_scoring/controllers/grading.py @@ -24,9 +24,10 @@ def _band_to_cefr(band): def _recompute_bands(attempt): - """Recompute skill and overall bands after grading updates.""" + """Recompute skill and overall bands after grading updates, incorporating rubric sub-scores.""" Answer = request.env['encoach.student.answer'].sudo() Score = request.env['encoach.score'].sudo() + Feedback = request.env['encoach.feedback'].sudo() skill_totals = {} skill_max = {} @@ -36,6 +37,24 @@ def _recompute_bands(attempt): skill = q.skill or 'general' skill_totals.setdefault(skill, 0.0) skill_max.setdefault(skill, 0.0) + + fb = Feedback.search([ + ('attempt_id', '=', attempt.id), + ('question_id', '=', q.id), + ], limit=1, order='id desc') + + if fb and fb.rubric_scores: + try: + rubric_data = json.loads(fb.rubric_scores) + if isinstance(rubric_data, dict) and rubric_data: + rubric_avg = sum(float(v) for v in rubric_data.values()) / len(rubric_data) + rubric_score = (rubric_avg / 9.0) * (q.marks or 1.0) + skill_totals[skill] += rubric_score + skill_max[skill] += q.marks or 1.0 + continue + except (json.JSONDecodeError, TypeError, ValueError): + pass + skill_totals[skill] += ans.score or 0.0 skill_max[skill] += q.marks or 1.0 diff --git a/custom_addons/encoach_scoring/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_scoring/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cedb307c117e3d3ff06561f47d62e3a5dc551939 GIT binary patch literal 382 zcmX|-J5B>J5QfM5NFqc42}A|-+h9n6goF?$prhHwGV5Wpuxm%QqbNO`firLx4uBMC zX%Gb+Qo2-(R|!*m{`}h-Ki-GKEueb-{-|DP{0fszMQd5!ki3Ed#cF6+&RFn>Jj$ca zWAZqUJ5R`yJn1|oPxF+)yqEQV7`4gRV%PbpLhXh09-E1$Xy-rDZibeU)D^}e$>0G| z-OJ*Md~dUDVohn$x!bI_02@+B)a*Z>wUgX8pdD94~l+li(E{rV3B3!J}C2x$v+HoN&U3no+C-c?dio$7) f*LIuE4bOE4gx{Dk*1~ZMM=k8PaQF!)HhlXZOe|?P literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/models/__pycache__/feedback.cpython-312.pyc b/custom_addons/encoach_scoring/models/__pycache__/feedback.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c9684a9102f22112253691bd07ab6d82699e8c72 GIT binary patch literal 1154 zcmah|J#5oJ6h1q)foRB&K6A< zg4CfKi5Rl7qIO_pWM?T-5z#FmF|k!@SvqkS$88uYZg~FQyYJrnp5NUUP0Iqd-oF0k zR73!NaVJ^w0G!S<&;<}c!3CaR2%cz&0uaGt0L483Q%I;Q$)U^dK`O?E)Rao{Z|;;t zs(1lJE}_b%gIq}LOFjTel2ah?f(RG_1cnF&BLzi65&@Fyx#0sbhAAjP8A^xBffPrK z^p)H+R1Y%;tW~}Ywa=S~yRc8Uq#+ zEr*H=%Z#Kl(ryMLQjQ41WS#Y)nx=1g$TVrzG}-(km*bpiZbz0o*pd4b7KDh{*lFUKoJz%wlf1E1)FA@s{Qeoc?Byq?G_H=3AV^}gXPl6_|OKrc7jTI^k$Yd!fnUTjZy z3!TEz%?F>WN7WZc$T=Rbw^n)+H`}+mdPhH+yZdSPcw(is+M6u2m%6K+)pu*HwVpP! z|NOf)^HrPask1$G@Y P?ai*+asL30`)B_G-pDKh literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/models/__pycache__/score.cpython-312.pyc b/custom_addons/encoach_scoring/models/__pycache__/score.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82867230a251d288d592d9d917da8c09e0f9227b GIT binary patch literal 1384 zcmah}&1>976d!3R0YMRC&BT$TkIhJH zdwt0ka_FsI0^NIVW%CF0*n2Myq{Pgng`Rpdb$ZFEZ$^?$AT;kV^LxMf&Aj*KY4lsY zZXvKAAO9Xat|0W6a7xn(aC!~E2oXe-5JifsM5?PQNJZ<2s80~7P-RCiH=WO8I8T^c z?N{5{-vYK(u15)>VaoOU0S!s&3%a!OkkiYG2uP8u5ag;vaVtc1t16<}j$Mk+XHp?m zqLJ!zeO%31*O1!Axu!(hh#1cl(3)el(AK2(!%}fRj|=Etc(1~KucH1x8P%RCW2jh| zJ0W%Ns?s7Cp4(?xPxkBW32v{(euDi68-Bv*L7nE_LMmNrbstA_`O-&cOIeT5I9tG3 zMx$=F$qgT;J|?tX;U=SxdI6(^n@J2^q8a5{0BFB$Kull9+OB9gj)z-oUXWZJtG4W()d5z({ z5=MBxfR<11GcTmOG~~5BZ8-5~bPCbX8{&MEQkFV>$T-FiB21hvOLibu+PTtMauSjx za#+0T#B|Rq79GErW=Z5>LXtRjid&Hpp_5MjnjM+eLbuPv6PAN0G5raKC+OJzc(8i> z!R+AnpUt_$>Cx!w+s z9;}{Bp{W_z)*7~+&VaPhI@Cw@(0)2GxcRozoIjj?)trCPoQFd`(NB>%Weje?eh90N zCWn(pb60*@e%V<2{w7;06TREkcvTe7#Q!R9jdn-;r1D}u6RcE!4(N@!k~jJqTLxFW g+Vm0(Cly6e{y?*@^-IdSa=0{F8Ls?`1eSaM13QmyPyhe` literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/models/__pycache__/student_answer.cpython-312.pyc b/custom_addons/encoach_scoring/models/__pycache__/student_answer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ce33a1f5547662fd9577c810b28a69d82191a5e GIT binary patch literal 1161 zcmaJ=&ubGw6rSDeCfhVAO)NEtHf=4!qI9)LK`8}=rl@T$rXpL)vg}OK4f`YA+0dpJ zBlOVHLz+|cq*qD*0FNF8FM(DFb5Zc*O{iXaa%MNNLTTsl=Dj!Hd+(chZ@wgxaX?q& z)mJmZ1Mq_x{U!F4lX5-pm@g4j621JF-$lHpiE1XKK8R9Yo@KNK!K)8SEEk zhEPCTK8c2RC9%h@Ya!hsaT9BX>v_oViI}rooo<*q5Q#l;d{janN%|%whAZ?1H5-#y z(b7vL1V4ZiS{j_%$_hpvR%(>Kqp#aKR4SfZrU~)P-I-a%g{~Wjdk+)`ZEC$k#i(N6 zwKW|=*TG8ftu$8KbV^D%{YtMzT1b1kQuEmC2ZCK3*QwY6-NaOVp?l?Ked&8@{9v?| zZDuU%j_SAv~MtPfX-6wRGJGLJ?~9YlZ`IUQ1L6maojhM{T+>Scizmt Nn|nL=2T(PL{0pijEfoL& literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/models/__pycache__/student_attempt.cpython-312.pyc b/custom_addons/encoach_scoring/models/__pycache__/student_attempt.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b5c4c3e9f7214cab618e246b99b65da4f06851d4 GIT binary patch literal 2410 zcmai0O>7fK6yEjk+OZw~5n4*H1ErGH5))TNqH=>E#5CZfs8A}osN2cT1U9U9&F(tE zR;9WU2YSL*4sK74IDrzW9CPfwm!PD=noBG7)LTU8g;U?`kDD}!vWNA1-+b@Q`#raepzzef*BFJq|*b!yM)nuF6;Vs;A=NIS+S*!=8s6_7Z*`Z2$kP zcx|NOYxr{hznPNr&_GqgL@{V!P9_RAq@7l-lWiZEb~(aTc+6Ein6G%Tr{eQ)#6KU| zX<*CPi+$LSeXD^LpN&+42Xcd0SPiXs9G+nDl6!r^PWzzq>AlR=@CxsE8#u_@iepxZ zSd3$Pz1-pOz!M%vAd6_fa50O0VlTVzFMcQ^aVR5sC?jX9gkY9{W=}r)xEbY-adWm*XQj6J$ZL|I%e_C?Gsl5C;QWK{6JP}2W!}375Dn; zN0m9yPkM)+Y~x67h#r|#B@Ib;ZUum3I;K= zYF$xsydHuCb36@VGKcDlnG3+-9*|YBrfYX#H={W)rDm@?3ao`Bty*I{U>cfmMZklG zr0KGHhX!xh0{ciX42S^+5ex`Kst{zbNI!QZK;t!{Vz3oa4YplCN;7`lMzR+jL}z1^ z^XLQcqYF$9vJGlF5z$yPa9t;7E{*}>L1Wb8NCl7z44Vb)lC?Su*d+^-0GqHd39yMm zsTu2+N;PG((HwI1es5G`k?1t+^hlI(Gur2{44ZLRog)O#BI({tZiEV=sG=$nMH&`G z_-xh{CPzf^ejO>!ir=CDh>0QTa?O-ARcBv8Doi7_QP5OE!%iHqFAcJGGC{bEOk&Da zLcOZC$T&!c-iXMgk$$I`7PV~Z? z>ay8iiyAe8?)BA(wm@{GD7Il(B6GT^kOiX9;3Z9iPOCH`8)8jC5~;%2(-6F%wk+}i zcNAE3|0%N#DtxArLKV`6Qd=blx`be)73YRdwr_QBcWy6z-J0p8 zGGJQl6qm-qa+i|MwoBb|r@S=Nn%=#V7-Lo|o?{)K?{6_Lr>snu1et#{znVbN`O>%wY z{917%@hN2IdRZQPetaW74o=b;2<=+u+R`)&%}IX!)JM<1-AG;jzN}BWC7;RpsgE^O zXa892)8n6Je^czXTxO`nE`jt$DB5RnT%Q7!-Tel;__n+}&;P+?UI$L|ll+gRpUXd$ K|KXTy+5QWpnP~t3 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/models/__pycache__/student_progress.cpython-312.pyc b/custom_addons/encoach_scoring/models/__pycache__/student_progress.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8e016670f5e3a57b21bdc83c090641962c5d6c6 GIT binary patch literal 1544 zcmZ`(O>7%Q6rQ!c>-Aq^J2Yy5G^Q#kD}=X1s0f5wB&e&DG^!LRl8Llh?M%}R>m7Gy zSJXZkDM&>eNKS4~jkuxo&|@!1y>l_DrCM_V332ExBIVK(Z+5*lmB<`s-hA(yH{W}2 zG{2Tgc?4tUucz*JX@vfin`EeCpoOROz~ zOFt=i22{>Yic^Z%uP2=8dN4Mdvk{{<^(5AWQHdC55`4N&7;_Qh|LRtLN&73EicuBw zmwboX&drS=#KaG-F}lSF=iQSe#_K$G)Z2-tJf_wr+=@e6ZI1*5TXs;xggf0F1gVFd zF#fs7IyQG~OpLV98Mzg@j9{TtAKnI>5vmK;?QV{?>kbVWCx*gukXQFaA|ZzB@R~x8 zbjt}0R{-B3U7eGl=7*kVWZ=~md>U9huo>v-7S?G{+lV*P=la$pk;1A!$pL)1Nfsja zNsoDjNY`F4v~mdIOHtRC#5 zW!(yGZ|qSc3V^a~%xwoQ^@V0ph6!Wxc?_D!*eY0g_6KcE-SM!x~E9Xs$DUGIgKQMjrjckB)noh_A z+Olknsn5-E`79~T^|#FU?=X{;ldjd<9VY*dXp;5ezreJEM#bgcrP17*y|q!P)@%Gx zsqN19m-d$SUwarlb_ZX6HLPs*u8hh{yIOyCZ+5@%&>faP?yXLcLGAs=#<08wQ1y-7 z<-WOR4o<)Ks5`7)>3udTE#A5Qw6yqJY4LBQE@_8(R9@TVNJ$c zg24r;iP@QX>8@poIi-mu`9*%3Ot*xJp`!7rFySI*poWzUpFzg{%G3`nPAw|duT0EM z%}dP4O-#`*D9X=DO)e=mGB7gJ&riwE2NQ;t`gy74@lZ+q&M4u=4F<|$LkeT{^GF7%}*)KNwq8D0NM<4buozX Qftit!@g9R=5gU*L0RAFPDF6Tf literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_scoring/services/__pycache__/speaking_evaluator.cpython-312.pyc b/custom_addons/encoach_scoring/services/__pycache__/speaking_evaluator.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7fb7240384877a00eae663bf946010903c8016b8 GIT binary patch literal 3871 zcma)9OKcQZ7JaWi{d4?fRaEv5JF;`fIUg@rd00t+%Bix<-97} zxTiaV5DRB9nk6t{6lOIbB83GDmND5x%4F2WL^d^y6e-!v&cP!Ek zZ)0~lED7ioBI0F4q}zhGCeI29xo{+Xdhet$Lm4HCIZ3q-^?X**Op}`C1kGE@l*t!p zK4WN^F;&wQld@?&L(SyBxSoNGtId_3YP5O?=2s9!!x#(|2p$$m5MGamB_dr$!!ijG z8D;?*B!SE5wx?q_1SW;;=0VSnlhaymO0x`B=>5N}e1A-bD=_6Z%BgpUlxbb7u{$}C z@vY-;<6{y2S2uvTf{M6^R2aE!7Tv-F32cirKb;V4$)vea7KA;MKc*AYL;-5^2}xFle3N>M1H7lo1^NF~wY8k|&V)PT=y{sNe?}ixtK3djCYVFJdBo zUJ1iNWHtJGup|3VA4DbTSDu%~oBb!My&prhx-$X^@IPNCMuTVv>Om%+f!m%(82)Ah z7sT^u2Jb)?4+W>~L@a@k)#A^`+x$_rCqdsQ7=h0=Rd@VR5&I`H!g+YJ)$Z?r{_c`o zqkoIPQ|(EpSn&l$BupY%WWD6?!=49iQg>bA`bnT9e=HAr{S2N#?!6Mx!oeY?<;@J! zN2sDr5#8`WZH>_yfG8e%23>q78IN@ULBrbhAy^7dnN-y#bz5K~1BF-oSO#*)8Pf$@lRz-&i!;5M)|pP{xq zGHX%O4)ac9Oq;bMR>f!Y40esB=r!3h%c?(_)DL-&NopfHET>YnCckfSP4p9N7;DP#?%bJX~k)b zqug$)zCd+!6t=G?hv&~Uz?0^;ATFX6DHbN4SlHnu-OLbw+{j>i6Y=94q!&F?*ozP}u6TZ-*j zi0vuwJ-!%AKZvFuH*VzT2Ay;LpY)g8_uo1DFnV}-^VXXu?v4Cy|JNUVb7&!U?z`x@ zUshy(@R`Z8;-xg|4WM~3%4OrW^igrXJIu#NqrkApxmPG3VZb%h=;S<`A2v95GD11L(Lex6|J*DM$6hcuR@meQ-` z$x+3|k;29*tk)7up(A}-@$w`m5Y9f@w5I2@ksO7@9W|yY12n25pvw-8Qc5^53tN1c z)IMBcpTY+3Dm9!m0A)#%XZ8QaG@K+fy+Sm*!R;>5G-R1ZsOqP7ww3R2E@uiC+qvMh zkO;YqQ164*VGO&GO^q-;qXL6llgj zvm-e}BkF`fXpVL81rZ?b;2^u9s2<_d>`qUdwD6+u@LFF`qpBk^J4Jl NzyVC~6U3#X>OW5~)CK?m literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_signup/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_signup/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbc7b805e415062ba5d7844a2e85c8cea8ce78d2 GIT binary patch literal 293 zcmXw#u}TCn5I|=(d$K5JC4zt8HW$4@5X92b&SskslHldoBulcZY~?3d`VD@IwavlV zSlJ2JUFGCBr+9fYnSo(Grqe^9czyY_cl3Ve95#sA3-Y2VcFxFI z!w|-@p8O!S*SI=xL7O&_RmsFBt4#JI6?`8<+nSi}>v9E=QF|;iCWLp`5Me9$15G79 zN@u)WIH`FT!_ufe%`fIxJm?U1xV+}xJd6D&S3~N96H@Eo6E|K3sTLyHM?Z922CG2xdX;u=oYaQX#jv7*u+KdDY# literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_signup/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_signup/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..966c95f2e78ed00ffc21a3665b19049fce51f806 GIT binary patch literal 236 zcmX@j%ge<81pW0_GlhZlV-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zEQzHh8Gf2fw-}0;fg&pzK7;iA%GM7pPAw|duT0EM%}dP4O-#`*D9X=DO)e=mGB7gJ z&riwE2NQ;t`gy74@lZ+qa y9FW2B@tJv#D`imu6S7ynE{*Yq%d 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 to EnCoach!

' + f'

Your verification code is: {otp_code}

' + f'

This code expires in 15 minutes.

', + } + request.env['mail.mail'].sudo().create(mail_values).send() + except Exception as mail_err: + _logger.warning('OTP email failed for %s: %s', email, mail_err) + return _json_response({ 'message': 'Registration successful. Please verify your email.', 'user_id': user.id, @@ -205,12 +223,116 @@ class EncoachSignupController(http.Controller): _logger.info('Resend OTP for %s: %s', email, otp_code) + try: + user = request.env['res.users'].sudo().search( + [('login', '=', email)], limit=1) + if user: + mail_values = { + 'subject': 'EnCoach - Your New Verification Code', + 'email_from': request.env['ir.config_parameter'].sudo().get_param( + 'mail.catchall.email', 'noreply@encoach.com'), + 'email_to': email, + 'body_html': f'

Your new verification code is: {otp_code}

' + f'

This code expires in 15 minutes.

', + } + request.env['mail.mail'].sudo().create(mail_values).send() + except Exception as mail_err: + _logger.warning('Resend OTP email failed for %s: %s', email, mail_err) + return _json_response({'message': 'OTP resent'}) except Exception as e: _logger.exception('resend_otp failed') return _error_response(str(e), 500) + # ------------------------------------------------------------------ + # POST /api/reset/sendVerification + # ------------------------------------------------------------------ + @http.route('/api/reset/sendVerification', type='http', auth='public', + methods=['POST'], csrf=False) + def reset_send_verification(self, **kw): + try: + body = _get_json_body() + email = (body.get('email') or '').strip().lower() + if not email: + return _error_response('email is required', 400) + + user = request.env['res.users'].sudo().search( + [('login', '=', email)], limit=1) + if not user: + return _json_response({'message': 'If the email exists, a reset code has been sent.'}) + + otp_code = ''.join(random.choices(string.digits, k=6)) + otp_hash = hashlib.sha256(otp_code.encode()).hexdigest() + expires_at = fields.Datetime.now() + timedelta(minutes=15) + + request.env['encoach.otp'].sudo().create({ + 'email': email, + 'otp_hash': otp_hash, + 'expires_at': expires_at, + }) + + try: + template = request.env.ref('encoach_signup.email_template_password_reset', raise_if_not_found=False) + if template: + template.sudo().with_context(otp_code=otp_code).send_mail(user.id, force_send=True) + else: + mail_values = { + 'subject': 'EnCoach Password Reset Code', + 'email_from': request.env['ir.config_parameter'].sudo().get_param( + 'mail.catchall.email', 'noreply@encoach.com'), + 'email_to': email, + 'body_html': f'

Your password reset code is: {otp_code}

' + f'

This code expires in 15 minutes.

', + } + request.env['mail.mail'].sudo().create(mail_values).send() + except Exception as mail_err: + _logger.warning('Password reset email failed for %s: %s', email, mail_err) + + _logger.info('Password reset OTP for %s: %s', email, otp_code) + return _json_response({'message': 'If the email exists, a reset code has been sent.'}) + + except Exception as e: + _logger.exception('reset_send_verification failed') + return _error_response(str(e), 500) + + # ------------------------------------------------------------------ + # POST /api/auth/invite/set-password + # ------------------------------------------------------------------ + @http.route('/api/auth/invite/set-password', type='http', auth='public', + methods=['POST'], csrf=False) + def invite_set_password(self, **kw): + try: + body = _get_json_body() + token = body.get('token', '').strip() + password = body.get('password', '') + + if not token or not password: + return _error_response('token and password are required', 400) + + Invite = request.env['encoach.invite'].sudo() + invite = Invite.search([('token', '=', token), ('used', '=', False)], limit=1) + + if not invite: + return _error_response('Invalid or expired invitation token', 400) + + user = invite.user_id + if not user: + return _error_response('No user associated with this invitation', 400) + + user.sudo().write({'password': password}) + invite.write({'used': True}) + user.sudo().write({ + 'account_status': 'activated', + 'first_login': False, + }) + + return _json_response({'message': 'Password set successfully'}) + + except Exception as e: + _logger.exception('invite_set_password failed') + return _error_response(str(e), 500) + # ------------------------------------------------------------------ # GET /api/onboarding/goals # ------------------------------------------------------------------ @@ -342,3 +464,32 @@ class EncoachSignupController(http.Controller): except Exception as e: _logger.exception('captcha_config failed') return _error_response(str(e), 500) + + # ------------------------------------------------------------------ + # POST /api/subscription/trial + # ------------------------------------------------------------------ + @http.route('/api/subscription/trial', type='http', auth='none', + methods=['POST'], csrf=False) + @jwt_required + def start_trial(self, **kw): + try: + user = request.env.user + ICP = request.env['ir.config_parameter'].sudo() + trial_days = int(ICP.get_param('encoach.trial_duration_days', '14')) + + from datetime import timedelta + trial_end = fields.Datetime.now() + timedelta(days=trial_days) + + user.sudo().write({ + 'account_status': 'trial', + }) + + return _json_response({ + 'message': f'Trial activated for {trial_days} days', + 'trial_end': str(trial_end), + 'status': 'trial', + }) + + except Exception as e: + _logger.exception('start_trial failed') + return _error_response(str(e), 500) diff --git a/custom_addons/encoach_signup/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_signup/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aed1645eb84132652d071d1a94297de25f8dc5ac GIT binary patch literal 269 zcmXv|J5B>J5S>{^A`nH0o*ZBs98yF=LL7mPCXHpS9b&ZhtZc8)RvdwnGjJAann=)4 z(IKTvl`(=>y!YlmZ`0`sFrJ^@-JJES1plc1%Z?QJc#5C!+d5z{N|m|?$`cge;i2kmXp8?TMzfd|{1LynyAORQJsI03sgw&YD|OKg`|&j=`_|sX WV?JA6O%tXcfruY)_6f6i#PI>+kV$_4 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_signup/models/__pycache__/otp.cpython-312.pyc b/custom_addons/encoach_signup/models/__pycache__/otp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a5b1e5c26717fe9a217cf68c3f4741f46c184e28 GIT binary patch literal 1060 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_signup/services/__pycache__/captcha_service.cpython-312.pyc b/custom_addons/encoach_signup/services/__pycache__/captcha_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95a1a4283a5a79ecf7a8ef948af5512b0580b3cb GIT binary patch literal 1734 zcmZ`)&u<$=6rTNIdmYCP*toHsNVrKr7zJ+{5K==6YMm5vAc`7-6j#-1wKK8TS?{_t zyK!wC(L)Z&0hNe@d*Hwk6#f7tE~Qs4X(EJKDiMiOZy`Yf<;2XcZCWFqdL}RWpQ5fdA{bl;4DQaZGb?LgP_PmZW|N@ z$Wtvggq-Nc3Tn;P%IXTjo4SUy?qQxcn+x=J7WejOaV?;D2BsPy$1UYJS3u?_4M!x% zSjQ4I5ayQ6o?G%NL72!5wTeu&Tvef5!&U`pHkqB7eOtDmWqIn-W!Xe^rE8QmhuBtC zQ6aQUA|q3?RIRKKy<|EyneNEKB(mm*t#lXiwT3Gxif-z*qBKXJPb%LtgjjfCs_ubK z;=+#jnRG@0crNK6UGS1#rX_5H7N{`FfIu!yS1OD*Ap2ds#kcrMV8BQrSBrFFva069-^3QM8d#knR-%TpJYH^kfH&pDO*eA=I zGtV4&gEm%>AeNUaVMJ=QBhXX!wy=(as;#;qTdyL^vE2}HG};&>CwW~+8`6Q68!pk3 zctv9y+;I@Gi7VDDV!L96Sf(pbf*W4AtD%~$TPF2p{ow|@&*BP;g=KfhkHD*})UTu9 zV8azzP;QWF$FK>zYT2$}7Nr~X3)f5zG^D@GDCB#p?t$Z2{C;`2d@wrwIQGWRvDwG5 z*`wH7J3=R!YTw?weK7gn!}w8herJgGZTsrp)q{)ge0S?8vA820M-rcZau}KD#0$HH zPBi%-a~PfM#NYJ6*kN?46aR3xaGXe;h*CKHBr(SPze;p6Q=RdPe*}c-*hvtiGJl4I zm&SJHPb6?5(_Y(K`{LHljZPxnp4*#ypnsh_O2`Mp^50KJQm23mr+=Z_33NOs>}~vE z{L1w-c$5xbe?@pS#ZkSK3$XXdq?c7u+#yA&TF^1rd{|NLII7`WFzYw`DplVAJj~{- zCYZfJo?;IOVe8xAROAAqXTi}x+9xtjE`T$1a7Ff(V%Eo){k{19ud`Wy&vWUDAHutM fni|;O14&Xvv*5U2!N_l5;;-O1mp%nld2asz*-^yJ literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_signup/services/__pycache__/otp_service.cpython-312.pyc b/custom_addons/encoach_signup/services/__pycache__/otp_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7023efea446d1ebbbef6a931863ace9baa3582b GIT binary patch literal 3473 zcmcguO>7&-6`uX&lA_2+6fIe9+*PZnqHKzm63b3vDTr-2DG)dToEE4qi!Em*E=BID zvrF3&Xx9fHe*dp-K!cK(<1*1U#K&Ikz)nAbVD6fki>!;WAx+xs>~jXE86gVwNq( zER;=}TV`(2%KP5*h3T1`OI??Xy6Uobp-(Wxxw zKqDU0%enrt(dbMruLPQ5*pBTR#%k)=n91f~4;~B8_JGt=r`F^@X-Ci@9mZl5xv>-) z8^muql@!}ug3ExaLQx4@?fhw@^R%(H2uSIs=A2uEX&}qUL8M@Mg_8aIK=lgd^u?J# zMVqM=L<`nkYA;%zpAi|tFVN6xlr?o@q(MH;;8a8} zc9D-dI2F<2E~4VL)Wm($Z}-G1DWYjzR25q@BtPC17SX;gD)w~^K)306Kh=~`d0S~} zT!q1VGVD9hlpcSndKx;#!Q+u;tEsby6S@e}MXJg)@|o1!Lm*Z07RhL07#~ z&txIOwy%Hq@ki%%z&*2c+xPTa@4uS`DCii%^E$Kq3Ul=3l4(1>b=RK^$UZt1vQJpr zPll~X*>)?{x{nCI z&dlzn=GL@&YH(xj@!XT~-PE}??T7T44dbz~mmaUB$9K~c+rRsYJ|YEnbN`~CUh53kxErzL85ReR3-Q- zRHc!sydW*gRHM=D*wcoc_mrx_2C7OCA=X8-hsJH;7}+cFmEKHZ_3azBL-mRiVvL@L zX2r88KsfI*ssqaOe8I{ubs$_Xn|{79$g&fb{{?c zG8rO`0*-a4i1{rsP)c^$_5%gBvKTuDvp&9&(T>5(MsbJNkl}5>#()9TEtBO7fpUl0 zzLil=1TL3w=cKXH&g4IsrL?ilHa_z6CbJf4sND43p?>&)#G}- z_w?o)Pf|Pa*AAk}s8mR^D);_+JAh9!<2b{=%H zEV4;p`*{3}d<+6M1p`66UGtXI287o^?BSwT)r#d!#|Y=IrrY9vJd7K8zXb-d|8HV@ zAc>b_&-?l@gbEL#h#@>s$t$P6O-^l&?G0yZ!`Ux|+VIqlHuV$n`w}+&|HY4uK5rq174Pp0df7n&Caw7T&h;i@1sc``_aGLTyXY$uGwCCT43BvtJ9fiFbES zU;QqA?LdMFJlZ!iQGDn+@Srw~AZ8e4msU#HjvK}wDrPB^Fnk(?MQ? z*)MDoFVpH30JcUp{tw0 zH%g?z-AQ2Ud=?rSjwP}8F6GCj-a)D*k_KY0uos7erl%}d>U3~X&x5wKOuTTW~>1gt<~{JW|a#ErLESoy;&hDkq%DabjE+6}n Sc_{W%BjN{Ke!^8cmHij|QAa)i literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_taxonomy/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_taxonomy/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef0f07614699b091c63fd966294bf4c0ada5713e GIT binary patch literal 242 zcmXv|F$w}P5X|0z9D-n_Z@9*&g&>Geu(PoVAqjYL$x0H@t9*i`Z}2VFHdokK*$LNK znTSrYJ2T7f?6uQrlYrClR`f%EMDa)RBTYAuGm%6>Ni?hgNR{O26M~&Xoq2vhgSuMe zNlk1T+zV;q?pxEPQ`XUnYi0Oab4j-rH%fRn9*!pzCE~Y?rqrlC`wgksIggrgDbYBp wj6g2d?4Lsg8gH>I<7vhUQ+UP(+v=UoG|FA6<~9rI@jVyGD+Pc%>Dg8gA2M!3&j0`b literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_taxonomy/controllers/__pycache__/taxonomy.cpython-312.pyc b/custom_addons/encoach_taxonomy/controllers/__pycache__/taxonomy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c28578dfb8f9db950e249f1b2cd932863b4aac0 GIT binary patch literal 9562 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 GsQL#PL0e=1 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_taxonomy/models/__pycache__/domain.cpython-312.pyc b/custom_addons/encoach_taxonomy/models/__pycache__/domain.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65826f19f6bdd78009600159685104502519c83e GIT binary patch literal 1657 zcmZ`(O=ufO6rNqJR;#sS$v<@y$&TGp8Wy=;+lN3&Nujmfx^?VB+)@^rWxX?w*O7Le znN@0;5>)WPKG~uN5h%pR6#LL)k3AN8iG#q)P-vj^kXwq|OHQ5HpGXPm9NxTn?|X0F ze(%lxmd~qzt=+%QoDWj~{K*f=O2^9iHKw!y1W>4gnqUYu(GUe7f=>VxcL7WxVN*_m zy8AK9$Cn{BBrW}vtC~pVng>ypP_0-Iha4`e?i+IEbIbfs8Q4gXnx+cJ5k8=o-BA2Nz5%qCv;*qb5&nHE5sj znbwwLLdW)ZF3$JP=TwiY$ciF2m}r7P$sH8-3mxU+lfjYp<<{k3_(FTJwHTBxJ<#v# zXQj#0(qu3?@nGft%Gv1j>F9J&9zQErPRo_Y<(Y>#7%8=Hw{HKP&lJ^XAd^+kSz55H z4O7K5Ig6%ARnugZ)~j64ndY6kRgFFA5WQJnB8++8sr2!Ng+qp^a@}$pvz&F# zHI-J;wjVN1GmEZ|ZXrySLHL2>+0ZWmgGqry++U%u)Tmz#^{QZ}td)$ziXwKSFZoM8S=BXZK$`F}gA vyTYw6zU8^{K}7jAJjEP*3dsc~o}~mq_ydgpBflZ2hYRhc*3!R#sbS=Q;QfY) literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_taxonomy/models/__pycache__/learning_objective.cpython-312.pyc b/custom_addons/encoach_taxonomy/models/__pycache__/learning_objective.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbc81cac26c23635d7813d14aa84b9490047f7e8 GIT binary patch literal 1801 zcmZ`)%}*Og6rWwM?PaksUqX%@2=pUh@v*U`My*msDj#WS6IwO2QdcUgWoLjT_O3H) zQ;bmXfl6>9s0V^n3Di>}@(1)!sMJe|kXVgWHB!|>ZnSPMoH{e!#ZHvW;mw=h@4cC~ z^L}Ih8jmZ0j?KSLt=~fc{K*!<2>VX$CUy1z1W?F>f}jZnQ4<9qf{y_dHvtSGVL1{c zHRdC_9~+ufkuu>I%*}`-Qg9&3yCkw;p*(a=1_vY9q$UgOKm;@a0!@U17J{NC!H^af z0g5cQ1qqEAN>F+lJ`(GQCiA$?1|N7ZLL;LzRz8yaScS*-1QCt-$al3Ek4QC`z*_{c zz%J?L6wOX1?yzsv1$9Ft!P_u1Y-9Mv_yu=@{nHZDe5E zvKK#}Uq)uhT0v_mRA$0E zrHE)`iRgPd>g5EL<>eaUo!nm=2yiIWa_G& zQ?m!w!E!UpLjVZcCotX@hEMT{qP_%PK?4~!!EeZaUF7TcWEHvXe&gniLGMEa%`fQXaVbaw1V;^ zVsIJJEfi$CW!gN)M))#40QWM(q>THS8DNHKmbOH4QGUT?H{O4a)vsKHUA00_w~eKO z0o5XQm^|IwwcK^pfsVsX_5;;M-|0T7nq{}-6m$bZ$97d;XnM(4tXlt(Py|L(43!y)*TOw=vcf)kSM{b!w`>lVdxH?Zk3L_*-r(+_*PYy(-ktW6 zmk;9m@zdncadOB@^&O1vkDjJRj#DFE`pRi~_&7cMES-If8Kv&4&r<5+FTI}B-o4#> ze<$R2GCPXHdI6MmN&rebc`q3-w8YyvMfRGsp=u2pY)@!smK=dC?k*LQAg-#C;WPoA`9 ztCL=$Z);^|V|(M##?RfqwEXtXwL*@j@58Hm!@I*jj8;GMItCv0oOTQxcMSXk zLT^WEAk-PHetIT@c9#5L`@!M-Ng_kD;_0ogcjmU|4ku6Ind+^Yq=c1vg{-)lOqfVa zNtiwQ`rU-@u>X;I?e8)4;(N~J59>F66TeRhrc*ab%~?nggg?NQeMf9t@jkN^Mx literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_taxonomy/models/__pycache__/subject.cpython-312.pyc b/custom_addons/encoach_taxonomy/models/__pycache__/subject.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff6b79ddfa0b10ac1dc061f4a0703d2e61e86418 GIT binary patch literal 1528 zcmZ`(J#X7a7(P-YMN^h!%dU`EHLMP8Kq$3p4*`k<8B#f|`{4kMn}G;IFuJo%MlY$BP=ygQ?jI{Y{?Rm(T51jy9lRjrO$9<5pFtOHENHNz{*63OQW^e$NKTu5!_P@D;uHSjH6Kt zr=6qn5vn{|k9}<53?4tuo>4Z5bGyhYwDaZ!&nGlhZ9Uv1^JXd=C72RVW3uM7 z8o^F(co6oRj_YwFInZ`7PuHRx1H8rp>U!(-go~&nAqVmNr{96;p{Hnbv>HJW8geX& zdh&8fDViXwjK;AK+5ZsRw!}b^Sc0nPK66Io3h3C7Oz!(?E8^fc)#kAFYTmQt+!alYYhxGWGP86+KJz2B3Ah%kf$5-7A3w`Y3@a-@=K}mYiZ#*4U03qN8Lw%X0!?871G9xQ`iTsm{VN0Z9$)H zbHldba;=8&$8Gy@%V{JPHG)9$0=c$NF`-mEI#)i}aOgRyTv;XCK}0Q2FM9!5CzR_$ zne+55-)|7di)iQi9gi$F9k0!eSh}ECMrUB#?-4D*L@x^?WE2^3AbSdC7lq@qouzQ< z?arrRcD8f-Wu~}y?cnR&804G@Wutll_$5ikK^iPP?3sfs%jVd)#l|yc+XfHW+W^A)0O6TzA&3oUQdH&ve z{wvhN_n4h{3KW(qPX~@{s1r zmX_tHq2P2;($~7EJV#x<=nr(5f@zpJ%AV8K3v-)5>ucoIOC&vSn~q_wE;%*J+{mEd zG~w}McF9hM7(o)ZY>3u3ve6aLsT!6|5~ksr z21IHMCulxIaVV^UJcJc`e9f9f6-WZ26{BA9HU^{c3No;5*^efihil06tfz=5JS*LT z8-2G!@5tTA>(X0f*TXc#42k2P&mLv{a`p!mZSVtFyXfT*0HT5j%paCIbn%T^!=k=t zjT-BM`G4X+g#7TGjFlo>djqoM<0%l!~`PK~kQh8#POZmg#Nu&tK?R+NkHAJWa{HM@19(N_r=^o$DwAFMA8^YprYk z<^J|UYr!8V?GNn@oeqqi42=54;r-dY+0)|0NpXT6PK#qF#j)Rulh3hV7;HaoJ^nkB z$S2=`L{IXJUJDl0%S6$2#-Xm0q^{FE>lLP_b^S@*sDz$4hfw1?JnIgI2xC@rB7L!H zV9qa5?ihAsigC`ECejjG_c-4qv0!`X5yC`?#*QRDcN{txHm?Oy?%HUoO2bJZnilc>%>FFD09>RS9$H1F(_Vqpeczof-XUEHKr{o<=gJ)7tJQ*a&a$8j6 zL}Fco*~|uH#qY2mdyx7lvz~v>TV*CF!7Lu94%U-yKNW9cf*||}hX0YT2+7^)_DpN$ JUqDqJ`5!~DllA}r literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_vector/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_vector/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd937586c364de206f8a98f0efd822940a600a8c GIT binary patch literal 973 zcmZ`&y=xRf6rb6T-0tOa7c>_W6|xuwx5%wYAt*tx2sRo-v`8W>o1MvJlii(TW-qx5 z7f4}YDhmq*TN{agLJF+~QA9i!Q>99Gcp#F>HjN=BgfsCx;H7l#KV{9rW6eU`yM%t!|k%C%k3!Qkima@{H z<(!^GZ)rQnEn(DD#!*tpyq6Il#t8CCndS5(eI)nRIL(}c+;!AY=g>N~&5g+i_1FsH zAPKzCTBCl#IH-g+g1BmVO9|x`OrsuBu!_VB!^(lgp5^i?Fd?%S?1E#Xa-WH0LSp>` zmpoSHKY zpVpFq#c6Kc<1wJvdaBZRjhiwm=Su7>NB3DhPK4YFOVZ(j^9ay|(}Ys7w;XxIsd2Uf z!xdB4rmj1TFxF#}H=IS!U!^f|{JKb3{$)M}8sI%y(4q9SXTzudHdbd-3)K z_5FDaeAd=d#O2m=x#qpQyg^+M5kCtoHKvcY=N2CURsH~C5LidW81JE>Jv7|yE8sjo G2gW~M9{y7R literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_vector/models/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_vector/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3bfb7339ee00deaebb4251d201c732daa3f61399 GIT binary patch literal 232 zcmX@j%ge<81m{F=Wl8|)#~=<2FhLog1%Qm{3@HpLj5!Rsj8Tk?43$ip%r6;%!kUb? zI8$?zQd3eg^V0n^nQk!@F$0BHGJFPU{*|O3TAW%`tY4X!o0^xHk(-#JUr>~vm6}{q zY-C_$rk|gZpARMsE%lQUle1IvQuLEci%arz;}cU-^7D%IQ}dGZ6O%LI%Yb_Fi}Z8z zQ&Mw^_2c6+^D;}~nR)QQ=3}Sp>W@Kc%#~@zB2IK$$+73Rd literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_vector/models/__pycache__/embedding.cpython-312.pyc b/custom_addons/encoach_vector/models/__pycache__/embedding.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54e2521d873e3bbd8c41365474ff3bf1b716e0d9 GIT binary patch literal 6331 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 G^8W?RjuA-! literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_vector/services/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_vector/services/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b814457531b4334f11b07b1f7cf1882a2a109574 GIT binary patch literal 273 zcmXv|u}T9$5S_UT#28Xoq!X;K$(j@aLHq5R2XE3YT-LQKJ-k10dev9A-9B5-@ z7f6@NIf<`$^WN}=H}9j-IS4++t((jI?#w@mlQ>+8cm)E&HF#VgcDfKIuEUK^Tst9weJpV>}15@`ltV#V59P zo?Xx8DpHJpG`&$vW1l&YvfErouMJTQS#hw@*p=SNO-$<4oR!utxLWJUrfJV^eWdN0 Y@6td@yLa?lF$T_D2a|!6O{3$Curl% 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 literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_vector/services/__pycache__/indexer.cpython-312.pyc b/custom_addons/encoach_vector/services/__pycache__/indexer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1fa885d690c0acadfcdfed9dd60bdc4cabbcef68 GIT binary patch literal 4449 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 i3jfJvri~f+WH89Y9v1DdDQ~eK}vpk0Y literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_verification/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_verification/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee2bf7d4edc0f0613b1e1f543df4a23aa016e643 GIT binary patch literal 237 zcmXwzF$w}P5JfY)AfgDidV_6@ZXpQb5$tSiLP#P;HW^8xvXw`$^bDTG+Q!1h%1*Ge zGAsIvnfK>2%$!@T28lZCFS;B1y)u6#KX|nx9El_n3SwXmK*}Ub9}veGT$=)Ia99+| z`DvD1iA!T}BCl%wt?10hfR@}S%a?{rx^}oyBKW+Y4=GB-ZyAiJRXg?zso3~{hH)v; ydaA5IE|zSooL*?bgGNgk(^dz@dh7CC9~+dLLQPyfUada!6+BY_xRH*lMe_l}{XwPx literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_verification/controllers/__pycache__/__init__.cpython-312.pyc b/custom_addons/encoach_verification/controllers/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6fda254edc06c6fc951547c41a76a0c930d6523 GIT binary patch literal 244 zcmX@j%ge<81pW0_Gev>)V-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zY-OoMnQ4`NnoPGCikN|7D;Yk6bp9&T4=qkDD%P(|%uUTp%*ahl(Jv^<&q_@$DK;`N zGSkmb$U#N>>4uq~O%i6xo&dHTuu zc_l^pIXNKXx@mF^KVjnURt49)m~`8;}D4 Dr-npl literal 0 HcmV?d00001 diff --git a/custom_addons/encoach_verification/controllers/__pycache__/verify.cpython-312.pyc b/custom_addons/encoach_verification/controllers/__pycache__/verify.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7cf933cda5d2cc6cff4fccf4668bf69e2b750ad GIT binary patch literal 3366 zcmaJ@U2GHC6~5yc|He*C?EE@^C5aQ0jVD0J29}})@9zP1H((?p9>mN=wU1&IFE&|ZYnDn#Z6Ee65LR1JRqDCp86380 zNA^A6x#!$-&OP_ubMId~9v6b|qaQs^oCfqa%9x+k0NcL+u!b_gF)-VUY>hzoyLD5TkK%Rm}pm%j9Z~C~C-})eA{Q$_O%1vQkDNT7y7j zS(0CML`{>F+6`v=6o55E5S?YjqDSm7WIG6Eum!W2i!s>xx$T~jFKoYw?ipGU>!Ks% z)LJGpQAv!(FAzB~w|G*@sIrtw5jo$*i`fK!P4DK9Dyp2w#E!&8B`!oIOpeKPni`jp zGDKsiC(loXIE_;mvqa;>oEq2cX`;p@tY}{e89kJB`rvL3mj!wmiR3o_vC3or> zLooBX#Z3PaTVOHU29hNX5T_$6AS*>lb6XfADZw^uzh_uovK6?bnaG_wju`XGgS}v% zKr77U4ES&q9LZghD>v`npVT+(4#NO540bL#LErs)Kjm~gyY&B0J1($O|KD~#M%Yzw z>aFWz^h@hfow~==N;aCPMhmuNQ;jnbt}}B`sQdqN_0+ z?}%`hLsW1V7<1JW=EE-v)?L@ljXk?(WRBgjqMjI9sxNpZ(B&|!X+xnt*=@#CqlJcK zPmMFt0;5=r_doynjNM>wSRn^MdaoCTLUVDb>>powb~?0XpmvVFBa z6PdovRe{3Q(2ffAp#6raQ=`xev-|F6+Q8mV?53S4%xD%ttou!EyazX$*`7tcNIhUm z`j9-j?JhMgqqHt zheByla`_fgEly!Y&0&&J!=kE^bXLuKUJ0U-O!B^j9F9tvxkOCJin0i$2MSog)X{5L zA}Xp0sJ04;%0$h#VlpS@QtEJ(ACAVwOpFYtNr=^KiYlr(MPt6NIb@O|qC&8SH0DU& znp5Y7$2FG`hLFHAJzh}Dt;z?9R7&Hnh#CB~kM`L$N7XS5b{p{v8Hi1Dk_9ncg&Y=D z0uJe5MRQ9qLQJIuYDIHJ$($^t$TgD62QJV$Y|NpDR^gtEr1s27xeQMH9Li_juRB|$ zmj_I%XHHC{2u{2JQK&7*VS^08|av@5xbQLwbkdk6CBGX(N zeW5)Xr;yYf1Y=%On&pFe`FnJz{djfbXx3TkoX(wY1I=Nqq@vjkB-5%T(~?B5Fhvn# zM03zNBM~5qN7nL)xMTkNxZO?bVmlFT3LS%(sgnVX1NFnC4vXmrIRXH$nV2qcr zBIg|5HW@)0dMSJp}LW(JD7)!Zrss|aXp8#i<;-P_0RWDR!@$; zZ+2Yk;n&ps5WDhk*dsU4mTkm2@}#kCZD@69-T!4{aQS4VxvkiKu+%)dJYDg(+-fNK z2bU+GHnkSp!lfp@+;q6qbhzRjF7iLvW-ZP2%Trqp)Y`pvef4^A;6yQaa6f8w5-^l@?&NG_#^)K%5>QuEct_F|Ij1<&;xmkMSD77?C|LC&;9P)%JkZ~)pKS4 z;3NOwgGMTA-?E{u{yUM|ky|r&nY(Y??Ye(;qiv(E*gmmhe-h}vGk$x#;%{F&vwCKI zVAH>^;t#ByT|K-0=B9t>NfmF~xsJwf9mvvo!zwQeU7-Mz%8cI+I7cs+f(Te zes=NGi@&;j-%{!8|7_;dnP*mZp#2-fwgt9W&;%zP`zn2dmBG-ce z_NZ@mW1xKGOzFrOfW;rqZuXonzWZMB!h6M@OO?GafG-aoEe#&61c%GP@ltU7QSjKt ziDwOtq2_Jm=xBM498E1-JY@F82?qIli@k3@=-u>972Q++{Ch*|b7X<#bo&&XdgPA zr)=!Q#?UE-efSmw_zT7g?b(n`a|n6?69mmA2x$rDQUtJD5U%FL6fGixP< zJP9s-i?*Rf@&s+@vr2Co04O{(H_?_0*}ON-|1|RBNYOiT|5~Lfuuj%5-aqt$Wo$>D zar>uzAwp z%}Z|*^MHk~K=Id0l~IDAe9q{VN1mcC4^fw{+N-%btipJXVJvVO>N=JO%C11k6}WY3)75{&{=zoSjNHO^ Mq}$Rr2%zraKe%T)HUIzs literal 0 HcmV?d00001 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..828be3bf --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,32 @@ +version: '3.8' + +services: + db: + image: pgvector/pgvector:pg16 + environment: + POSTGRES_USER: odoo + POSTGRES_PASSWORD: odoo + POSTGRES_DB: encoach + volumes: + - pgdata:/var/lib/postgresql/data + ports: + - "5432:5432" + + odoo: + build: . + depends_on: + - db + ports: + - "8069:8069" + volumes: + - odoo-data:/var/lib/odoo + - ./custom_addons:/opt/odoo/custom_addons + environment: + - HOST=db + - USER=odoo + - PASSWORD=odoo + command: ["odoo", "--config=/etc/odoo/odoo.conf"] + +volumes: + pgdata: + odoo-data: diff --git a/docs/06-All-Credentials-Inventory.md b/docs/06-All-Credentials-Inventory.md deleted file mode 100644 index 3a62c046..00000000 --- a/docs/06-All-Credentials-Inventory.md +++ /dev/null @@ -1,190 +0,0 @@ -# EnCoach - Complete Credentials Inventory - -**Extracted From:** Cloud Run service environment variables (plaintext) -**Date:** March 8, 2026 - -> **IMPORTANT:** All credentials below were found stored as plaintext environment variables -> in Cloud Run service configurations. They are NOT in Secret Manager, NOT in .env files, -> and NOT in the code repos. They were set directly during deployment. - ---- - -## 1. AI Service Keys - -| Variable | Value | Service | Used By | -|---|---|---|---| -| `OPENAI_API_KEY` | `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` | OpenAI (GPT-4o, GPT-3.5) | ielts-be (prod + staging) | -| `AWS_ACCESS_KEY_ID` | `AKIAXXT434IN3J7YQQ66` | AWS Polly (TTS) | ielts-be (prod + staging) | -| `AWS_SECRET_ACCESS_KEY` | `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` | AWS Polly (TTS) | ielts-be (prod + staging) | -| `ELAI_TOKEN` | `KtzxETdcZesZtwl7JKiYQapRvp0b4zMG` | ELAI (avatar videos) | ielts-be (prod + staging) | -| `GPT_ZERO_API_KEY` | `0195b9bb24c5439899f71230809c74af` | GPTZero (AI detection) | ielts-be (prod + staging) | -| `HEY_GEN_TOKEN` | `MjY4MDE0MjdjZmNhNDFmYTlhZGRkNmI3MGFlMzYwZDItMTY5NTExNzY3MA==` | HeyGen (legacy) | ielts-be (prod + staging) | -| `ELEVENLABS_API_KEY` | `sk_01190f3d023f6abe585d2bae06557cf4e4b9e1cf257d4732` | ElevenLabs (TTS) | ielts-be (staging only) | -| `ELEVENLABS_MODEL` | `eleven_multilingual_v2` | ElevenLabs model | ielts-be (staging only) | -| `TTS_PROVIDER` | `elevenlabs` | TTS provider selector | ielts-be (staging only) | - ---- - -## 2. Database Credentials - -| Variable | Value | Service | Used By | -|---|---|---|---| -| `MONGODB_URI` | `mongodb+srv://user:JKpFBymv0WLv3STj@encoach.3ydyg.mongodb.net/?retryWrites=true&w=majority&appName=EnCoach` | MongoDB Atlas | All services | -| `MONGODB_DB` (prod) | `production` | MongoDB database name | ielts-be, ielts-ui (prod) | -| `MONGODB_DB` (staging) | `staging` | MongoDB database name | ielts-be, ielts-ui (staging) | -| `DATABASE_HOST` | `34.77.91.43` | MySQL (CMS) | encoach-cms | -| `DATABASE_NAME` | `encoach` | MySQL database | encoach-cms | -| `DATABASE_USERNAME` | `root` | MySQL user | encoach-cms | -| `DATABASE_PASSWORD` | `VN*n1yVLxswU` | MySQL password | encoach-cms | -| `DATABASE_URL` | `jdbc:mysql://34.77.91.43:3306/` | MySQL connection | encoach-cms | - ---- - -## 3. Authentication & Security Keys - -| Variable | Value | Service | Used By | -|---|---|---|---| -| `JWT_SECRET_KEY` | `6e9c124ba92e8814719dcb0f21200c8aa4d0f119a994ac5e06eb90a366c83ab2` | Backend JWT | ielts-be | -| `JWT_TEST_TOKEN` | `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0In0.Emrs2D3BmMP4b3zMjw0fJTPeyMwWEBDbxx2vvaWguO0` | Backend test JWT | ielts-be | -| `BACKEND_JWT` | `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0In0.Emrs2D3BmMP4b3zMjw0fJTPeyMwWEBDbxx2vvaWguO0` | Frontend→Backend JWT | ielts-ui | -| `SECRET_COOKIE_PASSWORD` | `S2NrN2aBBYCpFpULvK2vDPFwsPbixAH6` | iron-session cookie | ielts-ui | -| `ADMIN_JWT_SECRET` | `aM9l2NPCbOlIBBfGfWAJAw==` | Strapi admin JWT | encoach-cms | -| `JWT_SECRET` | `hexTrI8hLY8k5syUSucXcg==` | Strapi public JWT | encoach-cms | -| `APP_KEYS` | `qLCKRYNICu/zsCYF566pEQ==,SbgGbzHLzVih3yY/bCvG9w==,xJ27/S+YudYyftTuqPRG8g==,dMDRY3LHbBOLavygMJIeNg==` | Strapi app keys | encoach-cms | -| `API_TOKEN_SALT` | `OWtKC1U80X18NIFBUpJV0A==` | Strapi API token salt | encoach-cms | -| `TRANSFER_TOKEN_SALT` | `qTWhsKJZK/Z2X0hDPtvCPA==` | Strapi transfer token | encoach-cms | - ---- - -## 4. Firebase Credentials - -### Production - -| Variable | Value | Used By | -|---|---|---| -| `FIREBASE_PUBLIC_API_KEY` | `AIzaSyCdD3xqz5-25ZuRU_Tm2W7tBY9FtWCIfRU` | ielts-ui (prod) | -| `FIREBASE_AUTH_DOMAIN` | `storied-phalanx-349916.firebaseapp.com` | ielts-ui (prod) | -| `FIREBASE_STORAGE_BUCKET` | `storied-phalanx-349916.appspot.com` | ielts-ui, ielts-be (prod) | -| `FIREBASE_PROJECT_ID` | `storied-phalanx-349916` | ielts-ui, ielts-be (prod) | -| `FIREBASE_MESSAGING_SENDER_ID` | `785091389226` | ielts-ui (prod) | -| `FIREBASE_APP_ID` | `1:785091389226:web:77cab7f4990c76aa0d2053` | ielts-ui (prod) | -| `FIREBASE_CLIENT_EMAIL` | `tiago.ribeiro@ecrop.dev` | ielts-ui (prod) | -| `FIREBASE_CREDENTIALS` | `/app/firebase-configs/storied-phalanx-349916.json` | ielts-be (prod) | -| `FIREBASE_SCRYPT_B64_SIGNER_KEY` | `vbO3Xii2lajSeSkCstq3s/dCwpXP7J2YN9rP/KRreU2vGOT1fg+wzSuy1kIhBECqJHG82tmwAilSxLFFtNKVMA==` | ielts-ui, ielts-be (prod) | -| `FIREBASE_SCRYPT_B64_SALT_SEPARATOR` | `Bw==` | ielts-ui, ielts-be (prod) | -| `FIREBASE_SCRYPT_ROUNDS` | `8` | ielts-ui, ielts-be (prod) | -| `FIREBASE_SCRYPT_MEM_COST` | `14` | ielts-ui, ielts-be (prod) | - -### Staging - -| Variable | Value | Used By | -|---|---|---| -| `FIREBASE_PUBLIC_API_KEY` | `AIzaSyB1HDuvYOX18ZxpSgi2PmmVOaUu49CNYws` | ielts-ui (staging) | -| `FIREBASE_AUTH_DOMAIN` | `encoach-staging.firebaseapp.com` | ielts-ui (staging) | -| `FIREBASE_STORAGE_BUCKET` | `encoach-staging.appspot.com` | ielts-ui, ielts-be (staging) | -| `FIREBASE_PROJECT_ID` | `encoach-staging` | ielts-ui, ielts-be (staging) | -| `FIREBASE_MESSAGING_SENDER_ID` | `1078696515702` | ielts-ui (staging) | -| `FIREBASE_APP_ID` | `1:1078696515702:web:b8a5518dac09cf6e366757` | ielts-ui (staging) | -| `FIREBASE_CREDENTIALS` | `/app/firebase-configs/encoach-staging.json` | ielts-be (staging) | -| `FIREBASE_SCRYPT_B64_SIGNER_KEY` | `qjo/b5U5oNxA8o+PHFMZx/ZfG8ZQ7688zYmwMOcfZvVjOM6aHe4Jf270xgyrVArqLIQwFi7VkFnbysBjueMbVw==` | ielts-ui, ielts-be (staging) | - ---- - -## 5. Payment Gateway Credentials - -### Paymob (Production) - -| Variable | Value | Used By | -|---|---|---| -| `PAYMOB_API_KEY` | `ZXlKaGJHY2lPaUpJVXpVeE1pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SmpiR0Z6Y3lJNklrMWxjbU5vWVc1MElpd2ljSEp2Wm1sc1pWOXdheUk2T1RFM0xDSnVZVzFsSWpvaWFXNXBkR2xoYkNKOS5HMnJTZXJ2WHR1UUEyNWVQN0tvTDBHaHJaUmM3VWx5RHhmV0huRDRPbkZpVExyV0xicnUzeVZSYXk2ZENqTnpXS1duWmJoZ2RYcUgwSGxnWkNUTi1aQQ==` | ielts-ui (prod) | -| `PAYMOB_PUBLIC_KEY` | `omn_pk_live_BkKVov5VSuLtTIqgcfya39ucEDcnX35l` | ielts-ui (prod) | -| `PAYMOB_SECRET_KEY` | `omn_sk_live_a669c50ebabb3d5c88135eee070a507258a7d10522214de89c123a4a5b25fd22` | ielts-ui (prod) | -| `PAYMOB_INTEGRATION_ID` | `1620` | ielts-ui (prod) | - -### Paymob (Staging / Test) - -| Variable | Value | Used By | -|---|---|---| -| `PAYMOB_PUBLIC_KEY` | `omn_pk_test_Oh9XcYe589i5FqXHLZ7yZGUkF2M8Vf55` | ielts-ui (staging) | -| `PAYMOB_SECRET_KEY` | `omn_sk_test_ee1e6e3f149b481f9b943334c680b7c3fa27e8f1800e111aae45cc829c92f8e5` | ielts-ui (staging) | -| `PAYMOB_INTEGRATION_ID` | `1540` | ielts-ui (staging) | - -### Stripe (Landing Page) - -| Variable | Value | Used By | -|---|---|---| -| `STRIPE_KEY` | `pk_test_51NzD5xFI67mXFum2XDMXiLu89SbCAMY5O0RnKjlU6XqyfboRVvFHI3f5OJHaxsrjjB7WqDYqN7Y3eF8mq3sF354F00l30L5GuJ` | encoach-landing-page | -| `STRIPE_SECRET` | `sk_test_51NzD5xFI67mXFum2Lzi2JtR8Th9zuA3CnoKKkAaOBiHmiHDQdGt7Pruj1Z89e4nF5eVNStL866twJLoVBUgfiaxZ00yqst8gkh` | encoach-landing-page | -| `STRIPE_PRICING_TABLE` | `prctbl_1O0hFcFI67mXFum2kEqiD57r` | encoach-landing-page | - ---- - -## 6. Email / SMTP Credentials - -| Variable | Value | Used By | -|---|---|---| -| `MAIL_USER` | `noreply@encoach.com` | ielts-ui | -| `MAIL_PASS` | `sovlwwwqvnenladl` | ielts-ui | -| `SMTP_HOST` | `smtp.gmail.com` | ielts-ui | - ---- - -## 7. CMS / Strapi Integration - -| Variable | Value | Used By | -|---|---|---| -| `STRAPI_URL` | `https://encoach-cms-zrwipjl2nq-ew.a.run.app` | encoach-landing-page | -| `STRAPI_TOKEN` | `1adf65151d6c8bf7491f4162d504dc9063ae750399fe8d4c841af20d2b3f8a3fbc6206ecb63bb9e9cbb9a00baac73a8547772ab0f16f0f7d04f4201f04ef72f9a2cb37fbadf5c347d8243a6733ac21589364e76b2fb5309386cb5aec52244f633b26d04faad5aca355df728200c86089d65e4162658a5b37ec1a6730d36fa383` | encoach-landing-page | -| `GCS_BUCKET_NAME` | `encoach-cms-media` | encoach-cms | -| `GCS_SERVICE_ACCOUNT` | *(base64-encoded GCP service account JSON with private key)* | encoach-cms | - ---- - -## 8. Internal Service URLs - -| Variable | Value | Used By | -|---|---|---| -| `BACKEND_URL` (prod) | `https://ielts-be-zrwipjl2nq-ew.a.run.app/api` | ielts-ui (prod) | -| `BACKEND_URL` (staging) | `https://ielts-be-zrwipjl2nq-zf.a.run.app/api` | ielts-ui (staging) | -| `WEBSITE_URL` | `https://encoach.com` | ielts-ui | -| `NEXT_PUBLIC_APP_URL` | `https://platform.encoach.com` | encoach-landing-page | -| `WEBHOOK_URL` | `https://encoach.com/api/stripe` | encoach-landing-page | -| `DATABASE_URL` | `jdbc:mysql://34.77.91.43:3306/` | encoach-cms | - ---- - -## 9. Application Config (Non-Secret) - -| Variable | Value | Used By | -|---|---|---| -| `ENVIRONMENT` (prod) | `platform` | ielts-ui (prod) | -| `ENVIRONMENT` (staging) | `staging` | ielts-ui (staging) | -| `PDF_VERSION` (prod) | `1.1.0` | ielts-ui (prod) | -| `PDF_VERSION` (staging) | `1.0.7` | ielts-ui (staging) | -| `EXCEL_VERSION` | `0.0.1` | ielts-ui | -| `HOST` | `0.0.0.0` | encoach-cms | - ---- - -## Where Each Service Gets Its Keys - -| Cloud Run Service | Region | Environment | Key Categories | -|---|---|---|---| -| **ielts-be** | europe-west1 | Production | AI keys, AWS, DB, Firebase, JWT | -| **ielts-be** | me-west1 | Staging | AI keys, AWS, DB, Firebase, JWT, ElevenLabs | -| **ielts-ui** | europe-west1 | Production | DB, Firebase, Paymob (live), SMTP, JWT | -| **ielts-ui** | us-central1 | Staging | DB, Firebase (staging), Paymob (test), SMTP, JWT | -| **encoach-frontend-staging** | me-central1 | Staging | DB, Firebase (staging), Paymob (test), SMTP, JWT | -| **encoach-cms** | europe-west1 | Production | MySQL, Strapi JWT, GCS service account | -| **encoach-landing-page** | europe-west1 | Production | Stripe (test), Strapi token | - ---- - -## Notes - -1. **Production and staging share the same OpenAI, AWS, ELAI, and GPTZero keys** — there is no separation of API keys between environments. -2. **Production and staging share the same MongoDB Atlas cluster** (`encoach.3ydyg.mongodb.net`) — only the database name differs (`production` vs `staging`). -3. **The Stripe keys on the landing page are test keys** (`pk_test_`, `sk_test_`) even in the production deployment. -4. **The `BACKEND_JWT` and `JWT_TEST_TOKEN` are identical** — the same test JWT is used for frontend-to-backend auth and for testing. -5. **The `GCS_SERVICE_ACCOUNT` in encoach-cms contains a full GCP service account private key** encoded in base64. -6. **The `FIREBASE_CLIENT_EMAIL` references `tiago.ribeiro@ecrop.dev`** — a developer's email from the previous development team. diff --git a/docs/Developer Workflow Manual.txt b/docs/Developer Workflow Manual.txt deleted file mode 100644 index 4d7f2827..00000000 --- a/docs/Developer Workflow Manual.txt +++ /dev/null @@ -1,156 +0,0 @@ - - - -# Developer Workflow Manual — EnCoach Backend & Frontend - -## One-Time Setup (Do This Once) - -**Step 1 — Clone the repositories** -```bash -git clone https://git.albousalh.com/devops/encoach_backend_new_v2.git -git clone https://git.albousalh.com/devops/encoach_frontend_new_v2.git -``` - -**Step 2 — Switch to the working branch** -```bash -cd encoach_backend_new_v2 -git checkout full_stack_dev - -cd ../encoach_frontend_new_v2 -git checkout full_stack_dev -``` - -**Step 3 — Install the `tea` CLI (to open PRs from terminal)** -```bash -# macOS -brew install tea - -# Or download directly: -# https://gitea.com/gitea/tea/releases - -# Configure it (run once): -tea login add --name encoach --url https://git.albousalh.com --token YOUR_TOKEN -``` -> To get your token: log in at `https://git.albousalh.com` → top-right avatar → Settings → Applications → Generate Token. - ---- - -## Every Day — Starting Work - -**Step 4 — Always pull the latest before coding** -```bash -git checkout full_stack_dev -git pull origin full_stack_dev -``` -> This makes sure you have the latest code before making changes. - ---- - -## Making Changes - -**Step 5 — Make your code changes locally** - -Work as normal in your editor. No restrictions on what you change. - -**Step 6 — If you add a new Python package**, add it to `new_project/requirements.txt`: -``` -openai>=1.50 -your-new-package>=x.x -``` - -**Step 7 — If you add a new Odoo addon**, place it under `new_project/custom_addons/your_module/` and make sure: -- The `__manifest__.py` lists **all** modules you reference via `comodel_name=` in its `depends` list. -- Notify Talal — new addons need a one-time manual install on the server (see end of this doc). - ---- - -## Pushing Your Work - -**Step 8 — Stage and commit your changes** -```bash -git add . -git commit -m "Short description of what you changed" -``` - -**Step 9 — Push to your working branch** -```bash -git push origin full_stack_dev -``` - -**Step 10 — Open a Pull Request** (asks Talal for review/approval) -```bash -tea pr create \ - --repo devops/encoach_backend_new_v2 \ - --head full_stack_dev \ - --base main \ - --title "Brief title of your changes" \ - --description "What you changed and why" -``` -> For frontend, replace `encoach_backend_new_v2` with `encoach_frontend_new_v2`. - -**Step 11 — Notify Talal** that a PR is waiting for his review. - ---- - -## After Talal Approves & Merges - -**Step 12 — Deployment is fully automatic.** You do not need to do anything on the server. - -What happens behind the scenes: -1. Talal merges the PR on `https://git.albousalh.com` -2. The server detects the merge to `main` -3. The deploy script pulls the latest code -4. Docker rebuilds the image (if `Dockerfile` or `requirements.txt` changed — takes ~10–15 min; otherwise ~1 min) -5. The container restarts with the new code - -**Step 13 — Verify it worked** by checking the live URL: -- Frontend: `http://5.189.151.117:3000` -- Backend API: `http://5.189.151.117:8069/api/login` - ---- - -## Checking Logs If Something Goes Wrong - -SSH into the server (ask Talal for credentials) and run: -```bash -# Backend logs -docker logs backend-v2-odoo --tail 50 - -# Frontend logs -docker logs encoach-frontend --tail 50 -``` - ---- - -## Special Case: Adding a New Odoo Addon - -New addons need a **one-time manual install** on the server (the database doesn't know about them yet). Tell Talal and he will run: -```bash -ssh root@5.189.151.117 -docker stop backend-v2-odoo -docker run --rm \ - --network backend-v2_default \ - -v /opt/encoach/backend-v2/odoo-docker.conf:/etc/odoo/odoo.conf:ro \ - -v /opt/encoach/backend-v2/new_project/custom_addons:/mnt/custom_addons:ro \ - -v /opt/encoach/backend-v2/new_project/enterprise-19:/mnt/enterprise:ro \ - -v /opt/encoach/backend-v2/new_project/openeducat_erp-19.0:/mnt/openeducat:ro \ - -v odoo-web-data:/var/lib/odoo \ - encoach-backend:latest \ - odoo -c /etc/odoo/odoo.conf -d encoach_v2 -i your_new_module --stop-after-init -docker start backend-v2-odoo -``` -> After the first install, all future deploys update it automatically. - ---- - -## Quick Reference - -| Action | Command | -|---|---| -| Pull latest | `git pull origin full_stack_dev` | -| Commit | `git add . && git commit -m "message"` | -| Push | `git push origin full_stack_dev` | -| Open PR (backend) | `tea pr create --repo devops/encoach_backend_new_v2 --head full_stack_dev --base main --title "..."` | -| Open PR (frontend) | `tea pr create --repo devops/encoach_frontend_new_v2 --head full_stack_dev --base main --title "..."` | -| View logs (backend) | `docker logs backend-v2-odoo --tail 50` | -| View logs (frontend) | `docker logs encoach-frontend --tail 50` | \ No newline at end of file diff --git a/docs/ENCOACH_USER_STORIES.md b/docs/ENCOACH_USER_STORIES.md deleted file mode 100644 index 0658c71c..00000000 --- a/docs/ENCOACH_USER_STORIES.md +++ /dev/null @@ -1,2125 +0,0 @@ -# EnCoach Platform -- Granular User Stories (English Only) - -**Document Version:** 2.0 -**Date:** April 2026 -**Status:** Active -- Ready for Development -**Scope:** English Language Only (General English + IELTS). Math/IT deferred to future phase. -**Audience:** Odoo Developer (full-stack, using Cursor IDE) - ---- - -## Companion Documents - -| Document | Version | Purpose | -|----------|---------|---------| -| `ENCOACH_WORKFLOWS_FRONTEND_SRS.md` | v1.1 | Frontend technical specification | -| `ENCOACH_WORKFLOWS_BACKEND_SRS.md` | v1.1 | Backend technical specification | -| `ENCOACH_USER_STORIES_OVERVIEW.md` | v1.0 | High-level overview (superseded by this document for development) | - ---- - -## How to Read This Document - -Each user story follows this format: - -> **US-[ACTOR]-[NUMBER]: [Title]** -> **As a** [single role], **I want to** [one specific action], **so that** [one clear benefit]. - -**One story = one function = one testable unit.** - -### Actor Prefixes - -| Prefix | Actor | Section | -|--------|-------|---------| -| SL | Self-Learning Student | Section 1 | -| ES | Entity/University Student | Section 2 | -| AD | Admin / Teacher | Section 3 | -| PV | Public Verifier | Section 3 (end) | - -### Priority Legend - -| Priority | Meaning | -|----------|---------| -| **Must Have** | Core functionality. Cannot launch without this. | -| **Should Have** | Important. Can be deferred briefly if needed. | -| **Could Have** | Desirable enhancement. Implement if time permits. | - ---- - -# SECTION 1 -- SELF-LEARNING STUDENT JOURNEY - -The complete end-to-end journey of an individual student who registers independently, pays for access, and learns on their own. - ---- - -## 1A. Registration - -### US-SL-01: Register a New Account - -**As a** self-learning student, **I want to** create an account by providing my name, email, password, and selecting "Self-Learner" as my role, **so that** I can access the platform independently. - -**Acceptance Criteria:** -- [ ] Registration page is accessible at `/register` without authentication -- [ ] Form fields: Full Name, Email, Password, Confirm Password, Role (select "Self-Learner"), CAPTCHA -- [ ] Password strength indicator updates in real time (Weak/Medium/Strong) -- [ ] Email uniqueness checked on blur; inline error if taken -- [ ] CAPTCHA must be completed before submission -- [ ] On success, redirect to `/verify-email?email={email}` -- [ ] On validation error, show field-level error messages - -**Flow:** -1. Student opens `/register` -2. Fills in all fields, selects "Self-Learner" role -3. Completes CAPTCHA -4. Clicks "Create Account" -5. System creates account, sends 6-digit OTP to email -6. Redirect to email verification page - -**Error / Edge Cases:** -- Duplicate email: inline error on blur -- CAPTCHA failure: "Please complete the CAPTCHA" -- Network error: toast "Something went wrong. Please try again." - -**SRS Reference:** Frontend 4, Backend 12 -**Priority:** Must Have - ---- - -### US-SL-02: Verify Email Address - -**As a** self-learning student who just registered, **I want to** enter a 6-digit verification code sent to my email, **so that** the platform confirms I own this email address. - -**Acceptance Criteria:** -- [ ] Page shows "We've sent a 6-digit verification code to {email}" -- [ ] 6-digit OTP input auto-focuses first digit, advances focus automatically -- [ ] "Verify" button enabled only when all 6 digits entered -- [ ] On valid OTP: redirect to `/onboarding` -- [ ] On invalid OTP: clear input, show "Invalid verification code. Please try again." -- [ ] On expired OTP: show "This code has expired. Please request a new one." -- [ ] "Resend code" disabled for 60 seconds after each send (countdown shown) -- [ ] Maximum 3 resend attempts; after 3: "Maximum resend attempts reached. Please contact support." -- [ ] Code expires after 15 minutes (countdown timer shown) - -**Flow:** -1. Student lands on `/verify-email?email={email}` -2. Checks email for OTP -3. Enters 6 digits -4. Clicks "Verify" -5. On success, proceeds to onboarding wizard - -**Error / Edge Cases:** -- Wrong code: input clears, retry allowed -- Code expired: must request new one -- All 3 resends exhausted: contact support -- Browser closed: returns to verification on next login (account still unverified) - -**SRS Reference:** Frontend 5, Backend 13 -**Priority:** Must Have - ---- - -## 1B. Onboarding - -### US-SL-03: Select Learning Goal - -**As a** self-learning student, **I want to** select my learning goal (General English, IELTS Academic, or IELTS General Training) in Step 1 of the onboarding wizard, **so that** the platform tailors my experience to my objective. - -**Acceptance Criteria:** -- [ ] Step 1 of 4 in the onboarding wizard at `/onboarding` -- [ ] Progress bar shows "Step 1 of 4" -- [ ] Radio card group displays available goals loaded from `GET /api/onboarding/goals` -- [ ] English-related options: General English, IELTS Academic, IELTS General Training -- [ ] Each card has: icon, title, description -- [ ] User must select one goal before clicking "Next" -- [ ] "Back" button is hidden on Step 1 - -**Flow:** -1. Student lands on onboarding wizard -2. Views available learning goals -3. Selects one goal (e.g., "IELTS Academic") -4. Clicks "Next" to proceed to Step 2 - -**SRS Reference:** Frontend 6, Backend 14 -**Priority:** Must Have - ---- - -### US-SL-04: Set Target Level and Timeline - -**As a** self-learning student, **I want to** set my target band/CEFR level and optionally an exam date in Step 2, **so that** the platform knows what I'm aiming for and by when. - -**Acceptance Criteria:** -- [ ] Step 2 of 4 in the onboarding wizard -- [ ] For IELTS goals: band score slider 4.0-9.0 in 0.5 steps -- [ ] For General English goals: CEFR level select (A1-C2) -- [ ] Optional exam date picker: "I have an upcoming exam on..." -- [ ] Checkbox: "I don't have a specific exam date" hides the date picker -- [ ] "Back" returns to Step 1 without losing data -- [ ] "Next" proceeds to Step 3 - -**Flow:** -1. Student sets target band/CEFR level -2. Optionally selects exam date or checks "no specific date" -3. Clicks "Next" - -**SRS Reference:** Frontend 6, Backend 14 -**Priority:** Must Have - ---- - -### US-SL-05: Set Study Preferences - -**As a** self-learning student, **I want to** configure my study hours per week, study mode, and learning style in Step 3, **so that** the platform personalises content delivery to my preferences. - -**Acceptance Criteria:** -- [ ] Step 3 of 4 in the onboarding wizard -- [ ] Hours per week: slider, 1-40, default 10. Shows estimated completion time -- [ ] Study mode: radio group -- "Self-study" or "With a teacher" -- [ ] Learning style: checkbox group (multi-select, at least one) -- Visual, Audio, Reading, Mixed -- [ ] "Back" returns to Step 2 without losing data -- [ ] "Next" proceeds to Step 4 - -**Flow:** -1. Student adjusts study hours slider -2. Selects study mode -3. Selects one or more learning styles -4. Clicks "Next" - -**SRS Reference:** Frontend 6, Backend 14 -**Priority:** Must Have - ---- - -### US-SL-06: Choose Placement Test Decision - -**As a** self-learning student, **I want to** decide whether to take the placement test now or skip it in Step 4, **so that** I can either get an accurate level assessment or start at a default level. - -**Acceptance Criteria:** -- [ ] Step 4 of 4 in the onboarding wizard -- [ ] Heading: "Ready to find your level?" -- [ ] Description explains the test (~20-30 minutes) -- [ ] "Take Placement Test Now" button: submits wizard data, navigates to `/student/placement` -- [ ] "Skip for Now" button: shows warning "Without a placement test, we'll start you at B1 (intermediate) level. You can take the test anytime from your dashboard." Submits wizard data, navigates to `/student/dashboard` -- [ ] On submission, account status changes to `activated` -- [ ] All 4 steps of wizard data submitted via `POST /api/onboarding/complete` - -**Flow:** -1. Student reads the placement test description -2. Chooses "Take Placement Test Now" or "Skip for Now" -3. Wizard data is submitted -4. Account is activated -5. Redirect to placement test or dashboard - -**Error / Edge Cases:** -- Browser closed mid-wizard: data lost, user restarts wizard on next login (account still `unactivated`) -- Skip chosen: default level B1, dashboard banner prompts test later - -**SRS Reference:** Frontend 6, Backend 14 -**Priority:** Must Have - ---- - -## 1C. Placement Test - -### US-SL-07: View Placement Test Briefing - -**As a** self-learning student, **I want to** see an overview of the placement test before starting, **so that** I know what to expect (sections, duration, adaptive nature). - -**Acceptance Criteria:** -- [ ] Briefing page at `/student/placement` -- [ ] Shows: subject (English), estimated duration (20-30 min), section count (4), adaptive note -- [ ] Dimension breakdown table: Grammar (~30 MCQ, ~8 min), Vocabulary (~20 items, ~5 min), Reading (~10 Q / 2 passages, ~10 min), Speaking (3 prompts, ~5 min) -- [ ] "Begin Test" button starts the test -- [ ] If an active incomplete session exists, "Begin Test" resumes from where the student left off - -**Flow:** -1. Student navigates to `/student/placement` -2. Reviews test overview -3. Clicks "Begin Test" -4. System creates CAT session and navigates to test interface - -**SRS Reference:** Frontend 7, Backend 15 -**Priority:** Must Have - ---- - -### US-SL-08: Take Placement Test -- Grammar Section - -**As a** self-learning student, **I want to** answer adaptive grammar questions one at a time, **so that** the system accurately assesses my grammar proficiency. - -**Acceptance Criteria:** -- [ ] Full-screen distraction-free interface (no sidebar) -- [ ] Top bar: elapsed timer, section name "Grammar", progress "Question X of ~30" -- [ ] Each question fetched one at a time from backend (no pre-loading) -- [ ] After each answer, next question adapts in difficulty (IRT algorithm) -- [ ] Question types: MCQ (single answer), MCQ (multiple answers) -- [ ] "Previous" button disabled (no going back in CAT) -- [ ] Auto-save every 10 seconds; "Saved" indicator shown -- [ ] When backend returns `section_complete: true`, show transition: "Grammar section complete. Next: Vocabulary" with countdown or "Continue" button - -**Flow:** -1. First grammar question appears -2. Student selects answer, clicks "Next" -3. Backend returns next (adapted) question -4. Repeat until section complete -5. Transition screen to Vocabulary section - -**Error / Edge Cases:** -- Network loss: auto-save ensures no data loss; resume on reconnection -- Browser close: resume from last save on next login - -**SRS Reference:** Frontend 8, Backend 15-16 -**Priority:** Must Have - ---- - -### US-SL-09: Take Placement Test -- Vocabulary Section - -**As a** self-learning student, **I want to** answer adaptive vocabulary questions, **so that** the system assesses my vocabulary range. - -**Acceptance Criteria:** -- [ ] Section name shows "Vocabulary", progress updates -- [ ] Question types: MCQ, gap fill, definition match -- [ ] Same CAT adaptive behaviour as Grammar section -- [ ] Auto-save every 10 seconds -- [ ] On section complete, transition to Reading section - -**Flow:** -1. First vocabulary question appears after Grammar transition -2. Student answers adaptive questions -3. Section completes, transition to Reading - -**SRS Reference:** Frontend 8, Backend 15-16 -**Priority:** Must Have - ---- - -### US-SL-10: Take Placement Test -- Reading Section - -**As a** self-learning student, **I want to** read passages and answer comprehension questions, **so that** the system assesses my reading proficiency. - -**Acceptance Criteria:** -- [ ] Section name shows "Reading", progress updates -- [ ] Split view: passage on left, questions on right (desktop). Scrollable passage above questions (mobile). -- [ ] Question types: MCQ, True/False/Not Given -- [ ] Passages progress from easy to difficult (CAT adaptation) -- [ ] Auto-save every 10 seconds -- [ ] On section complete, transition to Speaking section - -**Flow:** -1. First reading passage and questions appear -2. Student reads passage, answers questions -3. Repeat for second passage -4. Section completes, transition to Speaking - -**SRS Reference:** Frontend 8, Backend 15-16 -**Priority:** Must Have - ---- - -### US-SL-11: Take Placement Test -- Speaking Section - -**As a** self-learning student, **I want to** record spoken responses to 3 prompts, **so that** the system can evaluate my speaking ability via AI. - -**Acceptance Criteria:** -- [ ] Microphone permission prompt appears at the start of the section -- [ ] If permission denied: section skipped with note "Speaking section skipped. Your placement will be based on the other three sections." -- [ ] 3 speaking prompts, each showing: prompt text, "Start Recording" button, 60-second countdown -- [ ] During recording: waveform visualiser, "Stop" button -- [ ] After recording: playback controls, "Re-record" (max 1 re-record per prompt), "Submit Recording" -- [ ] Audio uploaded as blob via `POST /api/placement/speaking-upload` -- [ ] On final prompt submission, "Finish Test" button navigates to results page - -**Flow:** -1. Microphone permission requested -2. First speaking prompt displayed -3. Student clicks "Start Recording", speaks for up to 60 seconds -4. Clicks "Stop", reviews via playback -5. Optionally re-records once -6. Clicks "Submit Recording" -7. Repeats for prompts 2 and 3 -8. Clicks "Finish Test" - -**SRS Reference:** Frontend 8, Backend 18 -**Priority:** Must Have - ---- - -### US-SL-12: View Placement Results - -**As a** self-learning student, **I want to** see my overall CEFR level and per-dimension scores after completing the placement test, **so that** I understand my current proficiency. - -**Acceptance Criteria:** -- [ ] Results page at `/student/placement/results?session={id}` -- [ ] Overall CEFR level displayed prominently (e.g., "B2" with coloured badge) -- [ ] Per-dimension scores in a radar chart: Grammar, Vocabulary, Reading, Speaking -- [ ] Score table: Dimension, Score %, CEFR Level, Gap to Target -- [ ] If Speaking evaluation is pending: row shows "Pending" badge, polls `GET /api/placement/speaking-status` every 30 seconds until complete -- [ ] "Continue" button at the bottom navigates to learning path preview - -**Flow:** -1. Student lands on results page after test completion -2. Views overall CEFR level -3. Reviews per-dimension breakdown -4. Waits for Speaking evaluation if pending -5. Clicks "Continue" - -**Error / Edge Cases:** -- Speaking pending: "Pending" badge with polling -- Network error loading results: retry button - -**SRS Reference:** Frontend 9, Backend 15, 17 -**Priority:** Must Have - ---- - -### US-SL-13: View Personalised Learning Path Preview - -**As a** self-learning student, **I want to** see a personalised learning path based on my placement results BEFORE any payment prompt, **so that** I understand what I will study and can make an informed decision about subscribing. - -**Acceptance Criteria:** -- [ ] Learning path preview section on the results page (below scores) -- [ ] Course outline card: estimated duration, module count, study hours per week -- [ ] Skill gap modules listed by priority (largest gap first) with: module name, estimated hours, resource type icons (PDF, Video, Audio, Exercise), difficulty level -- [ ] "View Full Course Plan" button expands the detailed module breakdown -- [ ] This is shown BEFORE any payment prompt (key design principle) - -**Flow:** -1. Student views placement results -2. Scrolls down to learning path preview -3. Reviews proposed modules and estimated effort -4. Clicks "Continue" to proceed to payment options - -**SRS Reference:** Frontend 9, Backend 15 -**Priority:** Must Have - ---- - -### US-SL-14: Choose Payment or Access Option - -**As a** self-learning student, **I want to** choose between full subscription, free trial, or skip, **so that** I can start learning immediately or decide later. - -**Acceptance Criteria:** -- [ ] Three pricing cards at `/student/placement/access`: - - "Unlock Full Course" -> navigates to `/student/subscription` - - "Try Free for 7 Days" -> activates trial, navigates to dashboard - - "Continue to Dashboard" -> navigates to dashboard with persistent banner -- [ ] Free trial: limited access to first 3 modules only -- [ ] Skip: persistent banner on dashboard "Unlock your personalised course -- Subscribe now" - -**Flow:** -1. Student views three pricing options -2. Selects one -3. Proceeds to subscription, dashboard (trial), or dashboard (skip) - -**SRS Reference:** Frontend 10 -**Priority:** Should Have - ---- - -## 1D. Exam Taking - -### US-SL-15: Start an Assigned Exam Session - -**As a** self-learning student, **I want to** open an exam that has been assigned to me and enter the distraction-free exam interface, **so that** I can take the exam under controlled conditions. - -**Acceptance Criteria:** -- [ ] Full-screen interface at `/student/exam/:examId/session` (no sidebar, minimal header) -- [ ] Top bar: exam title, current section name, section countdown timer, overall progress bar -- [ ] All sections and questions pre-loaded (unlike CAT) -- [ ] First section starts immediately with its countdown timer -- [ ] Auto-save every 10 seconds; "Saved" indicator shown - -**Flow:** -1. Student navigates to the exam session -2. Exam loads with all sections -3. First section countdown begins -4. Student starts answering questions - -**Error / Edge Cases:** -- Exam not assigned: redirect with error "This exam is not available to you" -- Access window expired: "This exam's access window has closed" - -**SRS Reference:** Frontend 17, Backend 25 -**Priority:** Must Have - ---- - -### US-SL-16: Answer Listening Questions - -**As a** self-learning student taking an IELTS exam, **I want to** listen to audio recordings and answer questions for each Listening part, **so that** my listening comprehension is assessed. - -**Acceptance Criteria:** -- [ ] Audio player with play/pause, progress bar, volume control -- [ ] Audio plays once (IELTS standard). No replay unless configured for practice mode. -- [ ] Question types: MCQ (single), MCQ (multiple), gap fill -- [ ] Section timer counts down; warning at 5 min and 1 min remaining -- [ ] "Next" navigates to next question; "Previous" navigates back within the section -- [ ] "Flag for Review" marks the question with a flag icon -- [ ] On timer expiry: answers auto-submit, student moves to next section - -**Flow:** -1. Listening section begins, audio plays -2. Student answers questions while listening -3. Navigates between questions -4. Flags uncertain questions -5. Section ends (timer or manual submit) - -**SRS Reference:** Frontend 17, Backend 25 -**Priority:** Must Have - ---- - -### US-SL-17: Answer Reading Questions - -**As a** self-learning student taking an IELTS exam, **I want to** read passages and answer comprehension questions for each Reading part, **so that** my reading comprehension is assessed. - -**Acceptance Criteria:** -- [ ] Split view: passage on left, questions on right (desktop) -- [ ] Question types: MCQ, True/False/Not Given, gap fill, matching -- [ ] Section timer with warnings at 5 min and 1 min -- [ ] Previous/Next navigation within section -- [ ] "Flag for Review" available -- [ ] Auto-save every 10 seconds - -**Flow:** -1. Reading section begins -2. Student reads passage, answers questions -3. Navigates between questions and passages -4. Section ends (timer or manual submit) - -**SRS Reference:** Frontend 17, Backend 25 -**Priority:** Must Have - ---- - -### US-SL-18: Complete Writing Tasks - -**As a** self-learning student taking an IELTS exam, **I want to** write responses to Writing Task 1 and Task 2 using a rich text editor, **so that** my writing ability is assessed. - -**Acceptance Criteria:** -- [ ] Rich text editor with word count displayed -- [ ] Task 1: minimum 150 words (indicator turns red below minimum) -- [ ] Task 2: minimum 250 words (indicator turns red below minimum) -- [ ] Submission is NOT blocked by low word count (student may choose to submit anyway) -- [ ] Section timer with warnings -- [ ] Auto-save every 10 seconds - -**Flow:** -1. Writing section begins -2. Student reads Task 1 prompt, writes response -3. Monitors word count -4. Moves to Task 2, writes response -5. Section ends (timer or manual submit) - -**SRS Reference:** Frontend 17, Backend 25 -**Priority:** Must Have - ---- - -### US-SL-19: Record Speaking Responses in Exam - -**As a** self-learning student taking an IELTS exam, **I want to** record spoken responses for each Speaking part, **so that** my speaking ability is assessed. - -**Acceptance Criteria:** -- [ ] Same audio recording interface as placement test (US-SL-11) -- [ ] Part 1: Familiar topic questions -- [ ] Part 2: Cue card long turn (1 min prep + 2 min speaking) -- [ ] Part 3: Abstract discussion linked to Part 2 topic -- [ ] Microphone permission prompt -- [ ] Playback and re-record (max 1) per prompt -- [ ] Audio uploaded on submission - -**Flow:** -1. Speaking section begins -2. Student records responses for Parts 1, 2, and 3 -3. Reviews each recording -4. Submits recordings - -**SRS Reference:** Frontend 17, Backend 25 -**Priority:** Must Have - ---- - -### US-SL-20: Review and Submit Exam - -**As a** self-learning student, **I want to** review a summary of my answers before final submission, **so that** I can ensure I haven't missed any questions. - -**Acceptance Criteria:** -- [ ] Review summary page shows per section: answered count, unanswered count, flagged count -- [ ] Flagged questions listed with "Go to Question" links -- [ ] "Submit Exam" button with confirmation dialog: "Are you sure? You cannot change your answers after submission." -- [ ] After submission, navigate to submission confirmation page - -**Flow:** -1. Student completes all sections -2. Review summary appears -3. Student reviews flagged/unanswered items -4. Optionally returns to fix answers -5. Clicks "Submit Exam" -6. Confirmation dialog -> final submit - -**SRS Reference:** Frontend 17, Backend 25 -**Priority:** Must Have - ---- - -### US-SL-21: View Exam Results (Auto-Release) - -**As a** self-learning student whose exam has auto-release enabled, **I want to** see my results immediately after submission, **so that** I know my score right away. - -**Acceptance Criteria:** -- [ ] Results page at `/student/exam/:examId/results` -- [ ] Overall band score displayed prominently (e.g., "6.5") -- [ ] CEFR equivalent shown -- [ ] Per-skill radar chart and table: Skill, Band, CEFR, Gap to Target -- [ ] Listening and Reading: auto-scored, shown immediately -- [ ] Writing and Speaking: if pending teacher grading, show "Pending Review" with estimated wait time -- [ ] Feedback section: per-question feedback (expandable accordions per section) -- [ ] "Areas to improve" summary: top 3 weakness areas -- [ ] "Download PDF Report" button -- [ ] "View Recommended Course" button - -**Flow:** -1. Student is redirected to results page after submission -2. Sees auto-scored L/R results immediately -3. W/S show "Pending Review" until teacher grades them -4. Once all skills graded, full results display - -**SRS Reference:** Frontend 19, Backend 27 -**Priority:** Must Have - ---- - -### US-SL-22: Receive Post-Exam Routing (Pass) - -**As a** self-learning student who met or exceeded my target band, **I want to** see a congratulatory message with options to register for the official IELTS exam or continue studying, **so that** I know I've reached my goal. - -**Acceptance Criteria:** -- [ ] Action card: "Congratulations! You've reached your target." -- [ ] "Register for Official IELTS Exam" button -> navigates to `/student/exam-registration` -- [ ] "Continue Studying" button -> navigates to `/student/dashboard` - -**Flow:** -1. Student views results showing target met -2. Action card appears at bottom -3. Student chooses next step - -**SRS Reference:** Frontend 20 -**Priority:** Should Have - ---- - -### US-SL-23: Receive Post-Exam Routing (Below Target) - -**As a** self-learning student who scored below my target band, **I want to** see my skill gaps and an option to start adaptive training, **so that** I can work on my weaknesses. - -**Acceptance Criteria:** -- [ ] Action card: "Let's build a plan to reach your target." -- [ ] Skill gap summary shown inline -- [ ] "Start Adaptive Training" button -> navigates to `/student/course/generate?from=exam&examId={id}` - -**Flow:** -1. Student views results showing target not met -2. Action card with gap summary appears -3. Student clicks "Start Adaptive Training" - -**SRS Reference:** Frontend 20 -**Priority:** Should Have - ---- - -## 1E. Course Learning - -### US-SL-24: View Gap Analysis - -**As a** self-learning student, **I want to** see a detailed skill gap analysis from my exam or placement results, **so that** I understand which areas need the most work. - -**Acceptance Criteria:** -- [ ] Gap analysis page at `/student/course/generate` -- [ ] Bar chart: skills ranked by gap size (largest first), current vs target -- [ ] Table: Skill, Current Level, Target Level, Gap, Priority (High/Medium/Low), Est. Hours -- [ ] Question-type weaknesses expandable per skill -- [ ] Topic weaknesses grouped by category -- [ ] "Generate Course" button to auto-generate a course - -**Flow:** -1. Student navigates to gap analysis -2. Reviews skill gaps and weakness breakdowns -3. Clicks "Generate Course" - -**SRS Reference:** Frontend 21, Backend 29 -**Priority:** Must Have - ---- - -### US-SL-25: Start Auto-Generated Course - -**As a** self-learning student, **I want to** view an auto-generated course structure based on my gap analysis and start learning immediately, **so that** I don't have to wait for a teacher to build a course. - -**Acceptance Criteria:** -- [ ] Read-only course preview: title, duration estimate, module list with skill assignments, hours, resource icons -- [ ] "Start Course" button begins the course -- [ ] "Customize" button (optional) allows minor adjustments (reorder modules, skip low-priority skills) -- [ ] Course is created via `POST /api/course/auto-generate` - -**Flow:** -1. System generates course structure from gap analysis -2. Student reviews the proposed course -3. Clicks "Start Course" -4. Course page opens with modules available - -**SRS Reference:** Frontend 22, Backend 30 -**Priority:** Must Have - ---- - -### US-SL-26: Start AI-Generated General English Course - -**As a** self-learning student studying General English, **I want to** launch an AI-generated course tailored to my CEFR level and learning style, **so that** I receive personalised content without waiting for a teacher. - -**Acceptance Criteria:** -- [ ] Confirmation screen shows: Current CEFR Level, Target CEFR Level (editable), Learning Style (editable), Estimated Duration -- [ ] "Start AI Course" triggers content generation via `POST /api/ai-course/english/create` -- [ ] Progress indicator during generation: "Generating your personalised course... Step 2/5: Creating grammar exercises." (1-2 min) -- [ ] Three parallel module tracks: Grammar Track, Skills Track, Vocabulary Track -- [ ] Each module: title, completion status, estimated time, "Start" / "Continue" button -- [ ] Level-up celebration modal when a level is achieved - -**Flow:** -1. Student reviews profile settings -2. Clicks "Start AI Course" -3. Waits for generation (1-2 min) -4. Course appears with three parallel tracks -5. Student progresses through modules - -**SRS Reference:** Frontend 28, Backend 36 -**Priority:** Must Have - ---- - -### US-SL-27: Start AI-Generated IELTS Course - -**As a** self-learning student preparing for IELTS, **I want to** launch an AI-generated IELTS course that targets my weakest skills, **so that** I get focused practice aligned with real IELTS standards. - -**Acceptance Criteria:** -- [ ] Profile summary: Exam Type, Current Bands per skill, Target Band (editable), Skills ranked by gap, Weak question types -- [ ] "Start AI IELTS Course" triggers per-skill content generation -- [ ] Generation progress per skill: "Listening: Generating... Creating audio scripts for Parts 1-4" -- [ ] Four parallel skill paths: Writing, Reading, Speaking, Listening -- [ ] Readiness check modal when engine determines target band likely reached -- [ ] Practice exam option for band confirmation - -**Flow:** -1. Student reviews IELTS gap profile -2. Clicks "Start AI IELTS Course" -3. Waits for per-skill generation -4. Progresses through four skill paths -5. Takes practice exam when prompted - -**SRS Reference:** Frontend 29, Backend 37 -**Priority:** Must Have - ---- - -### US-SL-28: Progress Through Course Modules - -**As a** self-learning student, **I want to** progress through my course modules, viewing my completion status and unlocking new modules, **so that** I learn systematically. - -**Acceptance Criteria:** -- [ ] Course page at `/student/course/:courseId` -- [ ] Header: title, overall progress %, estimated time remaining -- [ ] Module list with collapsible sections per skill -- [ ] Each module: status (locked/available/in-progress/completed), progress bar, resource list with type icons and completion checkmarks -- [ ] "Start" / "Continue" button per module -- [ ] Adaptive indicators (if adaptive progression): "Recommended Next" badge, "Unlocked!" animation, "Skipped" badge for mastered modules - -**Flow:** -1. Student opens course page -2. Sees module list with statuses -3. Opens the next available module -4. Progresses through resources - -**SRS Reference:** Frontend 24, Backend 31 -**Priority:** Must Have - ---- - -### US-SL-29: View In-Platform Resources - -**As a** self-learning student, **I want to** view course resources (PDF, video, audio, exercises) directly on the platform without downloading, **so that** I can learn seamlessly. - -**Acceptance Criteria:** -- [ ] PDF: embedded viewer (browser native or react-pdf) -- [ ] Video: HTML5 `