Commit 42bb1a75 by aagusti

tambah examp

1 parent 5d3d8145
Showing 99 changed files with 0 additions and 1852 deletions
=======
School
=======
This module was written to extend the functionality of school to support school management and allow you to get a functionality of school management.
Installation
============
To install this module, you need to:
install 'hr', 'crm', 'account', module
Configuration
=============
To configure this module, you need to:
have a school management functionality.
Usage
=====
To use this module, you need to:
go to apps, then install module to apply this functionality.
Try me on Runbot
Known issues / Roadmap
Bug Tracker
===========
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed feedback here.
=======
Credits
=======
Contributors
============
Serpent Consulting Services PVT. LTD. <http://serpentcs.com>
Maintainer
===========
Serpent Consulting Services PVT. LTD.
This module is maintained by the SerpentCS.
To contribute to this module, please visit http://serpentcs.com.
# See LICENSE file for full copyright and licensing details.
# ----------------------------------------------------------
# A Module for School Management System
# ----------------------------------------------------------
from . import models
from . import wizard
# See LICENSE file for full copyright and licensing details.
{
'name': 'School',
'version': '14.0.1.0.0',
'author': 'Serpent Consulting Services Pvt. Ltd.',
'website': 'http://www.serpentcs.com',
'category': 'School Management',
'license': "AGPL-3",
'complexity': 'easy',
'Summary': 'A Module For School Management',
'images': ['static/description/EMS.jpg'],
'depends': ['hr', 'crm', 'account'],
'data': ['security/school_security.xml',
'security/ir.model.access.csv',
'data/student_sequence.xml',
'wizard/terminate_reason_view.xml',
'wizard/wiz_send_email_view.xml',
'views/student_view.xml',
'views/school_view.xml',
'views/teacher_view.xml',
'views/parent_view.xml',
'wizard/assign_roll_no_wizard.xml',
'wizard/move_standards_view.xml',
'report/report_view.xml',
'report/identity_card.xml',
'views/template_view.xml'],
'demo': ['demo/school_demo.xml'],
'installable': True,
'application': True
}
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Sequences For student.code (Student Code) -->
<record id="seq_student_code" model="ir.sequence">
<field name="name">Student code</field>
<field name="code">student.code</field>
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
<!-- Sequences For student.registration (Registration Code) -->
<record id="seq_student_reg" model="ir.sequence">
<field name="name">Student registration code</field>
<field name="code">student.registration</field>
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
<!-- Sequences For student.student (Personal Identification Number) -->
<record id="seq_student_student" model="ir.sequence">
<field name="name">Student</field>
<field name="code">student.student</field>
<field name="prefix">%(year)s/%(month)s/</field>
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
<!-- Sequences For student.document (Student Documents) -->
<record id="seq_student_document" model="ir.sequence">
<field name="name">Document</field>
<field name="code">student.document</field>
<field name="prefix">F</field>
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
<!-- Sequences For document.type (Document Type) -->
<record id="seq_student_sequence" model="ir.sequence">
<field name="name">sequence</field>
<field name="code">document.type</field>
<field name="padding">1</field>
<field name="company_id" eval="False"/>
</record>
</data>
</odoo>
# See LICENSE file for full copyright and licensing details.
# ----------------------------------------------------------
# A Module to School Management System
# ----------------------------------------------------------
from . import school
from . import student
from . import teacher
from . import parent
from . import res_users
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class ParentRelation(models.Model):
'''Defining a Parent relation with child.'''
_name = "parent.relation"
_description = "Parent-child relation information"
name = fields.Char("Relation name", required=True,
help='Parent relation with student')
class SchoolParent(models.Model):
'''Defining a Teacher information.'''
_name = 'school.parent'
_description = 'Parent Information'
partner_id = fields.Many2one('res.partner', 'User ID', ondelete="cascade",
delegate=True, required=True,
help='Partner which is user over here')
relation_id = fields.Many2one('parent.relation', 'Relation with Child',
help='Parent relation with child')
student_id = fields.Many2many('student.student', 'students_parents_rel',
'students_parent_id', 'student_id',
'Children',
help='Student of the following parent')
standard_id = fields.Many2many('school.standard',
'school_standard_parent_rel',
'class_parent_id', 'class_id',
'Academic Class',
help='''Class of the student
of following parent''')
stand_id = fields.Many2many('standard.standard',
'standard_standard_parent_rel',
'standard_parent_id', 'standard_id',
'Academic Standard',
help='''Standard of the student
of following parent''')
teacher_id = fields.Many2one('school.teacher', 'Teacher',
related="standard_id.user_id", store=True,
help='Teacher of a student')
@api.onchange('student_id')
def onchange_student_id(self):
"""Onchange Method for Student."""
standard_ids = [student.standard_id.id
for student in self.student_id]
if standard_ids:
stand_ids = [student.standard_id.standard_id.id
for student in self.student_id]
self.standard_id = [(6, 0, standard_ids)]
self.stand_id = [(6, 0, stand_ids)]
@api.model
def create(self, vals):
"""Inherited create method to assign values in
the users record to maintain the delegation"""
parent_rec = super(SchoolParent, self).create(vals)
parent_grp_id = self.env.ref('school.group_school_parent')
emp_grp = self.env.ref('base.group_user')
parent_group_ids = [emp_grp.id, parent_grp_id.id]
user_vals = {'name': parent_rec.name,
'login': parent_rec.email,
'email': parent_rec.email,
'partner_id': parent_rec.partner_id.id,
'groups_id': [(6, 0, parent_group_ids)]
}
self.env['res.users'].create(user_vals)
return parent_rec
@api.onchange('state_id')
def onchange_state(self):
"""Onchange Method for State."""
if self.state_id:
self.country_id = self.state_id.country_id.id or False
# See LICENSE file for full copyright and licensing details.
from odoo import api, models
class ResUsers(models.Model):
_inherit = "res.users"
@api.model
def create(self, vals):
"""Inherit Method to create user of group teacher or parent."""
vals.update({'employee_ids': False})
user_rec = super(ResUsers, self).create(vals)
if self._context.get('teacher_create', False):
teacher_grp_id = self.env.ref('school.group_school_teacher')
user_base_grp = self.env.ref('base.group_user')
contact_create = self.env.ref('base.group_partner_manager')
teacher_group_ids = [user_base_grp.id, teacher_grp_id.id,
contact_create.id]
user_rec.write({'groups_id': [(6, 0, teacher_group_ids)],
'company_id': self._context.get('school_id'),
'company_ids': [(4, self._context.get('school_id'))
]})
return user_rec
# See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class SchoolTeacher(models.Model):
'''Defining a Teacher information.'''
_name = 'school.teacher'
_description = 'Teacher Information'
_inherit = ['mail.thread', 'mail.activity.mixin']
employee_id = fields.Many2one('hr.employee', 'Employee ID',
ondelete="cascade",
delegate=True, required=True,
help='Enter related employee')
standard_id = fields.Many2one('school.standard',
"Responsibility of Academic Class",
help="Standard for which the teacher\
responsible for.")
stand_id = fields.Many2one('standard.standard', "Course",
related="standard_id.standard_id", store=True,
help='''Select standard which are
assigned to teacher''')
subject_id = fields.Many2many('subject.subject', 'subject_teacher_rel',
'teacher_id', 'subject_id',
'Course-Subjects',
help='Select subject of teacher')
school_id = fields.Many2one('school.school', "Campus",
help='Select school')
category_ids = fields.Many2many('hr.employee.category',
'teacher_category_rel', 'emp_id',
'categ_id', 'Tags',
help='Select employee category')
department_id = fields.Many2one('hr.department', 'Department',
help='Select department')
is_parent = fields.Boolean('Is Parent',
help='Select this if it parent')
stu_parent_id = fields.Many2one('school.parent', 'Related Parent',
help='Enter student parent')
student_id = fields.Many2many('student.student',
'students_teachers_parent_rel',
'teacher_id', 'student_id',
'Children', help='Select student')
phone_numbers = fields.Char("Phone Number", help='Student PH no')
@api.onchange('standard_id')
def _onchange_standard_id(self):
for rec in self:
if rec.standard_id:
rec.school_id = rec.standard_id.school_id.id
@api.onchange('is_parent')
def _onchange_isparent(self):
"""Onchange method for is parent"""
if self.is_parent:
self.stu_parent_id = False
self.student_id = False
@api.onchange('stu_parent_id')
def _onchangestudent_parent(self):
"""Onchange method for student parent records"""
stud_list = []
if self.stu_parent_id and self.stu_parent_id.student_id:
for student in self.stu_parent_id.student_id:
stud_list.append(student.id)
self.student_id = [(6, 0, stud_list)]
@api.model
def create(self, vals):
"""Inherited create method to assign value to users for delegation"""
teacher_id = super(SchoolTeacher, self).create(vals)
user_obj = self.env['res.users']
user_vals = {'name': teacher_id.name,
'login': teacher_id.work_email,
'email': teacher_id.work_email,
}
ctx_vals = {'teacher_create': True,
'school_id': teacher_id.school_id.company_id.id}
user_rec = user_obj.with_context(ctx_vals).create(user_vals)
teacher_id.employee_id.write({'user_id': user_rec.id})
# if vals.get('is_parent'):
# self.parent_crt(teacher_id)
return teacher_id
# Removing this code because of issue faced due to email id of the
# user is same for parent and Teacher, and system will not allow it.
# now user shuld create Parent record first and then select it in
# related parent in Teacher Profile. - Anu Patel (24/03/2021)
# def parent_crt(self, manager_id):
# """Method to create parent record based on parent field"""
# stu_parent = []
# if manager_id.stu_parent_id:
# stu_parent = manager_id.stu_parent_id
# if not stu_parent:
# emp_user = manager_id.employee_id
# students = [stu.id for stu in manager_id.student_id]
# parent_vals = {'name': manager_id.name,
# 'email': emp_user.work_email,
# 'user_ids': [(6, 0, [emp_user.user_id.id])],
# 'partner_id': emp_user.user_id.partner_id.id,
# 'student_id': [(6, 0, students)]}
# stu_parent = self.env['school.parent'].with_context().create(parent_vals)
# manager_id.write({'stu_parent_id': stu_parent.id})
# user = stu_parent.user_ids
# user_rec = user[0]
# parent_grp_id = self.env.ref('school.group_school_parent')
# groups = parent_grp_id
# if user_rec.groups_id:
# groups = user_rec.groups_id
# groups += parent_grp_id
# group_ids = [group.id for group in groups]
# user_rec.write({'groups_id': [(6, 0, group_ids)]})
def write(self, vals):
"""Inherited write method to assign groups based on parent field"""
# if vals.get('is_parent'):
# self.parent_crt(self)
if vals.get('student_id'):
self.stu_parent_id.write({'student_id': vals.get('student_id')})
if not vals.get('is_parent'):
user_rec = self.employee_id.user_id
ir_obj = self.env['ir.model.data']
parent_grp_id = ir_obj.get_object('school', 'group_school_parent')
groups = parent_grp_id
if user_rec.groups_id:
groups = user_rec.groups_id
groups -= parent_grp_id
group_ids = [group.id for group in groups]
user_rec.write({'groups_id': [(6, 0, group_ids)]})
return super(SchoolTeacher, self).write(vals)
@api.onchange('address_id')
def onchange_address_id(self):
"""Onchange method for address."""
self.work_phone = self.address_id.phone or False,
self.mobile_phone = self.address_id.mobile or False
@api.onchange('department_id')
def onchange_department_id(self):
"""Onchange method for deepartment."""
self.parent_id = (self.department_id and
self.department_id.manager_id and
self.department_id.manager_id.id) or False
@api.onchange('user_id')
def onchange_user(self):
"""Onchange method for user."""
if self.user_id:
self.name = self.name or self.user_id.name
self.work_email = self.user_id.email
self.image = self.image or self.user_id.image
@api.onchange('school_id')
def onchange_school(self):
"""Onchange method for school."""
self.address_id = self.school_id.company_id.partner_id.id or \
False
self.mobile_phone = self.school_id.company_id.partner_id.mobile or \
False
self.work_location = self.school_id.company_id.partner_id.city or \
False
self.work_email = self.school_id.company_id.partner_id.email or False
phone = self.school_id.company_id.partner_id.phone or False
self.work_phone = phone or False
self.phone_numbers = phone or False
phone = self.school_id.company_id.partner_id.phone or False
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="identity_card">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page" style="height: 2px;">
<div class="oe_structure"/>
<br/>
<br/>
<br/>
<br/>
<br/>
<t t-foreach="o" t-as="student">
<br/><br/><br/>
<table width="25%" height="50px" style="border: 3px solid black;">
<tr>
<td width="100%" align="center" height="30">
<strong>
<span t-field="student.school_id.name" />
</strong>
</td>
</tr>
<tr>
<td align="center">
<img t-if="student.photo" t-att-src="'data:image/png;base64,%s' % to_text(student.photo)"
style="height:120px;width=120px" />
</td>
</tr>
<tr>
<td height="10px"></td>
</tr>
<tr>
<td align="center" height="30px">
<strong>
<span t-field="student.name" />
</strong>
<strong>
<span t-field="student.middle" />
</strong>
<strong>
<span t-field="student.last" />
</strong>
</td>
</tr>
<tr>
<td height="130">
<table width="100%">
<tr>
<td style="font-family: 'Helvetica';padding-left:20px;">
<strong>Roll No.</strong>
</td>
<td>
<strong>: </strong>
</td>
<td>
<span t-field="student.roll_no" />
</td>
</tr>
<tr>
<td style="font-family: 'Helvetica';padding-left:20px;">
<strong>Standard</strong>
</td>
<td>
<strong>: </strong>
</td>
<td>
<span t-field="student.standard_id.standard_id.name"/>
</td>
</tr>
<tr>
<td style="font-family: 'Helvetica';padding-left:20px;">
<strong>Division</strong>
</td>
<td>
<strong>: </strong>
</td>
<td>
<span t-field="student.standard_id.division_id.name"/>
</td>
</tr>
<tr>
<td style="font-family: 'Helvetica';padding-left:20px;">
<strong>Medium</strong>
</td>
<td>
<strong>: </strong>
</td>
<td>
<span t-field="student.medium_id.name" />
</td>
</tr>
<tr>
<td style="font-family: 'Helvetica';padding-left:20px;">
<strong>BirthDate</strong>
</td>
<td>
<strong>: </strong>
</td>
<td>
<span t-field="student.date_of_birth" />
</td>
</tr>
<tr>
<td style="font-family: 'Helvetica';padding-left:20px;">
<strong>Blood Group</strong>
</td>
<td>
<strong>: </strong>
</td>
<td>
<span t-field="student.blood_group" />
</td>
</tr>
</table>
</td>
</tr>
</table>
</t>
</div>
</t>
</t>
</t>
</template>
</odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="report_student_student" model="ir.actions.report">
<field name="name">Identity Card</field>
<field name="model">student.student</field>
<field name="binding_model_id" ref="model_student_student"/>
<field name="report_type">qweb-pdf</field>
<field name="report_name">school.identity_card</field>
<field name="report_file">school.identity_card</field>
<field name="binding_type">report</field>
<field name="groups_id" eval="[(4, ref('school.group_school_administration')),
(4, ref('school.group_school_teacher')),
(4, ref('school.group_school_student'))]"/>
</record>
</odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="module_category_school" model="ir.module.category">
<field name="name">School Management</field>
<field name="sequence">22</field>
</record>
<record id="group_school_administration" model="res.groups">
<field name="name">School Administrator</field>
<field name="category_id" ref="module_category_school"/>
<field name="users" eval="[(4, ref('base.user_root')),(4, ref('base.user_admin'))]"/>
</record>
<record id="group_school_teacher" model="res.groups">
<field name="name">School Teacher</field>
<field name="category_id" ref="module_category_school"/>
</record>
<record id="group_school_student" model="res.groups">
<field name="name">School Student</field>
<field name="category_id" ref="module_category_school"/>
</record>
<record id="group_school_parent" model="res.groups">
<field name="name">Student Parent</field>
<field name="category_id" ref="module_category_school"/>
</record>
<record id="group_is_admission" model="res.groups">
<field name="name">In Admission</field>
<field name="category_id" ref="module_category_school"/>
</record>
<!-- Rule For Creating Personal School Record As A Teacher, Student & Parent-->
<record id="rule_personal_school_record" model="ir.rule">
<field name="name">Rule Personal School Record</field>
<field name="model_id" ref="model_school_school"/>
<field name="domain_force">['|','|',('company_id.child_ids', 'child_of', [user.company_id.id]),('company_id', 'child_of', [user.company_id.id]),('company_id', '=', False)]</field>
<field name="groups" eval="[(4, ref('group_school_teacher')),(4, ref('group_school_student')),(4, ref('group_school_parent'))]"/>
</record>
<!-- Rule For Student Profile Record As A Student -->
<record id="rule_student_profile_record_as_student" model="ir.rule">
<field name="name">Rule Student Profile Record As A Student</field>
<field name="model_id" ref="model_student_student"/>
<field name="global" eval="True"/>
<field name="domain_force">[('user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('group_school_student'))]"/>
</record>
<!-- Rule For Student Profile Record As An Administrator -->
<record id="rule_student_profile_record_as_admin" model="ir.rule">
<field name="name">Rule Student Profile Record As An Administrator</field>
<field name="model_id" ref="model_student_student"/>
<field name="global" eval="True"/>
<field name="domain_force"> ['|','|',('company_id.child_ids','child_of',[user.company_id.id]),('company_id','child_of',[user.company_id.id]),('company_id','=',False)]</field>
<field name="groups" eval="[(4, ref('group_school_administration'))]"/>
</record>
<!-- Rule For Student Profile Record As A Teacher -->
<record id="rule_student_profile_record_as_teacher" model="ir.rule">
<field name="name">Rule Student Profile Record As A Teacher</field>
<field name="model_id" ref="model_student_student"/>
<field name="global" eval="True"/>
<field name="domain_force">[('company_id','=',user.company_id.id)]</field>
<field name="groups" eval="[(4, ref('group_school_teacher'))]"/>
</record>
<!-- Rule For Student Profile Record As A Parent -->
<!-- <record id="rule_student_profile_record_as_parent" model="ir.rule"> -->
<!-- <field name="name">Rule Student Profile Record As A Parent</field> -->
<!-- <field name="model_id" ref="model_student_student"/> -->
<!-- <field name="global" eval="True"/> -->
<!-- <field name="domain_force"> [('id','in', user.partner_id.student_ids.ids)]</field> -->
<!-- <field name="groups" eval="[(4, ref('group_school_parent'))]"/> -->
<!-- </record> -->
<record id="rule_student_profile_record_as_parent" model="ir.rule">
<field name="name">Rule Student Profile Record As A Parent</field>
<field name="model_id" ref="model_student_student"/>
<field name="global" eval="True"/>
<field name="domain_force"> [('parent_id.partner_id','=',user.partner_id.id)]</field>
<field name="groups" eval="[(4, ref('group_school_parent'))]"/>
</record>
<!-- Rule For School Standard Record As An Administrator -->
<record id="rule_school_standard_record_as_admin" model="ir.rule">
<field name="name">Rule School Standard Record As An Administrator</field>
<field name="model_id" ref="model_school_standard"/>
<field name="global" eval="True"/>
<field name="domain_force"> ['|','|',('cmp_id.child_ids','child_of',[user.company_id.id]),('cmp_id','child_of',[user.company_id.id]),('cmp_id','=',False)]</field>
<field name="groups" eval="[(4, ref('group_school_administration'))]"/>
</record>
<!-- Record Rule teacher can see standards related to school -->
<record id="rule_school_standard_teacher" model="ir.rule">
<field name="name">Teacher School Standard Record Rule</field>
<field name="model_id" ref="model_school_standard"/>
<field name="global" eval="True"/>
<field name="domain_force">[('school_id.company_id','=',user.company_id.id)]</field>
<field name="groups" eval="[(4, ref('group_school_teacher'))]"/>
</record>
<!-- Rule For News Update Record As A Student & Teacher -->
<record id="rule_student_news_update_record" model="ir.rule">
<field name="name">Rule News Update Record</field>
<field name="model_id" ref="model_student_news"/>
<field name="global" eval="True"/>
<field name="domain_force">[('user_ids.id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_student')),(4, ref('school.group_school_teacher'))]"/>
</record>
<!-- Record Rule parents can see reminder of own child -->
<record id="parents_reminder_record_rule" model="ir.rule">
<field name="name">Parents Reminder Record Rule</field>
<field name="model_id" ref="model_student_reminder"/>
<field name="global" eval="True"/>
<field name="domain_force">[('stu_id.parent_id.partner_id','=',user.partner_id.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_parent'))]"/>
</record>
<!-- Record Rule student can see reminder of their own -->
<record id="student_reminder_record_rule" model="ir.rule">
<field name="name">Student Remainder Record Rule</field>
<field name="model_id" ref="model_student_reminder"/>
<field name="global" eval="True"/>
<field name="domain_force">[('stu_id.user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_student'))]"/>
</record>
<!-- Rule For School Teacher -->
<!-- <record id="rule_school_teacher_own" model="ir.rule"> -->
<!-- <field name="name">Rule School Teacher Self</field> -->
<!-- <field name="model_id" ref="hr.model_hr_employee"/> -->
<!-- <field name="global" eval="True"/> -->
<!-- <field name="domain_force"> [('user_id','=',user.id)]</field> -->
<!-- <field name="groups" eval="[(4, ref('school.group_school_teacher'))]"/> -->
<!-- </record> -->
<record id="rule_personal_school_teacher" model="ir.rule">
<field name="name">Rule Personal teacher Record</field>
<field name="model_id" ref="model_school_teacher"/>
<field name="domain_force">[('employee_id.user_id.id', '=', user.id)]</field>
<field name="groups" eval="[(4, ref('group_school_teacher'))]"/>
</record>
<!-- Rule For Parent Profile Record As A Parent -->
<record id="rule_school_parents" model="ir.rule">
<field name="name">Rule Parent Profile Record As A Parent</field>
<field name="model_id" ref="model_school_parent"/>
<field name="global" eval="True"/>
<field name="domain_force"> [('partner_id','=', user.partner_id.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_parent'))]"/>
</record>
<!-- Record Rule student can see own parent -->
<record id="rule_stud_parent" model="ir.rule">
<field name="name">Record rule student can see own parent</field>
<field name="model_id" ref="model_school_parent"/>
<field name="global" eval="True"/>
<field name="domain_force"> [('student_id.user_id','=', user.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_student'))]"/>
</record>
<!-- Rule For Student Profile Record in Adminssion -->
<record id="rule_student_profile_record_as_student_in_admisssion" model="ir.rule">
<field name="name">Rule Student Profile Record As A Student for in Adminssion </field>
<field name="model_id" ref="model_student_student"/>
<field name="global" eval="True"/>
<field name="domain_force">[('user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('group_is_admission'))]"/>
</record>
</data>
</odoo>
.o_column_quick_create {
display:none
}
.o_column_delete {
display:none !important;
}
# See LICENSE file for full copyright and licensing details.
# ----------------------------------------------------------
# A Module to School Management System
# ----------------------------------------------------------
from . import test_school
# See LICENSE file for full copyright and licensing details.
from odoo.tests import common
class TestSchool(common.TransactionCase):
def setUp(self):
super(TestSchool, self).setUp()
self.student_student_obj = self.env['student.student']
self.teacher_obj = self.env['school.teacher']
self.parent_obj = self.env['school.parent']
self.school_school_obj = self.env['school.school']
self.school_standard_obj = self.env['school.standard']
self.res_company_obj = self.env['res.company']
self.assign_roll_obj = self.env['assign.roll.no']
self.school_id = self.env.ref('school.demo_school_1')
self.standard_medium = self.env.ref('school.demo_standard_medium_1')
self.year = self.env.ref('school.demo_academic_year_2')
self.currency_id = self.env.ref('base.INR')
self.sch = self.env.ref('school.demo_school_1')
self.country_id = self.env.ref('base.in')
self.std = self.env.ref('school.demo_standard_standard_1')
self.state_id = self.env.ref('base.state_in_gj')
self.subject1 = self.env.ref('school.demo_subject_subject_1')
self.subject2 = self.env.ref('school.demo_subject_subject_2')
self.student_student = self.env.ref('school.demo_student_student_2')
self.student_done = self.env.ref('school.demo_student_student_6')
self.parent = self.env.ref('school.demo_student_parent_1')
student_list = [self.student_done.id]
self.student_student._compute_student_age()
self.student_student.check_age()
self.student_student.admission_done()
self.student_student.set_alumni()
self.parent.student_id = [(6, 0, student_list)]
# Create academic Year
self.academic_year_obj = self.env['academic.year']
self.academic_year = self.academic_year_obj.\
create({'sequence': 7,
'code': '2012',
'name': '2012 Year',
'date_start': '2012-01-01',
'date_stop': '2012-12-31'
})
self.academic_year._check_academic_year()
self.academic_month_obj = self.env['academic.month']
# Academic month created
self.academic_month = self.academic_month_obj.\
create({'name': 'May',
'code': 'may',
'date_start': '2012-05-01',
'date_stop': '2012-05-31',
'year_id': self.academic_year.id
})
self.academic_month._check_duration()
self.academic_month._check_year_limit()
self.assign_roll_no = self.assign_roll_obj.\
create({'standard_id': self.std.id,
'medium_id': self.standard_medium.id
})
self.assign_roll_no.assign_rollno()
def test_school(self):
self.assertEqual(self.student_student.school_id,
self.student_student.standard_id.school_id)
<?xml version="1.0" ?>
<odoo>
<data>
<!-- search View Of Parent's Profiles -->
<record id="view_school_parent_search" model="ir.ui.view">
<field name="name">school.parent.search</field>
<field name="model">school.parent</field>
<field name="arch" type="xml">
<search string="Search Parent">
<field name="name" filter_domain="['|','|',('display_name','ilike',self),('ref','=',self),('email','ilike',self)]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
</search>
</field>
</record>
<!-- tree View Of Parent's Profiles -->
<record id="view_school_parent_tree" model="ir.ui.view">
<field name="name">school.parent.tree</field>
<field name="model">school.parent</field>
<field name="arch" type="xml">
<tree string="Parents">
<field name="name"/>
<field name="relation_id"/>
<field name="phone"/>
<field name="email"/>
<field name="city"/>
<field name="country_id"/>
</tree>
</field>
</record>
<!-- Form View Of Parent's Profiles -->
<record id="view_school_parent_form" model="ir.ui.view">
<field name="name">school.parent.form</field>
<field name="model">school.parent</field>
<field name="arch" type="xml">
<form string="Parents">
<sheet>
<field name="type" invisible="1"/>
<!-- <field name="image" widget="image" class="oe_avatar" options="{&quot;preview_image&quot;: &quot;image_medium&quot;, &quot;size&quot;: [90, 90]}"/> -->
<div class="oe_title">
<h1>
<field name="name" default_focus="1" placeholder="Name" attrs="{'required' : [('type', '=', 'contact')]}"/>
</h1>
</div>
<div>
<label for="relation_id"/>
<field name="relation_id"/>
</div>
<group>
<group string="Postal Address" name="postal_address">
<label for="street" string="Address"/>
<div class="o_address_format">
<field name="street" placeholder="Street..." class="o_address_street"/>
<field name="street2" placeholder="Street 2..." class="o_address_street"/>
<field name="city" placeholder="City" class="o_address_city"/>
<field name="state_id" class="o_address_state" placeholder="State"
options="{&quot;no_open&quot;: True}"
context="{'country_id': country_id, 'zip': zip}"/>
<field name="zip" placeholder="ZIP" class="o_address_zip"/>
<field name="country_id" placeholder="Country" class="o_address_country"
options="{&quot;no_open&quot;: True, &quot;no_create&quot;: True}"/>
</div>
</group>
<group string="Communication" name="communication">
<field name="phone" widget="phone"/>
<field name="mobile" widget="phone"/>
<field name="user_ids" invisible="1"/>
<field name="email" widget="email" required="1"/>
<field name="title" options="{&quot;no_open&quot;: True}"/>
<field name="lang"/>
<field name="category_id" widget="many2many_tags" placeholder="Tags..."/>
</group>
</group>
<notebook>
<page name="children" string="Children">
<field name="student_id" colspan="4" domain="[('state','=','done')]"/>
</page>
<page name="internal_notes" string="Internal Notes">
<field name="comment" placeholder="Internal note..."/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Action View Of school parent-->
<record id="action_school_parent_form" model="ir.actions.act_window">
<field name="name">Parent Profile</field>
<field name="res_model">school.parent</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_res_partner_form" name="Parents" parent="menu_students_parents"
action="action_school_parent_form" sequence="33"
groups="school.group_school_administration,school.group_school_student,school.group_school_teacher,school.group_school_parent"/>
</data>
</odoo>
<?xml version="1.0" ?>
<odoo>
<data>
<!-- search View Of Teahcer's Profiles -->
<record id="view_school_teacher_search" model="ir.ui.view">
<field name="name">school.teacher.search</field>
<field name="model">school.teacher</field>
<field name="arch" type="xml">
<search string="Employees">
<field name="name" string="Employees" filter_domain="['|',('work_email','ilike',self),('name','ilike',self)]"/>
<field name="department_id"/>
<field name="category_ids" groups="hr.group_hr_user"/>
<field name="job_id"/>
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group expand="0" string="Group By">
<filter name="manager" string="Manager" domain="[]" context="{'group_by':'parent_id'}"/>
<filter name="coach" string="Coach" domain="[]" context="{'group_by':'coach_id'}"/>
<filter name="department" string="Department" domain="[]" context="{'group_by':'department_id'}"/>
<filter name="job" string="Job" domain="[]" context="{'group_by':'job_id'}"/>
<filter name="company" string="Company" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
</group>
</search>
</field>
</record>
<!-- tree View Of Teahcer's Profiles -->
<record id="view_school_teacher_tree" model="ir.ui.view">
<field name="name">school.teacher.tree</field>
<field name="model">school.teacher</field>
<field name="arch" type="xml">
<tree string="Faculty" decoration-bf="message_needaction==True">
<field name="name"/>
<field name="work_phone" invisible="1"/>
<field name="phone_numbers"/>
<field name="work_email"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="department_id"/>
<field name="job_id"/>
<field name="parent_id"/>
<field name="coach_id" invisible="1"/>
<field name="message_needaction" invisible="1"/>
</tree>
</field>
</record>
<!-- Form View Of Teahcer's Profiles -->
<record id="view_school_teacher_form" model="ir.ui.view">
<field name="name">school.teacher.form</field>
<field name="model">school.teacher</field>
<field name="arch" type="xml">
<form string="Faculty">
<sheet>
<!-- <field name="image" widget="image" class="oe_avatar" options="{&quot;preview_image&quot;:&quot;image_medium&quot;}"/>
--> <div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name" placeholder="Teacher's Name" required='1'/>
</h1>
</div>
<field name="category_ids" widget="many2many_tags" placeholder="e.g. Part Time" groups="hr.group_hr_user"/>
<group>
<field name="standard_id" widget="selection"/>
<!-- <field name="standard_ids" required="1" widget="many2many_tags"/> -->
<field name="subject_id" required="1" widget="many2many_tags" options="{'no_create': True}"/>
<field name="school_id" widget="selection"/>
</group>
<group>
<field name="is_parent" widget="boolean_toggle"/>
<field name='stu_parent_id'
attrs="{'invisible':[('is_parent','=',False)],'required': [('is_parent','!=',False)]}"/>
</group>
<notebook>
<page name="public" string="Public Information">
<group>
<group string="Contact Information">
<field name="address_id" context="{'show_address': 1}" options="{&quot;always_reload&quot;: True, &quot;highlight_first_line&quot;: True}" string="Work Address"/>
<field name="mobile_phone" />
<field name="work_location" />
<field name="work_email" widget="email" required="1"/>
<field name="work_phone" invisible="1"/>
<field name="phone_numbers"/>
</group>
<group string="Position">
<field name="department_id"/>
<field name="job_id"/>
<field name="parent_id"/>
<field name="coach_id"/>
</group>
</group>
<field name="notes" placeholder="Other Information ..." colspan="4"/>
</page>
<page string="Personal Information" groups="hr.group_hr_user">
<group>
<group string="Citizenship &amp; Other Information">
<field name="country_id" options="{&quot;no_open&quot;: True, &quot;no_create&quot;: True}"/>
<field name="identification_id" groups="hr.group_hr_user"/>
<field name="passport_id" groups="hr.group_hr_user"/>
<field name="bank_account_id"/>
</group>
<group string="Contact Information">
<field name="address_home_id" context="{'show_address': 1}" options="{&quot;always_reload&quot;: True, &quot;highlight_first_line&quot;: True}"/>
</group>
<group string="Status">
<field name="gender"/>
<field name="marital"/>
</group>
<group string="Birth">
<field name="birthday"/>
</group>
</group>
</page>
<page string="Children" attrs="{'invisible': [('is_parent','=', False)]}">
<field name="student_id" domain="[('state', '=', 'done')]"/>
</page>
<page string="HR Settings" groups="hr.group_hr_user" invisible="1">
<group>
<group string="Status" name="active_group">
<field name="company_id" groups="base.group_multi_company"/>
<field name="user_id" string="Related User" context="{'default_groups_ref': ['base.group_user']}"/>
</group>
</group>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Action View Of school teacher-->
<record id="action_school_teacher_form" model="ir.actions.act_window">
<field name="name">Teacher Profile</field>
<field name="res_model">school.teacher</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="teacher_profile_menu" name="Teachers" action="action_school_teacher_form"
parent="menu_students_parents" sequence="32"
groups="school.group_school_administration,school.group_school_teacher"/>
</data>
</odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="assets_backend" name="school assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/school/static/src/scss/schoolcss.scss"/>
</xpath>
</template>
</data>
</odoo>
# See LICENSE file for full copyright and licensing details.
from . import assign_roll_no
from . import move_standards
from . import wiz_send_email
from . import teriminate_reason
# See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class AssignRollNo(models.TransientModel):
'''designed for assigning roll number to a student'''
_name = 'assign.roll.no'
_description = 'Assign Roll Number'
standard_id = fields.Many2one('school.standard', 'Class', required=True)
medium_id = fields.Many2one('standard.medium', 'Medium', required=True)
def assign_rollno(self):
'''Method to assign roll no to students'''
student_obj = self.env['student.student']
# Search Student
for rec in self:
student_ids = student_obj.search([
('standard_id', '=', rec.standard_id.id),
('medium_id', '=', rec.medium_id.id)],
order="name")
# Assign roll no according to name.
number = 1
for student in student_ids:
number += 1
student.write({'roll_no': number})
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Assign Roll Number Wizard Form View -->
<record id="view_assign_roll_no_form" model="ir.ui.view">
<field name="name">assign.roll.no.form</field>
<field name="model">assign.roll.no</field>
<field name="arch" type="xml">
<form string="Assigning Roll Number">
<separator string="Assign Roll Number" colspan="4"/>
<group colspan="4" col="6">
<field name="standard_id" widget="selection" />
<field name="medium_id" widget="selection" />
</group>
<footer>
<button class="btn btn-sm btn-default fa fa-ban" special="cancel" string="Close"/>
<button class="btn btn-sm btn-default fa fa-plus" name="assign_rollno" string="Finish" type="object"/>
</footer>
</form>
</field>
</record>
<!-- Action Of Form Views Of Assign Roll Number -->
<record id="action_assign_roll_no_form" model="ir.actions.act_window">
<field name="name">Assign Roll Number</field>
<field name="res_model">assign.roll.no</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_assign_roll_no_form" />
<field name="target">new</field>
</record>
<!-- MenuItem For Configurations->Move Classes -->
<menuitem id="menu_assign_rollno_form" name="Assign Roll Number" parent="menu_configuration" action="action_assign_roll_no_form" />
</odoo>
# See LICENSE file for full copyright and licensing details.
from odoo import models, fields
class MoveStandards(models.TransientModel):
"""Defining TransientModel to move standard."""
_name = 'move.standards'
_description = "Move Standards"
academic_year_id = fields.Many2one('academic.year', 'Academic Year',
required=True)
def move_start(self):
'''Code for moving student to next standard'''
academic_obj = self.env['academic.year']
school_stand_obj = self.env['school.standard']
standard_obj = self.env["standard.standard"]
student_obj = self.env['student.student']
done_rec = student_obj.search([('state', '=', 'done')])
for stud in done_rec:
year_id = academic_obj.next_year(stud.year.sequence)
academic_year = academic_obj.search([('id', '=', year_id)],
limit=1)
standard_seq = stud.standard_id.standard_id.sequence
next_class_id = standard_obj.next_standard(standard_seq)
# Assign the academic year
if next_class_id:
division = (stud.standard_id.division_id.id or False)
next_stand = school_stand_obj.search([
('standard_id', '=', next_class_id),
('division_id', '=', division),
('school_id', '=', stud.school_id.id),
('medium_id', '=', stud.medium_id.id)])
if next_stand:
std_vals = {'year': academic_year.id,
'standard_id': next_stand.id}
# Move student to next standard
stud.write(std_vals)
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Assign Roll Number Wizard Form View -->
<record id="view_move_standards_form" model="ir.ui.view">
<field name="name">move_standards.form</field>
<field name="model">move.standards</field>
<field name="arch" type="xml">
<form string="Move Classes">
<group>
<field name="academic_year_id" placeholder="Enter Academic Year" widget="selection"/>
</group>
<footer>
<button class="btn btn-sm btn-default fa fa-ban" special="cancel" string="Close"/>
<button class="btn btn-sm btn-default fa fa-plus" name="move_start" string="Move" type="object"/>
</footer>
</form>
</field>
</record>
<!-- Action Of Form & Tree Views Of Move Classes -->
<record id="action_move_standards_form" model="ir.actions.act_window">
<field name="name">Move Classes</field>
<field name="res_model">move.standards</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_move_standards_form" />
<field name="target">new</field>
</record>
<!-- MenuItem For Configurations->Move Classes -->
<menuitem id="menu_move_standards_form" name="Move Classes" parent="menu_configuration" action="action_move_standards_form" />
</odoo>
# See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class TerminateReason(models.TransientModel):
"""Defining TransientModel to terminate reason."""
_name = "terminate.reason"
_description = "Terminate Reason"
reason = fields.Text('Reason')
def save_terminate(self):
'''Method to terminate student and change state to terminate.'''
self.env['student.student'].browse(
self._context.get('active_id')).write({
'state': 'terminate',
'terminate_reason': self.reason,
'active': False})
student_rec = self.env['student.student'].browse(
self._context.get('active_id'))
student_rec.standard_id._compute_total_student()
user = self.env['res.users'].search([
('id', '=', student_rec.user_id.id)])
student_reminder = self.env['student.reminder'].search([
('stu_id', '=', student_rec.id)])
for rec in student_reminder:
rec.active = False
if user:
user.active = False
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Form View of terminate student wizard -->
<record id="school_terminate_reason" model="ir.ui.view">
<field name="name">Terminate Reason</field>
<field name="model">terminate.reason</field>
<field name="arch" type="xml">
<form string="Terminate Wizard">
<sheet>
<group>
<field name="reason" required="1" nolabel="1" placeholder="Reason"/>
</group>
<footer>
<button name="save_terminate" string="Terminate" type="object"/>
<button special="cancel" string="Cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
<!-- Action of Terminate Student Wizard -->
<record id="action_terminate_wizard" model="ir.actions.act_window">
<field name="name">Termination Reason</field>
<field name="res_model">terminate.reason</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</odoo>
# See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class MailTemplate(models.Model):
_inherit = "mail.template"
def generate_email(self, res_ids, fields=None):
'''Method to generate email.'''
ret = super(MailTemplate, self).generate_email(res_ids, fields=fields)
if (self._context.get('body_html', False) or
self._context.get('subject', False) or
self._context.get('email_to', False)):
ret['body_html'] = self._context['body_text']
ret['subject'] = self._context['subject']
ret['email_to'] = self._context['email_to']
return ret
#
#
class SendMail(models.TransientModel):
"""Defining TransientModel to send mail."""
_name = "send.email"
_description = "Send Mail"
note = fields.Text('Text')
def send_email(self):
'''Method to send email.'''
body = ''
email_template_obj = self.env['mail.template']
# search the model student.student
template_id = email_template_obj.search([
('model', '=', 'student.student')],
limit=1)
if template_id:
for i in self:
body += '\n' + i.note
email_template_obj.send_mail(template_id.id,
self._context.get('active_id'),
force_send=True)
return {'type': 'ir.actions.act_window_close'}
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Form View Of Send Mail -->
<record id="wiz_send_email_form_view" model="ir.ui.view">
<field name="name">send.email.form</field>
<field name="model">send.email</field>
<field name="arch" type="xml">
<form string="Send Email">
<field name='note' nolabel="0" height="350" width="350" placeholder="Notes"/>
<br/>
<footer>
<button name="send_email" string="Send Email" class="btn btn-sm btn-default fa fa-envelope" type="object"/>
<button special="cancel" string="Cancel"/>
</footer>
</form>
</field>
</record>
<!-- Action Of Form View Of Send Mail -->
<record id="act_send_email" model="ir.actions.act_window">
<field name="name">Send Email</field>
<field name="res_model">send.email</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="binding_model_id" ref="model_student_student"/>
<field name="binding_view_types">form</field>
<field name="groups_id" eval="[(4, ref('school.group_school_administration')),
(4, ref('school.group_school_teacher'))]"/>
</record>
</odoo>
=========
Timetable
=========
This module was written to extend the functionality of timetable management to support school management and allows you to manage timetable through this functionality.
Installation
============
To install this module, you need to:
install school module
Configuration
=============
To configure this module, you need to:
have a school Management functionality.
Usage
=====
To use this module, you need to:
go to apps, then install module to apply this functionality.
Try me on Runbot
Known issues / Roadmap
Bug Tracker
===========
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed feedback here.
=======
Credits
=======
Contributors
============
Serpent Consulting Services PVT. LTD. <http://serpentcs.com>
Maintainer
==========
Serpent Consulting Services PVT. LTD.
This module is maintained by the SerpentCS.
To contribute to this module, please visit http://serpentcs.com.
# See LICENSE file for full copyright and licensing details.
# ----------------------------------------------------------
# A Module for School Timetable Management System
# ----------------------------------------------------------
from . import models
from . import report
# See LICENSE file for full copyright and licensing details.
{
'name': 'Timetable Management',
'version': '14.0.1.0.0',
'author': '''Serpent Consulting Services Pvt. Ltd.''',
'website': 'http://www.serpentcs.com',
'license': "AGPL-3",
'category': 'School Management',
'complexity': 'easy',
'summary': 'A Module For Timetable Management In School',
'images': ['static/description/SchoolTimetable.png'],
'depends': ['school'],
'data': ['security/timetable_security.xml',
'security/ir.model.access.csv',
'report/report_view.xml',
'report/timetable.xml',
'views/timetable_view.xml',],
'demo': ['demo/timetable_demo.xml'],
'installable': True,
'application': True
}
# See LICENSE file for full copyright and licensing details.
from . import timetable
# See LICENSE file for full copyright and licensing details.
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class TimeTable(models.Model):
"""Defining model for time table."""
_description = 'Time Table'
_name = 'time.table'
@api.depends('timetable_ids')
def _compute_user(self):
'''Method to compute user.'''
for rec in self:
rec.user_ids = [teacher.teacher_id.employee_id.user_id.id
for teacher in rec.timetable_ids
]
name = fields.Char('Description', help='Enter description of timetable')
standard_id = fields.Many2one('school.standard', 'Academic Class',
required=True,
help="Select Standard")
year_id = fields.Many2one('academic.year', 'Year', required=True,
help="Select academic year")
timetable_ids = fields.One2many('time.table.line', 'table_id', 'TimeTable',
help='Enter the timetable pattern')
timetable_type = fields.Selection([('regular', 'Regular')],
'Time Table Type', default="regular",
invisible=True,
help='Select time table type')
user_ids = fields.Many2many('res.users', string="Users",
compute="_compute_user", store=True,
help='Teachers following this timetable')
class_room_id = fields.Many2one('class.room', 'Room Number',
help='''Class room in which tome table
would be followed''')
@api.constrains('timetable_ids')
def _check_lecture(self):
'''Method to check same lecture is not assigned on same day.'''
if self.timetable_type == 'regular':
domain = [('table_id', 'in', self.ids)]
line_ids = self.env['time.table.line'].search(domain)
for rec in line_ids:
records = [rec_check.id for rec_check in line_ids
if (rec.week_day == rec_check.week_day and
rec.start_time == rec_check.start_time and
rec.end_time == rec_check.end_time and
rec.teacher_id.id == rec.teacher_id.id)]
if len(records) > 1:
raise ValidationError(_('''
You cannot set lecture at same time %s at same day %s for teacher %s.!
''') % (rec.start_time, rec.week_day, rec.teacher_id.name))
# Checks if time is greater than 24 hours than raise error
if rec.start_time > 24 or rec.end_time > 24:
raise ValidationError(_('''
Start and End Time should be less than 24 hours!'''))
class TimeTableLine(models.Model):
"""Defining model for time table."""
_description = 'Time Table Line'
_name = 'time.table.line'
_rec_name = 'table_id'
@api.constrains('teacher_id', 'subject_id')
def check_teacher(self):
'''Check if lecture is not related to teacher than raise error.'''
for rec in self:
if (rec.teacher_id.id not in rec.subject_id.teacher_ids.ids and
rec.table_id.timetable_type == 'regular'):
raise ValidationError(_('''
The subject %s is not assigned to teacher %s.
''') % (rec.subject_id.name, rec.teacher_id.name))
teacher_id = fields.Many2one('school.teacher', 'Faculty Name',
help="Select Teacher")
subject_id = fields.Many2one('subject.subject', 'Subject Name',
help="Select Subject")
table_id = fields.Many2one('time.table', 'TimeTable')
start_time = fields.Float('Start Time', required=True,
help="Time according to timeformat of 24 hours")
end_time = fields.Float('End Time', required=True,
help="Time according to timeformat of 24 hours")
week_day = fields.Selection([('monday', 'Monday'),
('tuesday', 'Tuesday'),
('wednesday', 'Wednesday'),
('thursday', 'Thursday'),
('friday', 'Friday'),
('saturday', 'Saturday'),
('sunday', 'Sunday')], "Week day",
help='Select weekday for timetable')
class_room_id = fields.Many2one('class.room', 'Room Number',
help='''Class room in which time
table would be followed''')
@api.constrains('teacher_id', 'class_room_id')
def check_teacher_room(self):
"""Check available room for teacher."""
for rec in self:
timetable_rec = self.env['time.table'].search([
('id', '!=', rec.table_id.id)])
for data in timetable_rec:
for record in data.timetable_ids:
if (data.timetable_type == 'regular' and
rec.table_id.timetable_type == 'regular' and
rec.teacher_id == record.teacher_id and
rec.week_day == record.week_day and
rec.start_time == record.start_time):
raise ValidationError(_('''
There is a lecture of Lecturer at same time!'''))
if (data.timetable_type == 'regular' and
rec.table_id.timetable_type == 'regular' and
rec.class_room_id == record.class_room_id and
rec.start_time == record.start_time):
raise ValidationError(_("The room is occupied."))
class SubjectSubject(models.Model):
_inherit = "subject.subject"
@api.model
def _search(self, args, offset=0, limit=None, order=None, count=False,
access_rights_uid=None):
'''Override method to get subject related to teacher.'''
teacher_id = self._context.get('teacher_id')
if teacher_id:
for teacher_data in self.env['school.teacher'].browse(teacher_id):
args.append(('teacher_ids', 'in', [teacher_data.id]))
return super(SubjectSubject, self)._search(
args=args, offset=offset, limit=limit, order=order, count=count,
access_rights_uid=access_rights_uid)
# See LICENSE file for full copyright and licensing details.
from . import timetable_info
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<odoo>
<record id="report_time_table_qweb" model="ir.actions.report">
<field name="name">Timetable</field>
<field name="print_report_name">'Timetable(%s)'%object.standard_id.name</field>
<field name="model">time.table</field>
<field name="binding_model_id" ref="model_time_table"/>
<field name="report_type">qweb-pdf</field>
<field name="report_name">timetable.timetable</field>
<field name="report_file">timetable.timetable</field>
<field name="binding_type">report</field>
</record>
</odoo>
# See LICENSE file for full copyright and licensing details.
from odoo import api, models
class ReportTimetableInfo(models.AbstractModel):
_name = 'report.timetable.timetable'
_description = "Timetable details"
def _get_timetable(self, timetable_id):
"""Method to combain values for timetable"""
timetable_detail = []
self._cr.execute('''select t.start_time,t.end_time,s.name,week_day,
st.employee_id, hr.name as
teacher from time_table_line t,
subject_subject s, resource_resource r, school_teacher
st, hr_employee
hr where t.subject_id= s.id and t.teacher_id=st.id and
st.employee_id= hr.id
and t.table_id = %s
group by start_time,end_time,s.name,week_day,
st.employee_id,hr.name
order by start_time''', tuple([timetable_id.id]))
res = self._cr.dictfetchall()
self._cr.execute('''select start_time,end_time from time_table_line
where table_id=%s group by start_time,end_time
order by start_time''', tuple([timetable_id.id]))
time_data = self._cr.dictfetchall()
for time_detail in time_data:
for data in res:
if ((time_detail.get('start_time') == data.get('start_time'))
and (time_detail.get('end_time') == data.get('end_time'))):
if (data.get('name') == 'Recess'):
time_detail[data['week_day']] = data.get('name')
else:
td = data.get('name') + '\n(' + data.get(
'teacher') + ')'
time_detail[data['week_day']] = td
timetable_detail.append(time_detail)
return timetable_detail
@api.model
def _get_report_values(self, docids, data=None):
"""Inherited method to get report data"""
timetable_report = self.env['ir.actions.report']._get_report_from_name(
'timetable.timetable')
docs = self.env['time.table'].browse(docids)
return {
'doc_ids': docids,
'docs': docs,
'doc_model': timetable_report.model,
'data': data,
'get_timetable': self._get_timetable
}
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_academic_timetable1,time.table,model_time_table,school.group_school_administration,1,1,1,1
access_academic_timetbaleline1,time.table.line,model_time_table_line,school.group_school_administration,1,1,1,1
access_academic_timetable3,time.table,model_time_table,school.group_school_student,1,0,0,0
access_academic_timetbaleline3,time.table.line,model_time_table_line,school.group_school_student,1,0,0,0
access_academic_timetable4,time.table,model_time_table,school.group_school_teacher,1,0,0,0
access_academic_timetbaleline4,time.table.line,model_time_table_line,school.group_school_teacher,1,0,0,0
access_timetable_report_parent,time.table,model_time_table,school.group_school_parent,1,0,0,0
access_timetable_parent_report_line,time.table,model_time_table_line,school.group_school_parent,1,0,0,0
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>
<odoo>
<!-- Record Rule Of TimeTable For All Users -->
<record id="student_rule_timetable_record" model="ir.rule">
<field name="name">TimeTable Record rule as a student</field>
<field ref="model_time_table" name="model_id"/>
<field eval="1" name="global"/>
<field name="domain_force">[('standard_id.student_ids.user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_student'))]"/>
</record>
<!-- Record Rule Of TimeTable For Parents -->
<record id="parent_rule_timetable_record" model="ir.rule">
<field name="name">TimeTable Record rule as a parents</field>
<field ref="model_time_table" name="model_id"/>
<field eval="1" name="global"/>
<field name="domain_force">[('standard_id.student_ids.parent_id.partner_id','=',user.partner_id.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_parent'))]"/>
</record>
<!-- Record Rule teacher can see only realated lecture to him -->
<record id="timetable_teacher_record_rule" model="ir.rule">
<field name="name">Teacher Timetable Record Rule</field>
<field name="model_id" ref="model_time_table"/>
<field name="global" eval="True"/>
<field name="domain_force">[('user_ids','in',user.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_teacher'))]"/>
</record>
<!-- REcord Rule time table line -->
<record id="timetableline_teacher_record_rule" model="ir.rule">
<field name="name">Teacher TimetableLine Record Rule</field>
<field name="model_id" ref="model_time_table_line"/>
<field name="global" eval="True"/>
<field name="domain_force">[('teacher_id.employee_id.user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('school.group_school_teacher'))]"/>
</record>
<!-- Record Rule Parents on timetable line -->
<record id="timetableline_record_rule_parents" model="ir.rule">
<field name="name">Parent TimetableLine Record Rule</field>
<field name="model_id" ref="model_time_table_line"/>
<field name="global" eval="True"/>
<field name="domain_force">[]</field>
<field name="groups" eval="[(4, ref('school.group_school_parent'))]"/>
</record>
</odoo>
# See LICENSE file for full copyright and licensing details.
# ----------------------------------------------------------
# A Module to Assignment Management System
# ----------------------------------------------------------
from . import test_timetable
# See LICENSE file for full copyright and licensing details.
from odoo.exceptions import UserError, ValidationError
from odoo.tests import common
class TestTimetable(common.TransactionCase):
def setUp(self):
super(TestTimetable, self).setUp()
self.time_table_obj = self.env['time.table']
self.time_table_line_obj = self.env['time.table.line']
self.stander_id = self.env.ref('school.demo_standard_standard_2')
self.year_id = self.env.ref('school.demo_academic_year_1')
self.subject_id = self.env.ref('school.demo_subject_subject_2')
self.teacher_id = self.env.ref('school.demo_school_teacher_1')
self.table_id = self.env.ref('timetable.time_table_firsts0')
self.room_id = self.env.ref('school.class_room15')
# Create time-table
self.time_table = self.time_table_obj.\
create({'name': 'Test Timetable',
'standard_id': self.stander_id.id,
'year_id': self.year_id.id,
'timetable_type': 'regular',
})
# Create timetable line
self.time_table_line = self.time_table_line_obj.\
create({'week_day': 'monday',
'teacher_id': self.teacher_id.id,
'subject_id': self.subject_id.id,
'start_time': '17.0',
'end_time': '18.0',
'table_id': self.time_table.id,
'class_room_id': self.room_id.id
})
def test_timetable(self):
self.assertIn(self.subject_id, self.teacher_id.subject_id)
<?xml version="1.0"?>
<!DOCTYPE html>
<odoo>
<!-- Form View Of Time Table Information -->
<record id="view_time_table_form" model="ir.ui.view">
<field name="name">time.table.form</field>
<field name="model">time.table</field>
<field name="arch" type="xml">
<form string="TimeTable">
<sheet>
<group col="4" colspan="4">
<field name="name" placeholder="Enter Description"/>
<field name="standard_id" placeholder="Select Standard" widget="selection"/>
<field name="year_id" placeholder="Select Year" widget="selection"/>
<field name="class_room_id" options="{&quot;no_create&quot;: True}" invisible="1"/>
<field name="user_ids" invisible="1"/>
</group>
<notebook colspan="4">
<page string="TimeTable">
<field name="timetable_ids" nolabel="1" colspan="4">
<tree string="TimeTable" editable="top">
<field name="week_day"/>
<field name="subject_id" required="1" options='{"no_open": True, "no_create": True}'/>
<field name="start_time"/>
<field name="end_time"/>
<field name="teacher_id" options='{"no_open": True, "no_create": True}' required="1"/>
<field name="class_room_id" options='{"no_open": True, "no_create": True}'/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<!-- Tree View Of Time Table Information -->
<record id="view_time_table_tree" model="ir.ui.view">
<field name="name">time.table.tree</field>
<field name="model">time.table</field>
<field name="arch" type="xml">
<tree string="TimeTable">
<field name="name"/>
<field name="standard_id"/>
<field name="year_id"/>
</tree>
</field>
</record>
<!-- Search View Time Table Information -->
<record id="timetable_search" model="ir.ui.view">
<field name="name">time.table.search</field>
<field name="model">time.table</field>
<field name="arch" type="xml">
<search string="TimeTable">
<field name="name"/>
<field name="standard_id"/>
<field name="year_id"/>
<newline/>
<group expand="1" string="Group By">
<filter name="class" string="Academic Class" help="By class"
context="{'group_by':'standard_id'}"/>
<filter name="year" string="Year" help="By year" context="{'group_by':'year_id'}"/>
</group>
</search>
</field>
</record>
<!-- Actions Of Form & Tree Views Of Time Table Information -->
<record id="action_timetable_regular" model="ir.actions.act_window">
<field name="name">Regular Timetable</field>
<field name="res_model">time.table</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('timetable_type','=','regular')]</field>
<field name="context">{'default_timetable_type':'regular'}</field>
</record>
<!-- Menu items of Timetable -->
<menuitem id="menu_timetable_1" name="TimeTable" parent="school.menu_ems" groups="school.group_school_administration,school.group_school_teacher,school.group_school_student,school.group_school_parent" sequence="6"/>
<menuitem id="menu_timetable_regular" name="Regular Timetable" parent="menu_timetable_1" action="action_timetable_regular" groups="school.group_school_administration,school.group_school_teacher,school.group_school_student,school.group_school_parent" sequence="61"/>
</odoo>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!