This question has been flagged
4 Replies
5238 Views

I'm currently adapting the hr module to meet my company's requirement.

I've added two fields to the hr.holidays model.

When displaying the tree view, the js client doesn't render the table properly.

I also get some warning in the log (WARNING openerp.models: hr.holidays.read() with unknown field 'False')

When I look at the rpc request, I can see where the problem is : there's a 13th column called "false" but I don't know why it's there.

Here's the whole request : | Edit : Python code is below | I'm fairly new to Odoo and I don't know where to start looking, so any clue is welcomed !

{
  "jsonrpc": "2.0",
  "method": "call",
  "params": {
    "model": "hr.holidays",
    "method": "read",
    "args": [
      [
        12974
      ],
      [
        "holiday_status_id",
        "employee_id",
        "user_id",
        "date_from",
        "holiday_type",
        "state",
        "manager_id",
        "type",
        "department_id",
        "date_to",
        "category_id",
        "name",
        "number_of_days",
        false
      ]
    ],
    "kwargs": {
      "context": {
        "lang": "en_US",
        "tz": "Europe\/Brussels",
        "uid": 1,
        "params": {
          "action": 1867
        },
        "active_model": "hr.holidays"
      }
    }
  },
 "id": 793485475 }

Edit : My python code

from openerp import models,fields,api, _, workflow

from datetime import datetime, timedelta

from openerp.exceptions import ValidationError

from openerp.osv import osv

class hr_holidays(models.Model):

_inherit = "hr.holidays"

@api.multi

def _get_employee(self):

employee = self.env['hr.employee'].search([('user_id', '=', self._uid)])

if employee[0]:

return employee[0]

else:

return None

@api.multi

def _get_employee_id(self):

employee = self.env['hr.employee'].search([('user_id', '=', self._uid)])

if employee[0]:

return employee[0].id

else:

return None

#select automatically the good type depending on remaining days

@api.model

def _get_default_status_id(self, requested_days):

employee = self._get_employee()

#check by type of holidays if user has always

types = self.env["hr.holidays.status"].search([], order='count desc,sequence')

if not types:

return None

for holiday_type in types:

if holiday_type.count:

leave_days = holiday_type.get_days(employee.id)[holiday_type.id]

if leave_days['remaining_leaves'] >= requested_days and leave_days['virtual_remaining_leaves'] >= requested_days:

return holiday_type.id

return types[0].id

def onchange_type(self, cr, uid, ids, holiday_type):

result = {}

manager_group_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base','group_hr_manager')[1]

manager_group = self.pool.get('res.groups').browse(cr, uid, manager_group_id)

if uid in manager_group.users.ids:

return result

if holiday_type == 'employee':

employee_id = self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)])[0]

if employee_id:

result['value'] = {'employee_id': employee_id}

return result

def onchange_date_from(self, cr, uid, ids, date_to, date_from, employee_id):

try:

result = super(hr_holidays,self).onchange_date_from(cr, uid, ids, date_to, date_from)

except osv.except_osv:

#bypass warning if start date > end date

return {'value':{'number_of_days_temp': 0}}

if date_to and date_from:

diff_day = self._get_number_of_days_elneo(cr, uid, date_from, date_to, employee_id)

result['value'] = {

'number_of_days_temp': diff_day

}

return result

result['value'] = {

'number_of_days_temp': 0,

}

return result

def onchange_date_to(self, cr, uid, ids, date_to, date_from, employee_id):

try:

result = super(hr_holidays,self).onchange_date_to(cr, uid, ids, date_to, date_from)

except osv.except_osv:

#by pass warning if start date > end date

return {'value':{'number_of_days_temp': 0}}

if date_to and date_from:

diff_day = self._get_number_of_days_elneo(cr, uid, date_from, date_to, employee_id)

result['value'] = {

'number_of_days_temp': diff_day

}

return result

result['value'] = {

'number_of_days_temp': 0,

}

return result

@api.onchange('number_of_days_temp')

def onchange_number_of_days_temp(self):

res = {}

new_holiday_status = self._get_default_status_id(self.number_of_days_temp)

if not new_holiday_status:

return res

'''if self.holiday_status_id and self.holiday_status_id.id != new_holiday_status:

res = {'warning':{'title':'Warning','message':'Holiday type has changed !'}}'''

self.holiday_status_id = new_holiday_status

return res

#compute number of days based on working days and leaves already encoded

