odoo18/addons_extensions/hr_payroll/tests/test_dashboard.py

233 lines
10 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import base64
from freezegun import freeze_time
from datetime import date
from dateutil.relativedelta import relativedelta
from odoo.tests import HttpCase, tagged, TransactionCase
from odoo.tools import file_open
from odoo.addons.mail.tests.common import mail_new_test_user
@tagged('-at_install', 'post_install', 'payroll_dashboard_ui')
class TestDashboardUi(HttpCase):
def test_dashboard_ui(self):
# This test is meant to test the basic features of the dashboard
company = self.env['res.company'].create({
'name': 'Payroll Dashboard Company',
})
user = mail_new_test_user(
self.env, name="Laurie Poiret", login="dashboarder",
groups="base.group_user,hr_payroll.group_hr_payroll_manager",
company_id=company.id)
if self.env.ref('sign.group_sign_manager', raise_if_not_found=False):
user.groups_id += self.env.ref('sign.group_sign_manager', raise_if_not_found=False)
department = self.env['hr.department'].create({
'name': 'Payroll',
'company_id': company.id,
})
# this will make one of the action box non empty
self.env['hr.employee'].create({
'user_id': user.id,
'company_id': company.id,
'department_id': department.id,
'resource_calendar_id': company.resource_calendar_id.id,
})
# The test will break if sign is installed
if self.env['ir.module.module'].search([('name', '=', 'sign'), ('state', '=', 'installed')]):
user.groups_id += self.env.ref('sign.group_sign_manager', raise_if_not_found=False)
with file_open('sign/static/demo/employment.pdf', "rb") as f:
pdf_content = base64.b64encode(f.read())
attachment = self.env['ir.attachment'].with_user(user).create({
'type': 'binary',
'datas': pdf_content,
'name': 'Employment Contract.pdf',
})
self.env['sign.template'].with_user(user).create({
'attachment_id': attachment.id,
'sign_item_ids': [(6, 0, [])],
})
self.start_tour("/", "payroll_dashboard_ui_tour", login='dashboarder', timeout=300)
@tagged('-at_install', 'post_install', 'payroll_dashboard')
class TestDashboard(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.company = cls.env['res.company'].create({
'name': 'Dashboard Company',
})
cls.user = mail_new_test_user(
cls.env, name="Laurie Poiret", login="dashboarder",
groups="base.group_user,hr_payroll.group_hr_payroll_manager",
company_id=cls.company.id,
)
def test_multi_sections(self):
# Test that the dashboard function returns a dict with all keys, regardless of emptyness
Payslip = self.env['hr.payslip']
all_sections = Payslip._get_dashboard_default_sections()
dashboard = Payslip.get_payroll_dashboard_data(all_sections)
self.assertTrue(all(section in dashboard for section in all_sections))
sub_sections = all_sections[1:3]
dashboard = Payslip.get_payroll_dashboard_data(sub_sections)
self.assertEqual(len(sub_sections), len(dashboard))
self.assertTrue(all(section in dashboard for section in sub_sections))
def test_dashboard_batches(self):
# Tests the dates for batches, by default it should return
# the batches for the last 3 'active' months ignoring
# any month that has been skipped
payslip_runs = self.env['hr.payslip.run'].create([
{
'name': 'Batch 1 - Oct',
'date_start': '2021-10-01',
'date_end': '2021-10-31',
'company_id': self.company.id,
},
{
'name': 'Batch 1 - Sept',
'date_start': '2021-09-01',
'date_end': '2021-09-30',
'company_id': self.company.id,
},
{
'name': 'Batch 2 - Sept',
'date_start': '2021-09-01',
'date_end': '2021-09-30',
'company_id': self.company.id,
},
{
'name': 'Batch 1 - June',
'date_start': '2021-06-01',
'date_end': '2021-06-30',
'company_id': self.company.id,
},
{
'name': 'Batch 1 - May',
'date_start': '2021-05-01',
'date_end': '2021-05-31',
'company_id': self.company.id,
},
])
with freeze_time(date(2021, 12, 31)):
batches_to_return = payslip_runs.filtered(lambda r: r.date_start.month >= 6)
dashboard = self.env['hr.payslip'].with_user(self.user).get_payroll_dashboard_data(sections=['batches'])
self.assertTrue('batches' in dashboard)
self.assertEqual(len(dashboard['batches']), len(batches_to_return))
self.assertEqual(set(read['id'] for read in dashboard['batches']), set(batches_to_return.ids))
def test_dashboard_empty_stats(self):
# Tests that when stats are empty they are tagged as sample
dashboard = self.env['hr.payslip'].with_user(self.user).get_payroll_dashboard_data(sections=['stats'])
self.assertTrue(all(stats['is_sample'] is True for stats in dashboard['stats']))
def _test_dashboard_stats(self):
# Tests that the result inside of the stats dashboard is somewhat coherent
emp_1, emp_2, emp_3 = self.env['hr.employee'].create([
{'name': 'Employee 1', 'company_id': self.company.id},
{'name': 'Employee 2', 'company_id': self.company.id},
{'name': 'Employee 3', 'company_id': self.company.id}
])
today = date.today()
self.env['hr.contract'].create([
{
'name': 'Contract 1',
'employee_id': emp_1.id,
'date_start': today - relativedelta(months=1, day=1),
'state': 'open',
'wage': 1000,
'company_id': self.company.id,
},
{
'name': 'Contract 2',
'employee_id': emp_2.id,
'date_start': today - relativedelta(day=1),
'state': 'open',
'wage': 2000,
'company_id': self.company.id,
},
{
'name': 'Contract 3',
'employee_id': emp_3.id,
'date_start': today + relativedelta(months=1, day=1),
'state': 'open',
'wage': 4500,
'company_id': self.company.id,
}
])
self.env['hr.employee'].flush_model()
self.env['hr.contract'].flush_model()
dashboard = self.env['hr.payslip'].with_user(self.user).get_payroll_dashboard_data(sections=['stats'])
# Identify the different sections
employer_cost = employees = None
for section in dashboard['stats']:
if section['id'] == 'employer_cost':
employer_cost = section
elif section['id'] == 'employees':
employees = section
self.assertTrue(all([employer_cost, employees]))
# Check employees monthly
# Employees contains the number of unique employees that worked on that period
employees_stat = employees['data']['monthly']
self.assertEqual(employees_stat[0]['value'], 1)
self.assertEqual(employees_stat[1]['value'], 2)
self.assertEqual(employees_stat[2]['value'], 3)
# Check yearly employees outside the function as the assertions are dependent on the freeze time date
return employees['data']['yearly']
def test_dashboard_stat_end_of_year(self):
# Tests the dashboard at the end of a year
with freeze_time(date(2021, 12, 1)):
employees_stat = self._test_dashboard_stats()
self.assertEqual(employees_stat[0]['value'], 0)
self.assertEqual(employees_stat[1]['value'], 2)
self.assertEqual(employees_stat[2]['value'], 3)
def test_dashboard_stat_start_of_year(self):
# Tests the dashboard again but at the start of a year
with freeze_time(date(2021, 1, 1)):
employees_stat = self._test_dashboard_stats()
self.assertEqual(employees_stat[0]['value'], 1)
self.assertEqual(employees_stat[1]['value'], 3)
self.assertEqual(employees_stat[2]['value'], 3)
def test_dashboard_stat_middle_of_year(self):
# Tests the dashboard again but at the middle of the year
with freeze_time(date(2021, 6, 1)):
employees_stat = self._test_dashboard_stats()
self.assertEqual(employees_stat[0]['value'], 0)
self.assertEqual(employees_stat[1]['value'], 3)
self.assertEqual(employees_stat[2]['value'], 3)
def test_dashboard_no_english_language_access(self):
# Tests that we can access the dashboard when we don't have english language active
Payslip = self.env['hr.payslip']
# We remove english from every model of the app that needed it to get french as main and unique language
self.env['res.lang']._activate_lang('fr_FR')
fr_lang = self.env['res.lang'].search([['code', '=', 'fr_FR']])
if 'website' in self.env:
self.env['website'].search([]).write({'language_ids': fr_lang.ids, 'default_lang_id': fr_lang.id})
self.env['res.users'].with_context(active_test=False).search([]).write({'lang' : 'fr_FR'})
self.env['res.partner'].search([]).write({'lang' : 'fr_FR'})
self.env['res.lang'].search([['code', '=', 'en_US']]).active = False
# We only test that we won't receive a traceback when we don't have access to the english language
# The normal flow of the functions are tested above
Payslip.get_payroll_dashboard_data()
Payslip.get_dashboard_warnings()