Files
enterprise-addons/l10n_au_hr_payroll_account/tests/test_performance.py
T

248 lines
10 KiB
Python

# -*- coding:utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import logging
import time
from datetime import date, datetime
from dateutil.relativedelta import relativedelta
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo.tests.common import users, warmup, tagged, new_test_user
from .tools import mock_skip_stp_api_calls
_logger = logging.getLogger(__name__)
@tagged('post_install_l10n', 'post_install', '-at_install', 'au_payroll_perf')
class TestPerformance(AccountTestInvoicingCommon):
@classmethod
@AccountTestInvoicingCommon.setup_country('au')
def setUpClass(cls):
super().setUpClass()
cls.env.user.group_ids |= cls.env.ref('hr_payroll.group_hr_payroll_manager')
cls.company_data['company'].write({
'country_id': cls.env.ref('base.au').id,
'street': 'Rue du Paradis',
'zip': '6870',
'city': 'Eghezee',
'vat': '83914571673',
'phone': '061928374',
"l10n_au_bms_id": "ODOO_TEST_BMS_ID",
"email": "au_company@odoo.com",
'l10n_au_branch_code': '100'
})
cls.company = cls.company_data['company']
admin = cls.env['res.users'].search([('login', '=', 'admin')])
admin.company_ids |= cls.company
admin.email = "admin@odoo.com"
cls.env.user.tz = 'Australia/Sydney'
cls.resource_calendar_40_hours_per_week = cls.env['resource.calendar'].create([{
'name': "Test Calendar : 38 Hours/Week",
'company_id': cls.env.company.id,
'hours_per_day': 7.6,
'tz': "Australia/Sydney",
'two_weeks_calendar': False,
'hours_per_week': 38.0,
'full_time_required_hours': 38.0,
'attendance_ids': [(5, 0, 0)] + [(0, 0, {
'name': "Attendance",
'dayofweek': dayofweek,
'hour_from': hour_from,
'hour_to': hour_to,
'day_period': day_period,
'work_entry_type_id': cls.env.ref('hr_work_entry.work_entry_type_attendance').id
}) for dayofweek, hour_from, hour_to, day_period in [
("0", 8.0, 12.0, "morning"),
("0", 12.0, 13.0, "lunch"),
("0", 13.0, 16.6, "afternoon"),
("1", 8.0, 12.0, "morning"),
("1", 12.0, 13.0, "lunch"),
("1", 13.0, 16.6, "afternoon"),
("2", 8.0, 12.0, "morning"),
("2", 12.0, 13.0, "lunch"),
("2", 13.0, 16.6, "afternoon"),
("3", 8.0, 12.0, "morning"),
("3", 12.0, 13.0, "lunch"),
("3", 13.0, 16.6, "afternoon"),
("4", 8.0, 12.0, "morning"),
("4", 12.0, 13.0, "lunch"),
("4", 13.0, 16.6, "afternoon"),
]],
}])
cls.EMPLOYEES_COUNT = 100
cls.date_from = date(2023, 8, 1)
cls.date_to = date(2023, 8, 31)
cls.addresses = cls.env['res.partner'].create([{
'name': "Test Private Address %i" % i,
'company_id': cls.company.id,
'street': 'Brussels Street',
'city': 'Brussels',
'zip': '2928',
'country_id': cls.env.ref('base.au').id,
} for i in range(cls.EMPLOYEES_COUNT)])
cls.employees = cls.env['hr.employee'].create([{
'name': "Test Employee %i" % i,
'work_contact_id': cls.addresses[i].id,
'resource_calendar_id': cls.resource_calendar_40_hours_per_week.id,
'company_id': cls.company.id,
'country_id': cls.env.ref('base.au').id,
'lang': 'en_US',
'spouse_birthdate': datetime.today() + relativedelta(years=-25, month=1, day=1),
'sex': 'male',
'birthday': "1990-01-01",
'private_email': "test%i@example.com" % i,
'private_phone': '123456789',
'private_street': 'My Street',
'private_city': 'Sydney',
'private_zip': '2000',
"private_state_id": cls.env.ref("base.state_au_2").id,
'private_country_id': cls.env.ref('base.au').id,
'date_generated_from': datetime(2020, 9, 1, 0, 0, 0),
'date_generated_to': datetime(2020, 9, 1, 0, 0, 0),
'structure_type_id': cls.env.ref('l10n_au_hr_payroll.structure_type_schedule_1').id,
'date_version': date(2018, 12, 31),
'contract_date_start': date(2018, 12, 31),
'wage': 10000,
} for i in range(cls.EMPLOYEES_COUNT)])
cls.super_fund = cls.env['l10n_au.super.fund'].create({
'name': 'Fund A',
'abn': '2345678912',
'address_id': cls.env['res.partner'].create({'name': "Fund A Partner"}).id,
'usi': 'USI123456789',
})
cls.env['l10n_au.super.account'].create([{
"employee_id": cls.employees[i].id,
"date_from": date(2018, 12, 31),
"fund_id": cls.super_fund.id,
} for i in range(cls.EMPLOYEES_COUNT)])
cls.employees[1].user_id = new_test_user(cls.env, login='employee1', groups='hr.group_hr_manager', email="test@example.com")
cls.company.l10n_au_hr_super_responsible_id = cls.employees[1]
cls.company.l10n_au_stp_responsible_id = cls.employees[1]
cls.contracts = cls.employees.version_id
# Public Holiday (global)
cls.env['resource.calendar.leaves'].create([{
'name': "Public Holiday (global)",
'calendar_id': cls.resource_calendar_40_hours_per_week.id,
'company_id': cls.company.id,
'date_from': datetime(2023, 8, 15, 5, 0, 0),
'date_to': datetime(2023, 8, 15, 23, 0, 0),
'resource_id': False,
'time_type': "leave",
'work_entry_type_id': cls.env.ref('hr_work_entry.l10n_au_work_entry_type_other').id
}])
# Everyone takes a legal leave the same day
legal_leave = cls.env.ref('hr_work_entry.work_entry_type_legal_leave')
cls.env['resource.calendar.leaves'].create([{
'name': "Legal Leave %i" % i,
'calendar_id': cls.resource_calendar_40_hours_per_week.id,
'company_id': cls.company.id,
'resource_id': cls.employees[i].resource_id.id,
'date_from': datetime(2023, 1, 2, 5, 0, 0),
'date_to': datetime(2023, 1, 2, 23, 0, 0),
'time_type': "leave",
'work_entry_type_id': legal_leave.id,
} for i in range(cls.EMPLOYEES_COUNT)])
cls.env['l10n_au.super.account'].create([{
"date_from": date(2023, 6, 1),
"employee_id": employee.id,
"fund_id": cls.super_fund.id
} for employee in cls.employees])
@users('admin')
@warmup
@mock_skip_stp_api_calls()
def test_performance_l10n_au_payroll_whole_flow(self):
# Create Opening Balances
self.env["l10n_au.previous.payroll.transfer"].with_company(self.company).create(
{
"l10n_au_previous_payroll_transfer_employee_ids": [
(0, 0, {
"employee_id": employee.id,
"previous_payroll_id": "employee_%s" % employee.id,
"l10n_au_income_stream_type": employee.l10n_au_income_stream_type,
}) for employee in self.employees
]
}
).action_transfer()
stp_update = self.env["l10n_au.stp"].search([("company_id", "=", self.company.id)])
self.assertEqual(len(stp_update), 1, "There should be one STP update event created")
self.assertTrue(stp_update.is_opening_balances, "The STP update event should be an opening balances event")
action = self.env['l10n_au.stp.submit'].create(
{'l10n_au_stp_id': stp_update.id}
)
action.stp_terms = True
action.action_submit()
# Work entry generation
self.employees.generate_work_entries(self.date_from, self.date_to)
structure = self.env.ref('l10n_au_hr_payroll.hr_payroll_structure_au_regular')
payslips_values = [{
'name': "Test Payslip %i" % i,
'employee_id': self.employees[i].id,
'version_id': self.contracts[i].id,
'company_id': self.company.id,
'struct_id': structure.id,
'date_from': self.date_from,
'date_to': self.date_to,
} for i in range(self.EMPLOYEES_COUNT)]
# Payslip Creation
with self.assertQueryCount(admin=1400): # randomness
self.env.user.partner_id.email = "admin@example.com"
start_time = time.time()
payslips = self.env['hr.payslip'].with_context(allowed_company_ids=self.company.ids).create(payslips_values)
# --- 0.11892914772033691 seconds ---
_logger.info("Payslips Creation: --- %s seconds ---", time.time() - start_time)
# Payslip Computation
with self.assertQueryCount(admin=1500): # query count patch l10n_au_hr_payroll
start_time = time.time()
payslips.compute_sheet()
# --- 2.032362699508667 seconds ---
_logger.info("Payslips Computation: --- %s seconds ---", time.time() - start_time)
# Payslip Validation
with self.assertQueryCount(admin=1000):
start_time = time.time()
payslips.action_payslip_done()
# --- 0.3815627098083496 seconds ---
_logger.info("Payslips Validation: --- %s seconds ---", time.time() - start_time)
# STP Submission
with self.assertQueryCount(admin=2500):
start_time = time.time()
stp = payslips._get_payslip_stp()[payslips[0].id]
self.assertTrue(stp, "The STP record should have been created when the payslip was created")
self.assertEqual(stp.state, "draft", "The STP record should be in draft state")
stp.submit_date = stp.submit_date or date.today()
action = self.env['l10n_au.stp.submit'].create(
{'l10n_au_stp_id': stp.id}
)
action.stp_terms = True
action.action_submit()
self.assertTrue(stp.xml_file, "The XML file should have been generated")
self.assertEqual(stp.state, "sent", "The STP record should be in sent state")
# --- 0.0 seconds ---
_logger.info("STP Submission: --- %s seconds ---", time.time() - start_time)