# -*- coding: utf-8 -*- ############################################################################## # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 Tiny SPRL (). # Copyright (C) 2011-2012 Serpent Consulting Services () # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # ############################################################################## from osv import fields,osv import time from datetime import datetime from tools.translate import _ class academic_year(osv.osv): ''' Defining an academic year ''' _name = "academic.year" _description = "Academic Year" _order = "sequence" _columns = { 'sequence': fields.integer('Sequence', required=True), 'name': fields.char('Name', size=64, required=True, select=1), 'code': fields.char('Code', size=6, required=True, select=1), 'date_start': fields.date('Start Date', required=True), 'date_stop': fields.date('End Date', required=True), 'month_ids': fields.one2many('academic.month', 'year_id', 'Months'), } _order = "date_start" def next_year(self, cr, uid, sequence, context=None): year_ids = self.search(cr, uid, [('sequence', '>', sequence)]) if year_ids: return year_ids[0] return False def name_get(self, cr, uid, ids, context=None): res = [] for acd_year_rec in self.read(cr, uid, ids, context=context): nam = "[" + acd_year_rec['code'] + "]" + acd_year_rec['name'] res.append((acd_year_rec['id'],nam)) return res def _check_academic_year(self, cr, uid, ids, context=None): obj_academic_ids = self.search(cr, uid, [], context) for current_academic_yr in self.browse(cr, uid, ids, context=context): obj_academic_ids.remove(current_academic_yr.id) data_academic_yr = self.browse(cr, uid, obj_academic_ids, context=context) for old_ac in data_academic_yr: if old_ac.date_start <= current_academic_yr.date_start <= old_ac.date_stop or \ old_ac.date_start <= current_academic_yr.date_stop <= old_ac.date_stop: return False return True def _check_duration(self, cr, uid, ids, context=None): for obj_ac in self.browse(cr, uid, ids, context=context): if obj_ac.date_stop < obj_ac.date_start: return False return True _constraints = [ (_check_duration, 'Error! The duration of the academic year is invalid. ', ['date_stop']), (_check_academic_year, 'Error! You cannot define overlapping academic years',['date_start', 'date_stop']) ] academic_year() class academic_month(osv.osv): ''' Defining a month of an academic year ''' _name = "academic.month" _description = "Academic Month" _columns = { 'name': fields.char('Name', size=64, required=True, select=1), 'code': fields.char('Code', size=12, required=True, select=1), 'date_start': fields.date('Start of Period', required=True), 'date_stop': fields.date('End of Period', required=True), 'year_id': fields.many2one('academic.year', 'Academic Year', required=True, select=1), } _order = "date_start" def _check_duration(self, cr, uid, ids, context=None): for obj_month in self.browse(cr, uid, ids, context=context): if obj_month.date_stop < obj_month.date_start: return False return True def _check_year_limit(self,cr,uid,ids,context=None): for obj_month in self.browse(cr, uid, ids, context=context): if obj_month.year_id.date_stop < obj_month.date_stop or \ obj_month.year_id.date_stop < obj_month.date_start or \ obj_month.year_id.date_start > obj_month.date_start or \ obj_month.year_id.date_start > obj_month.date_stop: return False return True _constraints = [ (_check_duration, 'Error ! The duration of the Month(s) is/are invalid. ', ['date_stop']), (_check_year_limit, 'Invalid Months ! Some months overlap or the date period is not in the scope of the academic year. ', ['date_stop']) ] academic_month() class standard_medium(osv.osv): ''' Defining a medium(English, Hindi, Gujarati) related to standard''' _name = "standard.medium" _description = "Standard Medium" _order = "sequence" _columns = { 'sequence': fields.integer('Sequence', required=True), 'name': fields.char('Name', size=64, required=True, select=1), 'code': fields.char('Code', size=12, required=True, select=1), } standard_medium() class standard_division(osv.osv): ''' Defining a division(A, B, C) related to standard''' _name = "standard.division" _description = "Standard Division" _order = "sequence" _columns = { 'sequence': fields.integer('Sequence', required=True), 'name': fields.char('Name', size=64, required=True, select=1), 'code': fields.char('Code', size=12, required=True, select=1), } standard_division() class school_school(osv.osv): ''' Defining School Information ''' _description ='School Information' _name = 'school.school' _columns = { 'name': fields.char('Name', size=64, required=True, select=1), 'code': fields.char('Code', size=20, required=True, select=1), 'standards':fields.one2many('school.standard', 'school_id','Standards'), } school_school() class standard_standard(osv.osv): ''' Defining Standard Information ''' _description ='Standard Information' _name = 'standard.standard' _order = "sequence" _columns = { 'sequence': fields.integer('Sequence', required=True), 'name': fields.char('Name', size=64, required=True, select=1), 'code': fields.char('Code', size=20, required=True, select=1), } def next_standard(self, cr, uid, sequence, context=None): stand_ids = self.search(cr, uid, [('sequence', '>', sequence)]) if stand_ids: return stand_ids[0] return False standard_standard() class school_standard(osv.osv): ''' Defining a standard related to school ''' _description ='School Standards' _name = 'school.standard' _rec_name ="school_id" # def _compute_subject(self, cr, uid, ids, name, args, context=None): # ''' This function will automatically computes the subjects related to particular standard.''' # result = {} # subject_obj = self.pool.get('subject.subject') # for id in ids: # subject_ids = subject_obj.search(cr, uid, [('standard_ids.id','=',id)]) # result[id] = subject_ids # return result def _compute_student(self, cr, uid, ids, name, args, context=None): ''' This function will automatically computes the students related to particular standard.''' result = {} student_obj = self.pool.get('student.student') for standard_data in self.browse(cr, uid, ids, context=context): student_ids = student_obj.search(cr, uid,[('class_id','=',standard_data.standard_id.id), ('division_id','=',standard_data.division_id.id), ('medium_id','=',standard_data.medium_id.id)]) result[standard_data.id] = student_ids return result _columns = { 'school_id': fields.many2one('school.school', 'School', required=True), 'standard_id':fields.many2one('standard.standard', 'Class', required=True), 'division_id':fields.many2one('standard.division', 'Division', required=True), 'medium_id':fields.many2one('standard.medium', 'Medium', required=True), 'subject_ids': fields.many2many('subject.subject', 'subject_standards_rel','subject_id','standard_id','Subject'), 'user_id':fields.many2one('hr.employee', 'Class Teacher'), 'student_ids': fields.function(_compute_student, method=True, relation='student.student', type="one2many", string='Student In Class'), 'color': fields.integer('Color Index'), } def name_get(self, cr, uid, ids, context=None): res = [] for standard in self.browse(cr, uid, ids, context=context): nam = standard.standard_id.name+"[" + standard.division_id.name + "]" res.append((standard.id,nam)) return res school_standard() class subject_subject(osv.osv): '''Defining a subject ''' _name = "subject.subject" _description = "Subjects" _columns = { 'name': fields.char('Name', size=64, required=True, select=1), 'code': fields.char('Code', size=12, required=True, select=1), 'maximum_marks': fields.integer("Maximum marks", size = 5), 'minimum_marks': fields.integer("Minimum marks", size = 5), 'weightage': fields.integer("Weightage", size = 10), 'teacher_ids':fields.many2many('hr.employee','subject_teacher_rel','subject_id','teacher_id','Teachers'), 'standard_ids':fields.many2many('school.standard','subject_standards_rel','standard_id','subject_id','Standards'), } subject_subject() class student_student(osv.osv): ''' Defining a student information ''' def _calc_age(self, cr, uid, ids, name, arg, context=None): ''' This function will automatically calculates the age of particular student.''' res= {} for student in self.browse(cr, uid, ids, context=context): start = datetime.strptime(student.date_of_birth,"%Y-%m-%d") end = datetime.strptime(time.strftime('%Y-%m-%d'),"%Y-%m-%d") delta = end - start years = (delta.days / 365) res[student.id] = years return res _name = 'student.student' _table = "student_student" _description = 'Student Information' _inherits = {'res.partner': 'partner_id'} _columns = { 'partner_id': fields.many2one('res.partner', 'Partner', required=True, ondelete="cascade"), 'pid':fields.char('Student ID', size=64, required=True, readonly=True, help='Personal IDentification Number'), 'roll_no':fields.integer('Roll No.', readonly=True), 'photo': fields.binary('Photo'), 'year':fields.many2one('academic.year', 'Academic Year', required=True, states={'done':[('readonly',True)]}), 'class_id': fields.many2one('standard.standard', 'Class', required=True, states={'done':[('readonly',True)]}), 'division_id': fields.many2one('standard.division', 'Division', required=True, states={'done':[('readonly',True)]}), 'medium_id': fields.many2one('standard.medium', 'Medium', required=True, states={'done':[('readonly',True)]}), 'admission_date':fields.date('Admission Date', readonly=True), 'middle': fields.char('Middle Name', size=64, required=True, states={'done':[('readonly',True)]}), 'last': fields.char('Last Name', size=64, required=True, states={'done':[('readonly',True)]}), 'gender':fields.selection([('male','Male'), ('female','Female')], 'Gender', states={'done':[('readonly',True)]}), 'date_of_birth':fields.date('Birthdate', required=True, states={'done':[('readonly',True)]}), 'home_language':fields.selection([('eng','English'), ('guj','Gujarati')], 'Mother Tongue', states={'done':[('readonly',True)]}), 'age':fields.function(_calc_age, method=True, string='AGE', readonly=True, type="integer"), 'maritual_status':fields.selection([('unmarried','Unmarried'), ('married','Married')], 'Maritual Status', states={'done':[('readonly',True)]}), 'reference_ids':fields.one2many('student.reference', 'reference_id', 'References', states={'done':[('readonly',True)]}), 'previous_school_ids':fields.one2many('student.previous.school', 'previous_school_id', 'Previous School Detail', states={'done':[('readonly',True)]}), 'emergency_contact_ids':fields.one2many('student.emergency.contact', 'emergency_contact_id', 'Emergency Contact Detail', states={'done':[('readonly',True)]}), 'doctor': fields.char('Doctor Name', size=64, states={'done':[('readonly',True)]} ), 'designation': fields.char('Designation', size=64, states={'done':[('readonly',True)]} ), 'doctor_phone': fields.char('Phone', size=12, states={'done':[('readonly',True)]} ), 'blood_group': fields.char('Blood Group', size=12, states={'done':[('readonly',True)]} ), 'height': fields.float('Height', states={'done':[('readonly',True)]}), 'weight': fields.float('Weight', states={'done':[('readonly',True)]} ), 'eye':fields.boolean('Eyes', states={'done':[('readonly',True)]}), 'ear':fields.boolean('Ears', states={'done':[('readonly',True)]}), 'nose_throat':fields.boolean('Nose & Throat', states={'done':[('readonly',True)]}), 'respiratory':fields.boolean('Respiratory', states={'done':[('readonly',True)]}), 'cardiovascular':fields.boolean('Cardiovascular', states={'done':[('readonly',True)]}), 'neurological':fields.boolean('Neurological', states={'done':[('readonly',True)]}), 'muskoskeletal':fields.boolean('Muskoskeletal', states={'done':[('readonly',True)]}), 'dermatological':fields.boolean('Dermatological', states={'done':[('readonly',True)]}), 'blood_pressure':fields.boolean('Blood Pressure', states={'done':[('readonly',True)]}), 'remark':fields.text('Remark', states={'done':[('readonly',True)]}), 'school_id': fields.many2one('school.school', 'School', required=True, states={'done':[('readonly',True)]}), 'state':fields.selection([('draft','Draft'), ('confirm','Confirm'),('cancel','Cancel'), ('done','Done')],'State',readonly=True), 'history_ids': fields.one2many('student.history', 'student_id', 'History'), 'certificate_ids' : fields.one2many('student.certificate','student_id','Certificate'), 'attendance_ids' : fields.one2many('attendance.sheet.line','name','Attendance History',readonly=True), 'exam_results_ids' : fields.one2many('exam.result','student_id','Exam History',readonly=True), 'student_attachment_line' : fields.one2many('student.attachment','student_id','Attachment'), 'student_discipline_line' : fields.one2many('student.descipline','student_id','Descipline') } _defaults = { 'pid': lambda obj, cr, uid, context:obj.pool.get('ir.sequence').get(cr, uid, 'student.student'), 'state':'draft', } def admission_draft(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state' : 'draft'}, context=context) return True def admission_confirm(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state' : 'confirm'}, context=context) return True def admission_cancel(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state' : 'cancel'}, context=context) return True def admission_done(self, cr, uid, ids, context=None): school_standard_obj = self.pool.get('school.standard') for student_data in self.browse(cr, uid, ids, context=context): domain = [('standard_id', '=', student_data.class_id.id), ('medium_id' ,'=', student_data.medium_id.id), ('division_id', '=', student_data.division_id.id)] school_standard_search_ids = school_standard_obj.search(cr, uid, domain, context=context) if not school_standard_search_ids: raise osv.except_osv(_('Warning'), _('The standard is not defined in a school')) domain = [('class_id', '=', student_data.class_id.id), ('medium_id' ,'=', student_data.medium_id.id), ('division_id', '=', student_data.division_id.id)] student_search_ids = self.search(cr, uid, domain, context=context) number = 1 for student in self.browse(cr, uid, student_search_ids, context=context): self.write(cr, uid, student.id, {'roll_no':number}, context=context) number += 1 self.write(cr, uid, ids, {'state': 'done', 'admission_date': time.strftime('%Y-%m-%d')}, context=context) return True student_student() class student_attachment(osv.osv): _name = 'student.attachment' _columns = { 'student_id' : fields.many2one('student.student', 'Student'), 'name':fields.char('Document Name',size=30), 'new_datas' : fields.binary('Attachments'), 'file_name':fields.char('File Name',size=30) } student_attachment() class student_descipline(osv.osv): _name = 'student.descipline' _columns = { 'student_id' : fields.many2one('student.student', 'Student'), 'teacher_id':fields.many2one('hr.employee', 'Teacher'), 'date':fields.date('Date'), 'class_id': fields.many2one('standard.standard', 'Class'), 'note':fields.text('Note'), 'action_taken':fields.text('Action Taken'), } student_descipline() class student_history(osv.osv): _name = "student.history" _columns = { 'student_id': fields.many2one('student.student', 'Student'), 'academice_year_id':fields.many2one('academic.year', 'Academic Year', required=True), 'class_id': fields.many2one('standard.standard', 'Class', required=True), 'division_id': fields.many2one('standard.division', 'Division', required=True), 'medium_id': fields.many2one('standard.medium', 'Medium', required=True), } student_history() class student_certificate(osv.osv): _name = "student.certificate" _columns = { 'student_id' : fields.many2one('student.student', 'Student'), 'description' : fields.char('Description',size=50), 'certi' : fields.binary('Certificate',required =True) } student_certificate() class hr_employee(osv.osv): ''' Defining a teacher information ''' def _compute_subject(self, cr, uid, ids, name, args, context=None): ''' This function will automatically computes the subjects related to particular teacher.''' result = {} subject_obj = self.pool.get('subject.subject') for id in ids: subject_ids = subject_obj.search(cr, uid,[('teacher_ids.id','=',id)]) result[id] = subject_ids return result _name = 'hr.employee' _inherit = 'hr.employee' _description = 'Teacher Information' _columns = { 'subject_ids': fields.function(_compute_subject, method=True, relation='subject.subject', type="many2many", string='Subjects'), } hr_employee() class res_partner_address(osv.osv): ''' Defining a address information ''' _name = 'res.partner.address' _inherit = 'res.partner.address' _description = 'Address Information' _columns = { 'student_id': fields.many2one('student.student', 'Student' ), } res_partner_address() class student_reference(osv.osv): ''' Defining a student reference information ''' _name = "student.reference" _description = "Student Reference" _columns = { 'reference_id': fields.many2one('student.student', 'Student'), 'name': fields.char('First Name', size=64, required=True), 'middle': fields.char('Middle Name', size=64, required=True), 'last': fields.char('Last Name', size=64, required=True), 'designation': fields.char('Designation', size=12, required=True), 'phone': fields.char('Phone', size=12, required=True), 'gender':fields.selection([('male','Male'), ('female','Female')], 'Gender'), } student_reference() class student_previous_school(osv.osv): ''' Defining a student previous school information ''' _name = "student.previous.school" _description = "Student Previous School" _columns = { 'previous_school_id': fields.many2one('student.student', 'Student'), 'name': fields.char('Name', size=64, required=True), 'registration_no': fields.char('Registration No.', size=12, required=True), 'email': fields.char('Email', size=64, required=True), 'admission_date': fields.date('Admission Date'), 'exit_date': fields.date('Exit Date'), 'phone': fields.char('Phone', size=12, required=True), } student_previous_school() class student_emergency_contact(osv.osv): ''' Defining a student emergency contact information ''' _name = "student.emergency.contact" _description = "Student Emergency Contact" _columns = { 'emergency_contact_id': fields.many2one('student.student', 'Student'), 'name': fields.char('Name', size=64, required=True), 'relation': fields.char('Relation', size=64, required=True), 'phone': fields.char('Phone', size=12, required=True), 'email': fields.char('E-Mail', size=150, required=True), } student_emergency_contact() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: