2026-09-25 18:00:58 +05:30

98 lines
3.5 KiB
Python

# pyrefly: ignore [missing-import]
from odoo import api, fields, models
# pyrefly: ignore [missing-import]
from odoo.exceptions import ValidationError
class EducationHostelRoom(models.Model):
_name = 'education.hostel.room'
_description = 'Hostel Room'
_order = 'hostel_id, room_number'
_rec_name = 'display_name'
hostel_id = fields.Many2one(
'education.hostel',
string='Hostel',
required=True,
ondelete='restrict',
index=True,
)
floor_id = fields.Many2one(
'education.hostel.floor',
string='Floor',
required=True,
ondelete='restrict',
index=True,
)
name = fields.Char(string='Room Name', required=True)
room_number = fields.Char(string='Room Number', required=True, index=True)
room_type = fields.Selection([
('single', 'Single'),
('double', 'Double'),
('triple', 'Triple'),
('four', 'Four Sharing'),
('dormitory', 'Dormitory'),
('custom', 'Custom'),
], string='Room Type', default='double', required=True)
capacity = fields.Integer(string='Capacity', required=True, default=2)
gender = fields.Selection([
('male', 'Male'),
('female', 'Female'),
('mixed', 'Mixed'),
], string='Gender', default='mixed', required=True)
warden_notes = fields.Text(string='Warden Notes')
active = fields.Boolean(default=True)
bed_ids = fields.One2many('education.hostel.bed', 'room_id', string='Beds')
member_ids = fields.One2many('education.hostel.member', 'room_id', string='Residents')
company_id = fields.Many2one(
'res.company',
string='Company',
related='hostel_id.company_id',
store=True,
readonly=True,
index=True,
)
display_name = fields.Char(string='Display Name', compute='_compute_display_name', store=True)
# Computed occupancy
occupied_beds = fields.Integer(string='Occupied Beds', compute='_compute_occupancy', store=False)
available_beds = fields.Integer(string='Available Beds', compute='_compute_occupancy', store=False)
occupancy_percentage = fields.Float(string='Occupancy %', compute='_compute_occupancy', store=False)
_sql_constraints = [
('uniq_room_number_hostel', 'unique(room_number, hostel_id)', 'Room number must be unique within the hostel.'),
]
@api.depends('name', 'room_number', 'hostel_id.name')
def _compute_display_name(self):
for rec in self:
rec.display_name = f"{rec.hostel_id.name or ''} / {rec.room_number or ''} - {rec.name or ''}"
@api.depends('member_ids', 'member_ids.status', 'capacity')
def _compute_occupancy(self):
for rec in self:
active_members = rec.member_ids.filtered(lambda m: m.status == 'active')
rec.occupied_beds = len(active_members)
rec.available_beds = max(0, rec.capacity - rec.occupied_beds)
rec.occupancy_percentage = (
round(rec.occupied_beds / rec.capacity * 100, 1)
if rec.capacity else 0.0
)
@api.constrains('capacity')
def _check_capacity(self):
for rec in self:
if rec.capacity <= 0:
raise ValidationError('Room capacity must be greater than zero.')
@api.constrains('floor_id', 'hostel_id')
def _check_floor_hostel(self):
for rec in self:
if rec.floor_id and rec.floor_id.hostel_id != rec.hostel_id:
raise ValidationError(
'The selected floor does not belong to the selected hostel.'
)