2018-01-16 06:58:15 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
2018-01-16 11:34:37 +01:00
|
|
|
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
2018-01-16 06:58:15 +01:00
|
|
|
from datetime import datetime
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
|
2018-01-16 11:34:37 +01:00
|
|
|
from flectra.exceptions import AccessError, ValidationError, UserError
|
|
|
|
from flectra.tools import mute_logger, test_reports
|
2018-01-16 06:58:15 +01:00
|
|
|
|
2018-01-16 11:34:37 +01:00
|
|
|
from flectra.addons.hr_holidays.tests.common import TestHrHolidaysBase
|
2018-01-16 06:58:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
class TestHolidaysFlow(TestHrHolidaysBase):
|
|
|
|
|
2018-01-16 11:34:37 +01:00
|
|
|
@mute_logger('flectra.addons.base.ir.ir_model', 'flectra.models')
|
2018-01-16 06:58:15 +01:00
|
|
|
def test_00_leave_request_flow(self):
|
|
|
|
""" Testing leave request flow """
|
|
|
|
Holidays = self.env['hr.holidays']
|
|
|
|
HolidaysStatus = self.env['hr.holidays.status']
|
|
|
|
|
|
|
|
def _check_holidays_status(holiday_status, ml, lt, rl, vrl):
|
|
|
|
self.assertEqual(holiday_status.max_leaves, ml,
|
|
|
|
'hr_holidays: wrong type days computation')
|
|
|
|
self.assertEqual(holiday_status.leaves_taken, lt,
|
|
|
|
'hr_holidays: wrong type days computation')
|
|
|
|
self.assertEqual(holiday_status.remaining_leaves, rl,
|
|
|
|
'hr_holidays: wrong type days computation')
|
|
|
|
self.assertEqual(holiday_status.virtual_remaining_leaves, vrl,
|
|
|
|
'hr_holidays: wrong type days computation')
|
|
|
|
|
|
|
|
# HrUser creates some holiday statuses -> crash because only HrManagers should do this
|
|
|
|
with self.assertRaises(AccessError):
|
|
|
|
HolidaysStatus.sudo(self.user_hruser_id).create({
|
|
|
|
'name': 'UserCheats',
|
|
|
|
'limit': True,
|
|
|
|
})
|
|
|
|
|
|
|
|
# HrManager creates some holiday statuses
|
|
|
|
HolidayStatusManagerGroup = HolidaysStatus.sudo(self.user_hrmanager_id)
|
|
|
|
HolidayStatusManagerGroup.create({
|
|
|
|
'name': 'WithMeetingType',
|
|
|
|
'limit': True,
|
|
|
|
'categ_id': self.env['calendar.event.type'].sudo(self.user_hrmanager_id).create({'name': 'NotLimitedMeetingType'}).id
|
|
|
|
})
|
|
|
|
self.holidays_status_1 = HolidayStatusManagerGroup.create({
|
|
|
|
'name': 'NotLimited',
|
|
|
|
'limit': True,
|
|
|
|
})
|
|
|
|
self.holidays_status_2 = HolidayStatusManagerGroup.create({
|
|
|
|
'name': 'Limited',
|
|
|
|
'limit': False,
|
|
|
|
'double_validation': True,
|
|
|
|
})
|
|
|
|
|
|
|
|
# --------------------------------------------------
|
|
|
|
# Case1: unlimited type of leave request
|
|
|
|
# --------------------------------------------------
|
|
|
|
|
|
|
|
# Employee creates a leave request for another employee -> should crash
|
|
|
|
HolidaysEmployeeGroup = Holidays.sudo(self.user_employee_id)
|
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
HolidaysEmployeeGroup.create({
|
|
|
|
'name': 'Hol10',
|
|
|
|
'employee_id': self.employee_hruser_id,
|
|
|
|
'holiday_status_id': self.holidays_status_1.id,
|
|
|
|
'date_from': (datetime.today() - relativedelta(days=1)),
|
|
|
|
'date_to': datetime.today(),
|
|
|
|
'number_of_days_temp': 1,
|
|
|
|
})
|
|
|
|
Holidays.search([('name', '=', 'Hol10')]).unlink()
|
|
|
|
|
|
|
|
# Employee creates a leave request in a no-limit category
|
|
|
|
hol1_employee_group = HolidaysEmployeeGroup.create({
|
|
|
|
'name': 'Hol11',
|
|
|
|
'employee_id': self.employee_emp_id,
|
|
|
|
'holiday_status_id': self.holidays_status_1.id,
|
|
|
|
'date_from': (datetime.today() - relativedelta(days=1)),
|
|
|
|
'date_to': datetime.today(),
|
|
|
|
'number_of_days_temp': 1,
|
|
|
|
})
|
|
|
|
hol1_user_group = hol1_employee_group.sudo(self.user_hruser_id)
|
|
|
|
self.assertEqual(hol1_user_group.state, 'confirm', 'hr_holidays: newly created leave request should be in confirm state')
|
|
|
|
|
|
|
|
# Employee validates its leave request -> should not work
|
|
|
|
with self.assertRaises(UserError):
|
|
|
|
hol1_employee_group.action_approve()
|
|
|
|
self.assertEqual(hol1_user_group.state, 'confirm', 'hr_holidays: employee should not be able to validate its own leave request')
|
|
|
|
|
|
|
|
# HrUser validates the employee leave request
|
|
|
|
hol1_user_group.action_approve()
|
|
|
|
self.assertEqual(hol1_user_group.state, 'validate', 'hr_holidays: validates leave request should be in validate state')
|
|
|
|
|
|
|
|
# --------------------------------------------------
|
|
|
|
# Case2: limited type of leave request
|
|
|
|
# --------------------------------------------------
|
|
|
|
|
|
|
|
# Employee creates a new leave request at the same time -> crash, avoid interlapping
|
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
HolidaysEmployeeGroup.create({
|
|
|
|
'name': 'Hol21',
|
|
|
|
'employee_id': self.employee_emp_id,
|
|
|
|
'holiday_status_id': self.holidays_status_1.id,
|
|
|
|
'date_from': (datetime.today() - relativedelta(days=1)).strftime('%Y-%m-%d %H:%M'),
|
|
|
|
'date_to': datetime.today(),
|
|
|
|
'number_of_days_temp': 1,
|
|
|
|
})
|
|
|
|
|
|
|
|
# Employee creates a leave request in a limited category -> crash, not enough days left
|
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
HolidaysEmployeeGroup.create({
|
|
|
|
'name': 'Hol22',
|
|
|
|
'employee_id': self.employee_emp_id,
|
|
|
|
'holiday_status_id': self.holidays_status_2.id,
|
|
|
|
'date_from': (datetime.today() + relativedelta(days=0)).strftime('%Y-%m-%d %H:%M'),
|
|
|
|
'date_to': (datetime.today() + relativedelta(days=1)),
|
|
|
|
'number_of_days_temp': 1,
|
|
|
|
})
|
|
|
|
|
|
|
|
# Clean transaction
|
|
|
|
Holidays.search([('name', 'in', ['Hol21', 'Hol22'])]).unlink()
|
|
|
|
|
|
|
|
# HrUser allocates some leaves to the employee
|
|
|
|
aloc1_user_group = Holidays.sudo(self.user_hruser_id).create({
|
|
|
|
'name': 'Days for limited category',
|
|
|
|
'employee_id': self.employee_emp_id,
|
|
|
|
'holiday_status_id': self.holidays_status_2.id,
|
|
|
|
'type': 'add',
|
|
|
|
'number_of_days_temp': 2,
|
|
|
|
})
|
|
|
|
# HrUser validates the first step
|
|
|
|
aloc1_user_group.action_approve()
|
|
|
|
# HrManager validates the second step
|
|
|
|
aloc1_user_group.sudo(self.user_hrmanager_id).action_validate()
|
|
|
|
# Checks Employee has effectively some days left
|
|
|
|
hol_status_2_employee_group = self.holidays_status_2.sudo(self.user_employee_id)
|
|
|
|
_check_holidays_status(hol_status_2_employee_group, 2.0, 0.0, 2.0, 2.0)
|
|
|
|
|
|
|
|
# Employee creates a leave request in the limited category, now that he has some days left
|
|
|
|
hol2 = HolidaysEmployeeGroup.create({
|
|
|
|
'name': 'Hol22',
|
|
|
|
'employee_id': self.employee_emp_id,
|
|
|
|
'holiday_status_id': self.holidays_status_2.id,
|
|
|
|
'date_from': (datetime.today() + relativedelta(days=2)).strftime('%Y-%m-%d %H:%M'),
|
|
|
|
'date_to': (datetime.today() + relativedelta(days=3)),
|
|
|
|
'number_of_days_temp': 1,
|
|
|
|
})
|
|
|
|
hol2_user_group = hol2.sudo(self.user_hruser_id)
|
|
|
|
# Check left days: - 1 virtual remaining day
|
|
|
|
_check_holidays_status(hol_status_2_employee_group, 2.0, 0.0, 2.0, 1.0)
|
|
|
|
|
|
|
|
# HrUser validates the first step
|
|
|
|
hol2_user_group.action_approve()
|
|
|
|
self.assertEqual(hol2.state, 'validate1',
|
|
|
|
'hr_holidays: first validation should lead to validate1 state')
|
|
|
|
|
|
|
|
# HrManager validates the second step
|
|
|
|
hol2_user_group.sudo(self.user_hrmanager_id).action_validate()
|
|
|
|
self.assertEqual(hol2.state, 'validate',
|
|
|
|
'hr_holidays: second validation should lead to validate state')
|
|
|
|
# Check left days: - 1 day taken
|
|
|
|
_check_holidays_status(hol_status_2_employee_group, 2.0, 1.0, 1.0, 1.0)
|
|
|
|
|
|
|
|
# HrManager finds an error: he refuses the leave request
|
|
|
|
hol2.sudo(self.user_hrmanager_id).action_refuse()
|
|
|
|
self.assertEqual(hol2.state, 'refuse',
|
|
|
|
'hr_holidays: refuse should lead to refuse state')
|
|
|
|
# Check left days: 2 days left again
|
|
|
|
_check_holidays_status(hol_status_2_employee_group, 2.0, 0.0, 2.0, 2.0)
|
|
|
|
|
|
|
|
# Annoyed, HrUser tries to fix its error and tries to reset the leave request -> does not work, only HrManager
|
|
|
|
with self.assertRaises(UserError):
|
|
|
|
hol2_user_group.action_draft()
|
|
|
|
self.assertEqual(hol2.state, 'refuse',
|
|
|
|
'hr_holidays: hr_user should not be able to reset a refused leave request')
|
|
|
|
|
|
|
|
# HrManager resets the request
|
|
|
|
hol2_manager_group = hol2.sudo(self.user_hrmanager_id)
|
|
|
|
hol2_manager_group.action_draft()
|
|
|
|
self.assertEqual(hol2.state, 'draft',
|
|
|
|
'hr_holidays: resetting should lead to draft state')
|
|
|
|
|
|
|
|
# HrManager changes the date and put too much days -> crash when confirming
|
|
|
|
hol2_manager_group.write({
|
|
|
|
'date_from': (datetime.today() + relativedelta(days=4)).strftime('%Y-%m-%d %H:%M'),
|
|
|
|
'date_to': (datetime.today() + relativedelta(days=7)),
|
|
|
|
'number_of_days_temp': 4,
|
|
|
|
})
|
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
hol2_manager_group.action_confirm()
|
|
|
|
|
|
|
|
employee_id = self.ref('hr.employee_root')
|
|
|
|
# cl can be of maximum 20 days for employee_root
|
|
|
|
hol3_status = self.env.ref('hr_holidays.holiday_status_cl').with_context(employee_id=employee_id)
|
|
|
|
# I assign the dates in the holiday request for 1 day
|
|
|
|
hol3 = Holidays.create({
|
|
|
|
'name': 'Sick Leave',
|
|
|
|
'holiday_status_id': hol3_status.id,
|
|
|
|
'date_from': datetime.today().strftime('%Y-%m-10 10:00:00'),
|
|
|
|
'date_to': datetime.today().strftime('%Y-%m-11 19:00:00'),
|
|
|
|
'employee_id': employee_id,
|
|
|
|
'type': 'remove',
|
|
|
|
'number_of_days_temp': 1
|
|
|
|
})
|
|
|
|
# I find a small mistake on my leave request to I click on "Refuse" button to correct a mistake.
|
|
|
|
hol3.action_refuse()
|
|
|
|
self.assertEqual(hol3.state, 'refuse', 'hr_holidays: refuse should lead to refuse state')
|
|
|
|
# I again set to draft and then confirm.
|
|
|
|
hol3.action_draft()
|
|
|
|
self.assertEqual(hol3.state, 'draft', 'hr_holidays: resetting should lead to draft state')
|
|
|
|
hol3.action_confirm()
|
|
|
|
self.assertEqual(hol3.state, 'confirm', 'hr_holidays: confirming should lead to confirm state')
|
|
|
|
# I validate the holiday request by clicking on "To Approve" button.
|
|
|
|
hol3.action_approve()
|
|
|
|
self.assertEqual(hol3.state, 'validate', 'hr_holidays: validation should lead to validate state')
|
|
|
|
# Check left days for casual leave: 19 days left
|
|
|
|
_check_holidays_status(hol3_status, 20.0, 1.0, 19.0, 19.0)
|
|
|
|
|
|
|
|
def test_10_leave_summary_reports(self):
|
|
|
|
# Print the HR Holidays(Summary Department) Report through the wizard
|
|
|
|
ctx = {
|
|
|
|
'model': 'hr.department',
|
|
|
|
'active_ids': [self.ref('hr.employee_root'), self.ref('hr.employee_qdp'), self.ref('hr.employee_al')]
|
|
|
|
}
|
|
|
|
data_dict = {
|
|
|
|
'date_from': datetime.today().strftime('%Y-%m-01'),
|
|
|
|
'depts': [(6, 0, [self.ref('hr.dep_sales')])],
|
|
|
|
'holiday_type': 'Approved'
|
|
|
|
}
|
|
|
|
test_reports.try_report_action(self.env.cr, self.env.uid, 'action_hr_holidays_summary_dept', wiz_data=data_dict, context=ctx, our_module='hr_holidays')
|
|
|
|
|
|
|
|
# Print the HR Holidays(Summary Employee) Report through the wizard
|
|
|
|
ctx = {
|
|
|
|
'model': 'hr.employee',
|
|
|
|
'active_ids': [self.ref('hr.employee_root'), self.ref('hr.employee_qdp'), self.ref('hr.employee_al')]
|
|
|
|
}
|
|
|
|
data_dict = {
|
|
|
|
'date_from': datetime.today().strftime('%Y-%m-01'),
|
|
|
|
'emp': [(6, 0, [self.ref('hr.employee_root'), self.ref('hr.employee_qdp'), self.ref('hr.employee_al')])],
|
|
|
|
'holiday_type': 'Approved'
|
|
|
|
}
|
|
|
|
test_reports.try_report_action(self.env.cr, self.env.uid, 'action_hr_holidays_summary_employee', wiz_data=data_dict, context=ctx, our_module='hr_holidays')
|