# © 2015 2011,2013 Michael Telahun Makonnen # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from datetime import date from odoo import api, fields, models, _ from odoo.exceptions import UserError class HrHolidaysPublic(models.Model): _name = 'hr.holidays.public' _description = 'Public Holidays' _rec_name = 'year' _order = "year" display_name = fields.Char( "Name", compute="_compute_display_name", readonly=True, store=True, ) year = fields.Integer( "Calendar Year", required=True, default=date.today().year ) line_ids = fields.One2many( 'hr.holidays.public.line', 'year_id', 'Holiday Dates' ) country_id = fields.Many2one( 'res.country', 'Country' ) @api.multi @api.constrains('year', 'country_id') def _check_year(self): for line in self: line._check_year_one() def _check_year_one(self): if self.country_id: domain = [('year', '=', self.year), ('country_id', '=', self.country_id.id), ('id', '!=', self.id)] else: domain = [('year', '=', self.year), ('country_id', '=', False), ('id', '!=', self.id)] if self.search_count(domain): raise UserError(_('You can\'t create duplicate public holiday ' 'per year and/or country')) return True @api.multi @api.depends('year', 'country_id') def _compute_display_name(self): for line in self: if line.country_id: line.display_name = '%s (%s)' % (line.year, line.country_id.name) else: line.display_name = line.year @api.multi def name_get(self): result = [] for rec in self: result.append((rec.id, rec.display_name)) return result @api.model @api.returns('hr.holidays.public.line') def get_holidays_list(self, year, employee_id=None): """ Returns recordset of hr.holidays.public.line for the specified year and employee :param year: year as string :param employee_id: ID of the employee :return: recordset of hr.holidays.public.line """ holidays_filter = [('year', '=', year)] employee = False if employee_id: employee = self.env['hr.employee'].browse(employee_id) if employee.address_id and employee.address_id.country_id: holidays_filter.append('|') holidays_filter.append(('country_id', '=', False)) holidays_filter.append(('country_id', '=', employee.address_id.country_id.id)) else: holidays_filter.append(('country_id', '=', False)) pholidays = self.search(holidays_filter) if not pholidays: return list() states_filter = [('year_id', 'in', pholidays.ids)] if employee and employee.address_id and employee.address_id.state_id: states_filter += ['|', ('state_ids', '=', False), ('state_ids', '=', employee.address_id.state_id.id)] else: states_filter.append(('state_ids', '=', False)) hhplo = self.env['hr.holidays.public.line'] holidays_lines = hhplo.search(states_filter) return holidays_lines @api.model def is_public_holiday(self, selected_date, employee_id=None): """ Returns True if selected_date is a public holiday for the employee :param selected_date: datetime object or string :param employee_id: ID of the employee :return: bool """ if isinstance(selected_date, str): selected_date = fields.Date.from_string(selected_date) holidays_lines = self.get_holidays_list( selected_date.year, employee_id=employee_id) if holidays_lines: hol_date = holidays_lines.filtered( lambda r: r.date == fields.Date.to_string( selected_date)) if hol_date.ids: return True return False class HrHolidaysPublicLine(models.Model): _name = 'hr.holidays.public.line' _description = 'Public Holidays Lines' _order = "date, name desc" name = fields.Char( 'Name', required=True, ) date = fields.Date( 'Date', required=True ) year_id = fields.Many2one( 'hr.holidays.public', 'Calendar Year', required=True, ) variable_date = fields.Boolean('Date may change', oldname='variable', default=True) state_ids = fields.Many2many( 'res.country.state', 'hr_holiday_public_state_rel', 'line_id', 'state_id', 'Related States' ) @api.multi @api.constrains('date', 'state_ids') def _check_date_state(self): for line in self: line._check_date_state_one() def _check_date_state_one(self): if fields.Date.from_string(self.date).year != self.year_id.year: raise UserError(_( 'Dates of holidays should be the same year ' 'as the calendar year they are being assigned to' )) if self.state_ids: domain = [('date', '=', self.date), ('year_id', '=', self.year_id.id), ('state_ids', '!=', False), ('id', '!=', self.id)] holidays = self.search(domain) for holiday in holidays: if self.state_ids & holiday.state_ids: raise UserError(_('You can\'t create duplicate public ' 'holiday per date %s and one of the ' 'country states.') % self.date) domain = [('date', '=', self.date), ('year_id', '=', self.year_id.id), ('state_ids', '=', False)] if self.search_count(domain) > 1: raise UserError(_('You can\'t create duplicate public holiday ' 'per date %s.') % self.date) return True