117 lines
4.4 KiB
Python
117 lines
4.4 KiB
Python
# pyrefly: ignore [missing-import]
|
|
from odoo import api, fields, models
|
|
# pyrefly: ignore [missing-import]
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class EducationHostel(models.Model):
|
|
_name = 'education.hostel'
|
|
_description = 'Hostel'
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
_order = 'name'
|
|
_rec_name = 'name'
|
|
|
|
name = fields.Char(string='Hostel Name', required=True, tracking=True)
|
|
code = fields.Char(string='Hostel Code', required=True, index=True, tracking=True)
|
|
campus_id = fields.Many2one(
|
|
'education.campus',
|
|
string='Campus',
|
|
required=True,
|
|
ondelete='restrict',
|
|
index=True,
|
|
tracking=True,
|
|
)
|
|
hostel_type = fields.Selection([
|
|
('boys', 'Boys'),
|
|
('girls', 'Girls'),
|
|
('mixed', 'Mixed'),
|
|
], string='Hostel Type', required=True, default='boys', tracking=True)
|
|
warden_id = fields.Many2one(
|
|
'res.users',
|
|
string='Warden',
|
|
tracking=True,
|
|
domain=[('share', '=', False)],
|
|
)
|
|
contact_phone = fields.Char(string='Contact Phone')
|
|
email = fields.Char(string='Email')
|
|
address = fields.Text(string='Address')
|
|
description = fields.Text(string='Description')
|
|
active = fields.Boolean(default=True, tracking=True)
|
|
company_id = fields.Many2one(
|
|
'res.company',
|
|
string='Company',
|
|
required=True,
|
|
default=lambda self: self.env.company,
|
|
index=True,
|
|
)
|
|
|
|
# Relational
|
|
floor_ids = fields.One2many('education.hostel.floor', 'hostel_id', string='Floors')
|
|
room_ids = fields.One2many('education.hostel.room', 'hostel_id', string='Rooms')
|
|
member_ids = fields.One2many('education.hostel.member', 'hostel_id', string='Members')
|
|
|
|
# Computed statistics
|
|
room_count = fields.Integer(string='Total Rooms', compute='_compute_stats', store=False)
|
|
bed_count = fields.Integer(string='Total Beds', compute='_compute_stats', store=False)
|
|
occupied_bed_count = fields.Integer(string='Occupied Beds', compute='_compute_stats', store=False)
|
|
available_bed_count = fields.Integer(string='Available Beds', compute='_compute_stats', store=False)
|
|
occupancy_percentage = fields.Float(string='Occupancy %', compute='_compute_stats', store=False)
|
|
|
|
_sql_constraints = [
|
|
('uniq_hostel_code_company', 'unique(code, company_id)', 'Hostel code must be unique per company.'),
|
|
]
|
|
|
|
@api.depends('room_ids', 'room_ids.capacity', 'member_ids', 'member_ids.status')
|
|
def _compute_stats(self):
|
|
for rec in self:
|
|
rooms = rec.room_ids.filtered('active')
|
|
rec.room_count = len(rooms)
|
|
rec.bed_count = sum(rooms.mapped('capacity'))
|
|
active_members = rec.member_ids.filtered(lambda m: m.status == 'active')
|
|
rec.occupied_bed_count = len(active_members)
|
|
rec.available_bed_count = max(0, rec.bed_count - rec.occupied_bed_count)
|
|
rec.occupancy_percentage = (
|
|
round(rec.occupied_bed_count / rec.bed_count * 100, 1)
|
|
if rec.bed_count else 0.0
|
|
)
|
|
|
|
@api.constrains('campus_id', 'company_id')
|
|
def _check_campus_company(self):
|
|
for rec in self:
|
|
if rec.campus_id and rec.campus_id.company_id != rec.company_id:
|
|
raise ValidationError(
|
|
'The selected campus does not belong to the current company.'
|
|
)
|
|
|
|
def action_view_rooms(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'Rooms',
|
|
'res_model': 'education.hostel.room',
|
|
'view_mode': 'list,form',
|
|
'domain': [('hostel_id', '=', self.id)],
|
|
'context': {'default_hostel_id': self.id},
|
|
}
|
|
|
|
def action_view_members(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'Active Residents',
|
|
'res_model': 'education.hostel.member',
|
|
'view_mode': 'list,form',
|
|
'domain': [('hostel_id', '=', self.id), ('status', '=', 'active')],
|
|
'context': {'default_hostel_id': self.id},
|
|
}
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
if vals.get('code'):
|
|
vals['code'] = vals['code'].strip().upper()
|
|
return super().create(vals_list)
|
|
|
|
def write(self, vals):
|
|
if 'code' in vals and vals.get('code'):
|
|
vals['code'] = vals['code'].strip().upper()
|
|
return super().write(vals)
|