@api.model

def _get_number_of_days_elneo(self, date_from, date_to, employee_id):

DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"

INCREMENT=0.5

from_date = datetime.strptime(date_from, DATETIME_FORMAT)

to_date = datetime.strptime(date_to, DATETIME_FORMAT)

#build array of each days of current holidays

current_holidays = []

current_date = from_date

if(to_date.strftime("%H%M") > "1200"):

to_date=to_date.replace(hour=23,minute=59)

while current_date <= to_date:

date_without_hours = current_date.date()

if current_date.strftime("%H%M") > "1200":

period = 1

else:

period = 0

current_holidays.append((date_without_hours,period))

current_date = current_date+timedelta(days=INCREMENT)

#find holidays already encoded and subtract days already encoded, in the current interval

previous_holidays_objs = self.search([('state','=','validate'),('type','=','remove'),('employee_id','=',employee_id),

'|','&',('date_from','>=',datetime.strftime(from_date, DATETIME_FORMAT)),('date_from','<=',datetime.strftime(to_date, DATETIME_FORMAT)),

'|','&',('date_to','>=',datetime.strftime(from_date, DATETIME_FORMAT)),('date_to','<=',datetime.strftime(to_date, DATETIME_FORMAT)),

'&',('date_from','<=',datetime.strftime(from_date, DATETIME_FORMAT)),('date_to','>=',datetime.strftime(to_date, DATETIME_FORMAT))

])

#build dict of previous holidays

previous_holidays = set()

for previous_holidays_obj in previous_holidays_objs:

current_date = datetime.strptime(previous_holidays_obj.date_from, DATETIME_FORMAT)

date_to = datetime.strptime(previous_holidays_obj.date_to, DATETIME_FORMAT)

if(date_to.strftime("%H%M") > "1200"):

date_to=date_to.replace(hour=23,minute=59)

while current_date < date_to:

date_without_hours = current_date.date()

if current_date.strftime("%H%M") > "1200":

period = 1

else:

period = 0

previous_holidays.add((date_without_hours,period))

current_date = current_date+timedelta(days=INCREMENT)

#browse array of current holidays and add one day only if date is not in previous holidays array

number_of_days = 0

for day_part in current_holidays:

if ((day_part not in previous_holidays) and (day_part[0].strftime('%w') not in ['0','6'])):

number_of_days = number_of_days+INCREMENT

return number_of_days

####################

removed_days = set() #set of days already used by other holidays

for previous_holiday in previous_holidays:

current_date = from_date

while (current_date < to_date):

current_date_str = datetime.strftime(current_date, DATETIME_FORMAT)

if (current_date_str >= previous_holiday.date_from) and (current_date_str <= previous_holiday.date_to) and (current_date.strftime('%w') not in ['0','6']):

removed_days.add(current_date)

current_date = current_date+timedelta(days=INCREMENT)

if((current_date.strftime("%d%m%Y") == to_date.strftime("%d%m%Y")) & ((to_date.strftime("%H%M") > "1200") | (current_date.strftime("%H%M") > "1200"))):

removed_days.add(current_date)

days_to_remove = len(removed_days) * INCREMENT

#count days of holidays

number_of_days = 0.0

current_date = from_date

while ((current_date < to_date)):

if current_date.strftime('%w') not in ['0','6']:

number_of_days = float(number_of_days+INCREMENT)

current_date = current_date+timedelta(days=INCREMENT)

if((current_date.strftime("%d%m%Y") == to_date.strftime("%d%m%Y")) & (to_date.strftime("%H%M") > "1200")):

number_of_days = float(number_of_days+INCREMENT)

return number_of_days-days_to_remove;

#set manager as manager of department.

def set_manager(self):

if self.department_id and self.department_id.manager_id: # bien employee_id

self.manager_id = self.department_id.manager_id.id

else:

self.manager_id = 20

self.manager_id2 = 20

@api.onchange('department_id')

def onchange_department(self):

self.set_manager()

#say if current user is in hr manager group

@api.model

def uid_hr_manager(self):

manager_group_id = self.env['ir.model.data'].get_object_reference('base','group_hr_manager')[1]

manager_group = self.env['res.groups'].browse(manager_group_id)

if self._uid in manager_group.users.ids:

return True

return False

@api.multi

def holidays_confirm(self):

res = super(hr_holidays, self).holidays_confirm()

for holiday in self:

