school.py.svn-base 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. # -*- coding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # OpenERP, Open Source Management Solution
  5. # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
  6. # Copyright (C) 2011-2012 Serpent Consulting Services (<http://www.serpentcs.com>)
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ##############################################################################
  22. from osv import fields,osv
  23. import time
  24. from datetime import datetime
  25. from tools.translate import _
  26. class academic_year(osv.osv):
  27. ''' Defining an academic year '''
  28. _name = "academic.year"
  29. _description = "Academic Year"
  30. _order = "sequence"
  31. _columns = {
  32. 'sequence': fields.integer('Sequence', required=True),
  33. 'name': fields.char('Name', size=64, required=True, select=1),
  34. 'code': fields.char('Code', size=6, required=True, select=1),
  35. 'date_start': fields.date('Start Date', required=True),
  36. 'date_stop': fields.date('End Date', required=True),
  37. 'month_ids': fields.one2many('academic.month', 'year_id', 'Months'),
  38. }
  39. _order = "date_start"
  40. def next_year(self, cr, uid, sequence, context=None):
  41. year_ids = self.search(cr, uid, [('sequence', '>', sequence)])
  42. if year_ids:
  43. return year_ids[0]
  44. return False
  45. def name_get(self, cr, uid, ids, context=None):
  46. res = []
  47. for acd_year_rec in self.read(cr, uid, ids, context=context):
  48. nam = "[" + acd_year_rec['code'] + "]" + acd_year_rec['name']
  49. res.append((acd_year_rec['id'],nam))
  50. return res
  51. def _check_academic_year(self, cr, uid, ids, context=None):
  52. obj_academic_ids = self.search(cr, uid, [], context)
  53. for current_academic_yr in self.browse(cr, uid, ids, context=context):
  54. obj_academic_ids.remove(current_academic_yr.id)
  55. data_academic_yr = self.browse(cr, uid, obj_academic_ids, context=context)
  56. for old_ac in data_academic_yr:
  57. if old_ac.date_start <= current_academic_yr.date_start <= old_ac.date_stop or \
  58. old_ac.date_start <= current_academic_yr.date_stop <= old_ac.date_stop:
  59. return False
  60. return True
  61. def _check_duration(self, cr, uid, ids, context=None):
  62. for obj_ac in self.browse(cr, uid, ids, context=context):
  63. if obj_ac.date_stop < obj_ac.date_start:
  64. return False
  65. return True
  66. _constraints = [
  67. (_check_duration, 'Error! The duration of the academic year is invalid. ', ['date_stop']),
  68. (_check_academic_year, 'Error! You cannot define overlapping academic years',['date_start', 'date_stop'])
  69. ]
  70. academic_year()
  71. class academic_month(osv.osv):
  72. ''' Defining a month of an academic year '''
  73. _name = "academic.month"
  74. _description = "Academic Month"
  75. _columns = {
  76. 'name': fields.char('Name', size=64, required=True, select=1),
  77. 'code': fields.char('Code', size=12, required=True, select=1),
  78. 'date_start': fields.date('Start of Period', required=True),
  79. 'date_stop': fields.date('End of Period', required=True),
  80. 'year_id': fields.many2one('academic.year', 'Academic Year', required=True, select=1),
  81. }
  82. _order = "date_start"
  83. def _check_duration(self, cr, uid, ids, context=None):
  84. for obj_month in self.browse(cr, uid, ids, context=context):
  85. if obj_month.date_stop < obj_month.date_start:
  86. return False
  87. return True
  88. def _check_year_limit(self,cr,uid,ids,context=None):
  89. for obj_month in self.browse(cr, uid, ids, context=context):
  90. if obj_month.year_id.date_stop < obj_month.date_stop or \
  91. obj_month.year_id.date_stop < obj_month.date_start or \
  92. obj_month.year_id.date_start > obj_month.date_start or \
  93. obj_month.year_id.date_start > obj_month.date_stop:
  94. return False
  95. return True
  96. _constraints = [
  97. (_check_duration, 'Error ! The duration of the Month(s) is/are invalid. ', ['date_stop']),
  98. (_check_year_limit, 'Invalid Months ! Some months overlap or the date period is not in the scope of the academic year. ', ['date_stop'])
  99. ]
  100. academic_month()
  101. class standard_medium(osv.osv):
  102. ''' Defining a medium(English, Hindi, Gujarati) related to standard'''
  103. _name = "standard.medium"
  104. _description = "Standard Medium"
  105. _order = "sequence"
  106. _columns = {
  107. 'sequence': fields.integer('Sequence', required=True),
  108. 'name': fields.char('Name', size=64, required=True, select=1),
  109. 'code': fields.char('Code', size=12, required=True, select=1),
  110. }
  111. standard_medium()
  112. class standard_division(osv.osv):
  113. ''' Defining a division(A, B, C) related to standard'''
  114. _name = "standard.division"
  115. _description = "Standard Division"
  116. _order = "sequence"
  117. _columns = {
  118. 'sequence': fields.integer('Sequence', required=True),
  119. 'name': fields.char('Name', size=64, required=True, select=1),
  120. 'code': fields.char('Code', size=12, required=True, select=1),
  121. }
  122. standard_division()
  123. class school_school(osv.osv):
  124. ''' Defining School Information '''
  125. _description ='School Information'
  126. _name = 'school.school'
  127. _columns = {
  128. 'name': fields.char('Name', size=64, required=True, select=1),
  129. 'code': fields.char('Code', size=20, required=True, select=1),
  130. 'standards':fields.one2many('school.standard', 'school_id','Standards'),
  131. }
  132. school_school()
  133. class standard_standard(osv.osv):
  134. ''' Defining Standard Information '''
  135. _description ='Standard Information'
  136. _name = 'standard.standard'
  137. _order = "sequence"
  138. _columns = {
  139. 'sequence': fields.integer('Sequence', required=True),
  140. 'name': fields.char('Name', size=64, required=True, select=1),
  141. 'code': fields.char('Code', size=20, required=True, select=1),
  142. }
  143. def next_standard(self, cr, uid, sequence, context=None):
  144. stand_ids = self.search(cr, uid, [('sequence', '>', sequence)])
  145. if stand_ids:
  146. return stand_ids[0]
  147. return False
  148. standard_standard()
  149. class school_standard(osv.osv):
  150. ''' Defining a standard related to school '''
  151. _description ='School Standards'
  152. _name = 'school.standard'
  153. _rec_name ="school_id"
  154. # def _compute_subject(self, cr, uid, ids, name, args, context=None):
  155. # ''' This function will automatically computes the subjects related to particular standard.'''
  156. # result = {}
  157. # subject_obj = self.pool.get('subject.subject')
  158. # for id in ids:
  159. # subject_ids = subject_obj.search(cr, uid, [('standard_ids.id','=',id)])
  160. # result[id] = subject_ids
  161. # return result
  162. def _compute_student(self, cr, uid, ids, name, args, context=None):
  163. ''' This function will automatically computes the students related to particular standard.'''
  164. result = {}
  165. student_obj = self.pool.get('student.student')
  166. for standard_data in self.browse(cr, uid, ids, context=context):
  167. student_ids = student_obj.search(cr, uid,[('class_id','=',standard_data.standard_id.id),
  168. ('division_id','=',standard_data.division_id.id),
  169. ('medium_id','=',standard_data.medium_id.id)])
  170. result[standard_data.id] = student_ids
  171. return result
  172. _columns = {
  173. 'school_id': fields.many2one('school.school', 'School', required=True),
  174. 'standard_id':fields.many2one('standard.standard', 'Class', required=True),
  175. 'division_id':fields.many2one('standard.division', 'Division', required=True),
  176. 'medium_id':fields.many2one('standard.medium', 'Medium', required=True),
  177. 'subject_ids': fields.many2many('subject.subject', 'subject_standards_rel','subject_id','standard_id','Subject'),
  178. 'user_id':fields.many2one('hr.employee', 'Class Teacher'),
  179. 'student_ids': fields.function(_compute_student, method=True, relation='student.student', type="one2many", string='Student In Class'),
  180. 'color': fields.integer('Color Index'),
  181. }
  182. def name_get(self, cr, uid, ids, context=None):
  183. res = []
  184. for standard in self.browse(cr, uid, ids, context=context):
  185. nam = standard.standard_id.name+"[" + standard.division_id.name + "]"
  186. res.append((standard.id,nam))
  187. return res
  188. school_standard()
  189. class subject_subject(osv.osv):
  190. '''Defining a subject '''
  191. _name = "subject.subject"
  192. _description = "Subjects"
  193. _columns = {
  194. 'name': fields.char('Name', size=64, required=True, select=1),
  195. 'code': fields.char('Code', size=12, required=True, select=1),
  196. 'maximum_marks': fields.integer("Maximum marks", size = 5),
  197. 'minimum_marks': fields.integer("Minimum marks", size = 5),
  198. 'weightage': fields.integer("Weightage", size = 10),
  199. 'teacher_ids':fields.many2many('hr.employee','subject_teacher_rel','subject_id','teacher_id','Teachers'),
  200. 'standard_ids':fields.many2many('school.standard','subject_standards_rel','standard_id','subject_id','Standards'),
  201. }
  202. subject_subject()
  203. class student_student(osv.osv):
  204. ''' Defining a student information '''
  205. def _calc_age(self, cr, uid, ids, name, arg, context=None):
  206. ''' This function will automatically calculates the age of particular student.'''
  207. res= {}
  208. for student in self.browse(cr, uid, ids, context=context):
  209. start = datetime.strptime(student.date_of_birth,"%Y-%m-%d")
  210. end = datetime.strptime(time.strftime('%Y-%m-%d'),"%Y-%m-%d")
  211. delta = end - start
  212. years = (delta.days / 365)
  213. res[student.id] = years
  214. return res
  215. _name = 'student.student'
  216. _table = "student_student"
  217. _description = 'Student Information'
  218. _inherits = {'res.partner': 'partner_id'}
  219. _columns = {
  220. 'partner_id': fields.many2one('res.partner', 'Partner', required=True, ondelete="cascade"),
  221. 'pid':fields.char('Student ID', size=64, required=True, readonly=True, help='Personal IDentification Number'),
  222. 'roll_no':fields.integer('Roll No.', readonly=True),
  223. 'photo': fields.binary('Photo'),
  224. 'year':fields.many2one('academic.year', 'Academic Year', required=True, states={'done':[('readonly',True)]}),
  225. 'class_id': fields.many2one('standard.standard', 'Class', required=True, states={'done':[('readonly',True)]}),
  226. 'division_id': fields.many2one('standard.division', 'Division', required=True, states={'done':[('readonly',True)]}),
  227. 'medium_id': fields.many2one('standard.medium', 'Medium', required=True, states={'done':[('readonly',True)]}),
  228. 'admission_date':fields.date('Admission Date', readonly=True),
  229. 'middle': fields.char('Middle Name', size=64, required=True, states={'done':[('readonly',True)]}),
  230. 'last': fields.char('Last Name', size=64, required=True, states={'done':[('readonly',True)]}),
  231. 'gender':fields.selection([('male','Male'), ('female','Female')], 'Gender', states={'done':[('readonly',True)]}),
  232. 'date_of_birth':fields.date('Birthdate', required=True, states={'done':[('readonly',True)]}),
  233. 'home_language':fields.selection([('eng','English'), ('guj','Gujarati')], 'Mother Tongue', states={'done':[('readonly',True)]}),
  234. 'age':fields.function(_calc_age, method=True, string='AGE', readonly=True, type="integer"),
  235. 'maritual_status':fields.selection([('unmarried','Unmarried'), ('married','Married')], 'Maritual Status', states={'done':[('readonly',True)]}),
  236. 'reference_ids':fields.one2many('student.reference', 'reference_id', 'References', states={'done':[('readonly',True)]}),
  237. 'previous_school_ids':fields.one2many('student.previous.school', 'previous_school_id', 'Previous School Detail', states={'done':[('readonly',True)]}),
  238. 'emergency_contact_ids':fields.one2many('student.emergency.contact', 'emergency_contact_id', 'Emergency Contact Detail', states={'done':[('readonly',True)]}),
  239. 'doctor': fields.char('Doctor Name', size=64, states={'done':[('readonly',True)]} ),
  240. 'designation': fields.char('Designation', size=64, states={'done':[('readonly',True)]} ),
  241. 'doctor_phone': fields.char('Phone', size=12, states={'done':[('readonly',True)]} ),
  242. 'blood_group': fields.char('Blood Group', size=12, states={'done':[('readonly',True)]} ),
  243. 'height': fields.float('Height', states={'done':[('readonly',True)]}),
  244. 'weight': fields.float('Weight', states={'done':[('readonly',True)]} ),
  245. 'eye':fields.boolean('Eyes', states={'done':[('readonly',True)]}),
  246. 'ear':fields.boolean('Ears', states={'done':[('readonly',True)]}),
  247. 'nose_throat':fields.boolean('Nose & Throat', states={'done':[('readonly',True)]}),
  248. 'respiratory':fields.boolean('Respiratory', states={'done':[('readonly',True)]}),
  249. 'cardiovascular':fields.boolean('Cardiovascular', states={'done':[('readonly',True)]}),
  250. 'neurological':fields.boolean('Neurological', states={'done':[('readonly',True)]}),
  251. 'muskoskeletal':fields.boolean('Muskoskeletal', states={'done':[('readonly',True)]}),
  252. 'dermatological':fields.boolean('Dermatological', states={'done':[('readonly',True)]}),
  253. 'blood_pressure':fields.boolean('Blood Pressure', states={'done':[('readonly',True)]}),
  254. 'remark':fields.text('Remark', states={'done':[('readonly',True)]}),
  255. 'school_id': fields.many2one('school.school', 'School', required=True, states={'done':[('readonly',True)]}),
  256. 'state':fields.selection([('draft','Draft'), ('confirm','Confirm'),('cancel','Cancel'), ('done','Done')],'State',readonly=True),
  257. 'history_ids': fields.one2many('student.history', 'student_id', 'History'),
  258. 'certificate_ids' : fields.one2many('student.certificate','student_id','Certificate'),
  259. 'attendance_ids' : fields.one2many('attendance.sheet.line','name','Attendance History',readonly=True),
  260. 'exam_results_ids' : fields.one2many('exam.result','student_id','Exam History',readonly=True),
  261. 'student_attachment_line' : fields.one2many('student.attachment','student_id','Attachment'),
  262. 'student_discipline_line' : fields.one2many('student.descipline','student_id','Descipline')
  263. }
  264. _defaults = {
  265. 'pid': lambda obj, cr, uid, context:obj.pool.get('ir.sequence').get(cr, uid, 'student.student'),
  266. 'state':'draft',
  267. }
  268. def admission_draft(self, cr, uid, ids, context=None):
  269. self.write(cr, uid, ids, {'state' : 'draft'}, context=context)
  270. return True
  271. def admission_confirm(self, cr, uid, ids, context=None):
  272. self.write(cr, uid, ids, {'state' : 'confirm'}, context=context)
  273. return True
  274. def admission_cancel(self, cr, uid, ids, context=None):
  275. self.write(cr, uid, ids, {'state' : 'cancel'}, context=context)
  276. return True
  277. def admission_done(self, cr, uid, ids, context=None):
  278. school_standard_obj = self.pool.get('school.standard')
  279. for student_data in self.browse(cr, uid, ids, context=context):
  280. domain = [('standard_id', '=', student_data.class_id.id), ('medium_id' ,'=', student_data.medium_id.id), ('division_id', '=', student_data.division_id.id)]
  281. school_standard_search_ids = school_standard_obj.search(cr, uid, domain, context=context)
  282. if not school_standard_search_ids:
  283. raise osv.except_osv(_('Warning'), _('The standard is not defined in a school'))
  284. domain = [('class_id', '=', student_data.class_id.id), ('medium_id' ,'=', student_data.medium_id.id), ('division_id', '=', student_data.division_id.id)]
  285. student_search_ids = self.search(cr, uid, domain, context=context)
  286. number = 1
  287. for student in self.browse(cr, uid, student_search_ids, context=context):
  288. self.write(cr, uid, student.id, {'roll_no':number}, context=context)
  289. number += 1
  290. self.write(cr, uid, ids, {'state': 'done', 'admission_date': time.strftime('%Y-%m-%d')}, context=context)
  291. return True
  292. student_student()
  293. class student_attachment(osv.osv):
  294. _name = 'student.attachment'
  295. _columns = {
  296. 'student_id' : fields.many2one('student.student', 'Student'),
  297. 'name':fields.char('Document Name',size=30),
  298. 'new_datas' : fields.binary('Attachments'),
  299. 'file_name':fields.char('File Name',size=30)
  300. }
  301. student_attachment()
  302. class student_descipline(osv.osv):
  303. _name = 'student.descipline'
  304. _columns = {
  305. 'student_id' : fields.many2one('student.student', 'Student'),
  306. 'teacher_id':fields.many2one('hr.employee', 'Teacher'),
  307. 'date':fields.date('Date'),
  308. 'class_id': fields.many2one('standard.standard', 'Class'),
  309. 'note':fields.text('Note'),
  310. 'action_taken':fields.text('Action Taken'),
  311. }
  312. student_descipline()
  313. class student_history(osv.osv):
  314. _name = "student.history"
  315. _columns = {
  316. 'student_id': fields.many2one('student.student', 'Student'),
  317. 'academice_year_id':fields.many2one('academic.year', 'Academic Year', required=True),
  318. 'class_id': fields.many2one('standard.standard', 'Class', required=True),
  319. 'division_id': fields.many2one('standard.division', 'Division', required=True),
  320. 'medium_id': fields.many2one('standard.medium', 'Medium', required=True),
  321. }
  322. student_history()
  323. class student_certificate(osv.osv):
  324. _name = "student.certificate"
  325. _columns = {
  326. 'student_id' : fields.many2one('student.student', 'Student'),
  327. 'description' : fields.char('Description',size=50),
  328. 'certi' : fields.binary('Certificate',required =True)
  329. }
  330. student_certificate()
  331. class hr_employee(osv.osv):
  332. ''' Defining a teacher information '''
  333. def _compute_subject(self, cr, uid, ids, name, args, context=None):
  334. ''' This function will automatically computes the subjects related to particular teacher.'''
  335. result = {}
  336. subject_obj = self.pool.get('subject.subject')
  337. for id in ids:
  338. subject_ids = subject_obj.search(cr, uid,[('teacher_ids.id','=',id)])
  339. result[id] = subject_ids
  340. return result
  341. _name = 'hr.employee'
  342. _inherit = 'hr.employee'
  343. _description = 'Teacher Information'
  344. _columns = {
  345. 'subject_ids': fields.function(_compute_subject, method=True, relation='subject.subject', type="many2many", string='Subjects'),
  346. }
  347. hr_employee()
  348. class res_partner_address(osv.osv):
  349. ''' Defining a address information '''
  350. _name = 'res.partner.address'
  351. _inherit = 'res.partner.address'
  352. _description = 'Address Information'
  353. _columns = {
  354. 'student_id': fields.many2one('student.student', 'Student' ),
  355. }
  356. res_partner_address()
  357. class student_reference(osv.osv):
  358. ''' Defining a student reference information '''
  359. _name = "student.reference"
  360. _description = "Student Reference"
  361. _columns = {
  362. 'reference_id': fields.many2one('student.student', 'Student'),
  363. 'name': fields.char('First Name', size=64, required=True),
  364. 'middle': fields.char('Middle Name', size=64, required=True),
  365. 'last': fields.char('Last Name', size=64, required=True),
  366. 'designation': fields.char('Designation', size=12, required=True),
  367. 'phone': fields.char('Phone', size=12, required=True),
  368. 'gender':fields.selection([('male','Male'), ('female','Female')], 'Gender'),
  369. }
  370. student_reference()
  371. class student_previous_school(osv.osv):
  372. ''' Defining a student previous school information '''
  373. _name = "student.previous.school"
  374. _description = "Student Previous School"
  375. _columns = {
  376. 'previous_school_id': fields.many2one('student.student', 'Student'),
  377. 'name': fields.char('Name', size=64, required=True),
  378. 'registration_no': fields.char('Registration No.', size=12, required=True),
  379. 'email': fields.char('Email', size=64, required=True),
  380. 'admission_date': fields.date('Admission Date'),
  381. 'exit_date': fields.date('Exit Date'),
  382. 'phone': fields.char('Phone', size=12, required=True),
  383. }
  384. student_previous_school()
  385. class student_emergency_contact(osv.osv):
  386. ''' Defining a student emergency contact information '''
  387. _name = "student.emergency.contact"
  388. _description = "Student Emergency Contact"
  389. _columns = {
  390. 'emergency_contact_id': fields.many2one('student.student', 'Student'),
  391. 'name': fields.char('Name', size=64, required=True),
  392. 'relation': fields.char('Relation', size=64, required=True),
  393. 'phone': fields.char('Phone', size=12, required=True),
  394. 'email': fields.char('E-Mail', size=150, required=True),
  395. }
  396. student_emergency_contact()
  397. # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: