from odoo import api, fields, models, _ from odoo.exceptions import ValidationError class EducationLibraryReservation(models.Model): _name = 'education.library.reservation' _description = 'Library Reservation' _rec_name = 'name' _order = 'reservation_date desc, priority desc' name = fields.Char(string='Reference', required=True, copy=False, readonly=True, default=lambda self: _('New')) member_id = fields.Many2one('education.library.member', string='Member', required=True) book_id = fields.Many2one('education.library.book', string='Book', required=True) reservation_date = fields.Date(string='Reservation Date', default=fields.Date.context_today, required=True) expiry_date = fields.Date(string='Expiry Date') fulfilled_date = fields.Date(string='Fulfilled Date') state = fields.Selection([ ('draft', 'Draft'), ('active', 'Active'), ('fulfilled', 'Fulfilled'), ('cancelled', 'Cancelled'), ('expired', 'Expired') ], string='Status', default='draft', required=True) priority = fields.Integer(string='Priority', default=10) @api.model_create_multi def create(self, vals_list): for vals in vals_list: if vals.get('name', _('New')) == _('New'): vals['name'] = self.env['ir.sequence'].next_by_code('education.library.reservation') or _('New') return super().create(vals_list) @api.constrains('member_id', 'book_id', 'state') def _check_duplicate_reservation(self): for record in self: if record.state == 'active': duplicates = self.search([ ('member_id', '=', record.member_id.id), ('book_id', '=', record.book_id.id), ('state', '=', 'active'), ('id', '!=', record.id) ]) if duplicates: raise ValidationError(_('A member cannot have multiple active reservations for the same book.')) def action_activate(self): for record in self: if not record.member_id.active: raise ValidationError(_('Active member required to make a reservation.')) record.state = 'active' # Set expiry date if not set and configured if not record.expiry_date: max_days = int(self.env['ir.config_parameter'].sudo().get_param('education_library.max_reservation_days', 2)) record.expiry_date = record.reservation_date + fields.Date.context_today().replace(day=record.reservation_date.day) # Simplified for time Delta, will fix properly with datetime.timedelta from datetime import timedelta record.expiry_date = record.reservation_date + timedelta(days=max_days) def action_fulfill(self): for record in self: record.write({ 'state': 'fulfilled', 'fulfilled_date': fields.Date.today() }) def action_cancel(self): self.write({'state': 'cancelled'}) @api.model def _cron_expire_reservations(self): expired = self.search([ ('state', '=', 'active'), ('expiry_date', '<', fields.Date.today()) ]) expired.write({'state': 'expired'})