holiday.set_manager()

return res

#limit first approval to manager or hr managers

@api.multi

def holidays_first_validate(self):

res = super(hr_holidays, self).holidays_first_validate()

for holiday in self:

if holiday.manager_id and holiday.manager_id.user_id and holiday.manager_id.user_id.id != self._uid and not self.uid_hr_manager():

if holiday.manager_id:

raise ValidationError(_('Only %s or hr managers can approve this holiday !')%holiday.manager_id.name)

else:

raise ValidationError(_('Only hr managers can approve this holiday !'))

return res

#limit second approval aka validation to hr manager

@api.multi

def holidays_validate(self):

res = super(hr_holidays, self).holidays_validate()

if not self.uid_hr_manager():

raise ValidationError(_('Only hr managers can approve this holiday !'))

return res

#override _check_date function to allow overlap of 2 leaves on the same date with different types

@api.multi

def _check_date(self):

for holiday in self:

domain = [

('date_from', '<=', holiday.date_to),

('date_to', '>=', holiday.date_from),

('employee_id', '=', holiday.employee_id.id),

('id', '!=', holiday.id),

('state', 'not in', ['cancel', 'refuse']),

('holiday_status_id','=',holiday.holiday_status_id.id),

('type','=',holiday.type)

]

nholidays = self.search_count(domain)

if nholidays:

return False

return True

#change constraint to bypass warning

_constraints = [

(_check_date, 'You can not have 2 leaves that overlaps on same day!', ['date_from','date_to']),

]

@api.depends('date_from')

@api.one

def _get_year(self):

for holiday in self:

if holiday.date_from:

holiday.year = holiday.date_from[0:4]

else:

holiday.year = ''

year = fields.Char(string="Year", compute='_get_year', store=True)

@api.model

def default_get(self, fields):

res = super(hr_holidays, self).default_get(fields)

for field in fields:

if field == 'name':

res['name'] = _('Holidays')

if field == 'holiday_status_id':

default_status = self._get_default_status_id(1)

if default_status:

res['holiday_status_id'] = self._get_default_status_id(1)

if field == 'date_from':

if 'date_from' in res:

res['date_from'] = res['date_from'][0:10]+' 07:00:00'

else:

res['date_from'] = datetime.now().strftime('%Y-%m-%d 07:00:00')

if field == 'date_to':

if 'date_to' in res:

res['date_to'] = res['date_to'][0:10]+' 15:45:00'

else:

res['date_to'] = datetime.now().strftime('%Y-%m-%d 15:45:00')

if field == 'employee_id':

res['employee_id'] = self._get_employee_id()

return res

#display notification number on menu item only for holidays on which we must do an action

@api.model

def _needaction_domain_get(self):

dom = super(hr_holidays, self)._needaction_domain_get()

#dom.extend(['|',('manager_user_id','=',self._uid),('manager_user_id2','=',self._uid)])

dom.extend(['|',('manager_id','=',self._uid),('manager_id2','=',self._uid)])

return dom

#add fields to automate selection of good holiday type

class hr_holidays_status(models.Model):

_inherit = "hr.holidays.status"

_order = 'sequence'

sequence = fields.Integer("Sequence", help='Sequence is used to choose the first type with remaining days as default type.')

count = fields.Boolean("Count", help="First type with 'count' and with several remaining days will be used as default type ")

#display leaves taken and max even if holiday type is limited

def name_get(self, cr, uid, ids, context=None):

if context is None:

context = {}

if not context.get('employee_id',False):

# leave counts is based on employee_id, would be inaccurate if not based on correct employee

return super(hr_holidays_status, self).name_get(cr, uid, ids, context=context)

res = []

for record in self.browse(cr, uid, ids, context=context):

name = record.name

name = name + (' (%g/%g)' % (record.leaves_taken or 0.0, record.max_leaves or 0.0))

res.append((record.id, name))

return res

Avatar
Discard

Code added ! Thanks !

(please delete this comment)

Author Best Answer

Sorry for the delay !

There was an error in my xml  file : be careful with view_type and view_mode !

view_type = type of the view

view_mode = list of type available

And not the opposite ... 

Avatar
Discard
Best Answer

You have an error within your new fields declaration. Share your python code so i can help you. You can find more \here.

Avatar
Discard
Best Answer

which of the fields are you added and what is the purpose of these fields .Then only people can help.So please clarify these points first.

Avatar
Discard