EnCoach Odoo 19 custom modules
Full backend implementation with custom Odoo modules: - encoach_api: Core API, user management, JWT auth - encoach_exam: Exam generation (reading, writing, listening, speaking) - encoach_evaluate: AI-powered evaluation (writing, speaking) - encoach_training: Training tips and walkthrough - encoach_storage: File storage management - encoach_payment: Stripe, PayPal, Paymob integration - encoach_mail: Email notifications Made-with: Cursor
This commit is contained in:
1
encoach_assignment/__init__.py
Normal file
1
encoach_assignment/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
14
encoach_assignment/__manifest__.py
Normal file
14
encoach_assignment/__manifest__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "EnCoach Assignment",
|
||||
"version": "19.0.1.0.0",
|
||||
"category": "Education",
|
||||
"summary": "Exam assignments for teachers and students",
|
||||
"depends": ["encoach_core", "encoach_exam"],
|
||||
"data": [
|
||||
"security/ir.model.access.csv",
|
||||
"security/rules.xml",
|
||||
"views/assignment_views.xml",
|
||||
],
|
||||
"installable": True,
|
||||
"license": "LGPL-3",
|
||||
}
|
||||
1
encoach_assignment/models/__init__.py
Normal file
1
encoach_assignment/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import assignment
|
||||
87
encoach_assignment/models/assignment.py
Normal file
87
encoach_assignment/models/assignment.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from odoo import models, fields
|
||||
|
||||
INSTRUCTOR_GENDER = [
|
||||
("male", "Male"),
|
||||
("female", "Female"),
|
||||
]
|
||||
|
||||
|
||||
class EncoachAssignment(models.Model):
|
||||
_name = "encoach.assignment"
|
||||
_description = "EnCoach Assignment"
|
||||
|
||||
name = fields.Char(required=True)
|
||||
assigner_id = fields.Many2one(
|
||||
"res.users", string="Assigner", default=lambda self: self.env.uid,
|
||||
)
|
||||
assignee_ids = fields.Many2many(
|
||||
"res.users", "encoach_assignment_assignee_rel",
|
||||
"assignment_id", "user_id", string="Assignees",
|
||||
)
|
||||
exam_ids = fields.Many2many(
|
||||
"encoach.exam", "encoach_assignment_exam_rel",
|
||||
"assignment_id", "exam_id", string="Exams",
|
||||
)
|
||||
results = fields.Json(
|
||||
help="Array of {user, type, stats} result objects per assignee",
|
||||
)
|
||||
instructor_gender = fields.Selection(INSTRUCTOR_GENDER)
|
||||
start_date = fields.Datetime()
|
||||
end_date = fields.Datetime()
|
||||
teacher_ids = fields.Many2many(
|
||||
"res.users", "encoach_assignment_teacher_rel",
|
||||
"assignment_id", "user_id", string="Teachers",
|
||||
)
|
||||
archived = fields.Boolean(default=False)
|
||||
released = fields.Boolean(default=False)
|
||||
started = fields.Boolean(default=False)
|
||||
auto_start = fields.Boolean(default=False)
|
||||
entity_id = fields.Many2one("encoach.entity", index=True)
|
||||
legacy_id = fields.Char(index=True)
|
||||
|
||||
def action_start(self):
|
||||
for rec in self:
|
||||
rec.started = True
|
||||
|
||||
def action_release(self):
|
||||
for rec in self:
|
||||
rec.released = True
|
||||
|
||||
def action_archive(self):
|
||||
for rec in self:
|
||||
rec.archived = True
|
||||
|
||||
def action_unarchive(self):
|
||||
for rec in self:
|
||||
rec.archived = False
|
||||
|
||||
def to_encoach_dict(self):
|
||||
self.ensure_one()
|
||||
exams = []
|
||||
for exam in self.exam_ids:
|
||||
exams.append({
|
||||
"id": exam.id,
|
||||
"module": exam.module,
|
||||
"assignee": None,
|
||||
})
|
||||
return {
|
||||
"id": self.id,
|
||||
"name": self.name,
|
||||
"assigner": self.assigner_id.id if self.assigner_id else None,
|
||||
"assignees": self.assignee_ids.ids,
|
||||
"results": self.results or [],
|
||||
"exams": exams,
|
||||
"instructorGender": self.instructor_gender,
|
||||
"startDate": (
|
||||
self.start_date.isoformat() if self.start_date else None
|
||||
),
|
||||
"endDate": (
|
||||
self.end_date.isoformat() if self.end_date else None
|
||||
),
|
||||
"teachers": self.teacher_ids.ids,
|
||||
"archived": self.archived,
|
||||
"released": self.released,
|
||||
"start": self.started,
|
||||
"autoStart": self.auto_start,
|
||||
"entity": self.entity_id.id if self.entity_id else None,
|
||||
}
|
||||
5
encoach_assignment/security/ir.model.access.csv
Normal file
5
encoach_assignment/security/ir.model.access.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_encoach_assignment_student,encoach.assignment.student,model_encoach_assignment,encoach_core.group_encoach_student,1,0,0,0
|
||||
access_encoach_assignment_teacher,encoach.assignment.teacher,model_encoach_assignment,encoach_core.group_encoach_teacher,1,1,1,0
|
||||
access_encoach_assignment_admin,encoach.assignment.admin,model_encoach_assignment,encoach_core.group_encoach_admin,1,1,1,1
|
||||
access_encoach_assignment_sysadmin,encoach.assignment.sysadmin,model_encoach_assignment,base.group_system,1,1,1,1
|
||||
|
17
encoach_assignment/security/rules.xml
Normal file
17
encoach_assignment/security/rules.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="rule_assignment_student" model="ir.rule">
|
||||
<field name="name">Students see assigned assignments</field>
|
||||
<field name="model_id" ref="model_encoach_assignment"/>
|
||||
<field name="groups" eval="[(4, ref('encoach_core.group_encoach_student'))]"/>
|
||||
<field name="domain_force">[('assignee_ids', 'in', user.id)]</field>
|
||||
</record>
|
||||
<record id="rule_assignment_teacher" model="ir.rule">
|
||||
<field name="name">Teachers see all assignments</field>
|
||||
<field name="model_id" ref="model_encoach_assignment"/>
|
||||
<field name="groups" eval="[(4, ref('encoach_core.group_encoach_teacher'))]"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
91
encoach_assignment/views/assignment_views.xml
Normal file
91
encoach_assignment/views/assignment_views.xml
Normal file
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<record id="view_encoach_assignment_tree" model="ir.ui.view">
|
||||
<field name="name">encoach.assignment.tree</field>
|
||||
<field name="model">encoach.assignment</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Assignments">
|
||||
<field name="name"/>
|
||||
<field name="assigner_id"/>
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<field name="instructor_gender"/>
|
||||
<field name="started"/>
|
||||
<field name="released"/>
|
||||
<field name="archived"/>
|
||||
<field name="entity_id"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_encoach_assignment_form" model="ir.ui.view">
|
||||
<field name="name">encoach.assignment.form</field>
|
||||
<field name="model">encoach.assignment</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Assignment">
|
||||
<header>
|
||||
<button name="action_start" string="Start" type="object"
|
||||
class="btn-primary" invisible="started"/>
|
||||
<button name="action_release" string="Release" type="object"
|
||||
class="btn-primary" invisible="released or not started"/>
|
||||
<button name="action_archive" string="Archive" type="object"
|
||||
invisible="archived"/>
|
||||
<button name="action_unarchive" string="Unarchive" type="object"
|
||||
invisible="not archived"/>
|
||||
<field name="started" readonly="1"/>
|
||||
<field name="released" readonly="1"/>
|
||||
<field name="archived" readonly="1"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="assigner_id"/>
|
||||
<field name="instructor_gender"/>
|
||||
<field name="entity_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<field name="auto_start"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Assignees" name="assignees">
|
||||
<field name="assignee_ids" widget="many2many_tags"/>
|
||||
</page>
|
||||
<page string="Exams" name="exams">
|
||||
<field name="exam_ids" widget="many2many_tags"/>
|
||||
</page>
|
||||
<page string="Teachers" name="teachers">
|
||||
<field name="teacher_ids" widget="many2many_tags"/>
|
||||
</page>
|
||||
<page string="Results" name="results">
|
||||
<field name="results" widget="json" nolabel="1" placeholder="[]"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_encoach_assignment" model="ir.actions.act_window">
|
||||
<field name="name">Assignments</field>
|
||||
<field name="res_model">encoach.assignment</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first assignment.
|
||||
</p>
|
||||
<p>
|
||||
Assignments link exams to assignees and teachers with start and end dates.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_encoach_assignment"
|
||||
name="Assignments"
|
||||
parent="encoach_core.menu_encoach_classroom"
|
||||
action="action_encoach_assignment"
|
||||
sequence="20"/>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user