odex30_standard/employee_requests/tests/test_overtime_process.py

189 lines
6.8 KiB
Python

# -*- coding: utf-8 -*-
from odoo.tests.common import TransactionCase
from odoo.exceptions import UserError
from odoo import fields
from datetime import date, timedelta
class TestOvertimeProcess(TransactionCase):
def setUp(self):
super(TestOvertimeProcess, self).setUp()
self.account_type_expenses = self.env['account.account'].search([('account_type', '=', 'expense')], limit=1)
if not self.account_type_expenses:
user_type_expense = self.env.ref('account.data_account_type_expenses')
self.account_type_expenses = self.env['account.account'].create({
'name': 'Overtime Expense',
'code': 'X6000',
'account_type': 'expense',
'reconcile': True,
})
self.overtime_account = self.account_type_expenses
self.journal_account = self.env['account.account'].search([('account_type', '=', 'asset_cash')], limit=1)
self.journal = self.env['account.journal'].create({
'name': 'Overtime Journal',
'type': 'cash',
'code': 'OTJ',
'default_account_id': self.journal_account.id,
})
self.working_hours = self.env['resource.calendar'].create({
'name': 'Standard 40 Hours',
'hours_per_day': 8.0,
# 'max_overtime_hour': 10.0,
# 'overtime_factor_daily': 1.5,
# 'overtime_factor_holiday': 2.0,
# 'work_days': 20,
# 'work_hour': 8,
# 'journal_overtime_id': self.journal.id,
# 'account_overtime_id': self.overtime_account.id,
})
self.working_hours.write({
'max_overtime_hour': 20.0,
'overtime_factor_daily': 1.5,
'overtime_factor_holiday': 2.0,
'work_days': 30,
'work_hour': 8,
'journal_overtime_id': self.journal.id,
'account_overtime_id': self.overtime_account.id,
})
self.employee = self.env['hr.employee'].create({
'name': 'Ahmed Tester',
'state': 'open',
'first_hiring_date': date.today() - timedelta(days=365), # موظف منذ سنة
})
self.contract = self.env['hr.contract'].create({
'name': 'Contract for Ahmed',
'employee_id': self.employee.id,
'state': 'open',
'wage': 5000, # الراتب الأساسي
'resource_calendar_id': self.working_hours.id,
# 'total_allowance': 1000,
# 'salary': 5000,
})
self.contract.write({
'total_allowance': 1000,
'salary': 5000,
})
def test_overtime_period_constraint_cross_month(self):
# Arrange
date_from = date(2025, 1, 31)
date_to = date(2025, 2, 1) # شهر مختلف
# Act & Assert
with self.assertRaises(UserError):
request = self.env['employee.overtime.request'].create({
'employee_id': self.employee.id,
'request_date': date_from,
'date_from': date_from,
'date_to': date_to,
'line_ids_over_time': [(0, 0, {
'employee_id': self.employee.id,
'over_time_workdays_hours': 5.0,
})]
})
request.line_ids_over_time.get_max_remain_hours()
def test_max_hours_constraint_and_exception(self):
# Arrange
self.working_hours.write({'max_overtime_hour': 10.0})
date_from = date(2025, 3, 1)
date_to = date(2025, 3, 5)
with self.assertRaises(UserError):
self.env['employee.overtime.request'].create({
'employee_id': self.employee.id,
'date_from': date_from,
'date_to': date_to,
'exception': False,
'line_ids_over_time': [(0, 0, {
'employee_id': self.employee.id,
'over_time_workdays_hours': 15.0,
})]
})
request = self.env['employee.overtime.request'].create({
'employee_id': self.employee.id,
'date_from': date_from,
'date_to': date_to,
'exception': True,
'line_ids_over_time': [(0, 0, {
'employee_id': self.employee.id,
'over_time_workdays_hours': 15.0,
})]
})
# Assert
self.assertTrue(request.line_ids_over_time.exception, "Exception flag should be propagated to lines")
def test_calculate_daily_rate(self):
expected_hourly_rate = 8500.0 / 240.0
# Act
request = self.env['employee.overtime.request'].create({
'employee_id': self.employee.id,
'date_from': date(2025, 4, 1),
'date_to': date(2025, 4, 1),
'line_ids_over_time': [(0, 0, {
'employee_id': self.employee.id,
'over_time_workdays_hours': 2.0,
})]
})
line = request.line_ids_over_time[0]
# Assert
self.assertAlmostEqual(line.daily_hourly_rate, expected_hourly_rate, places=2,
msg="Daily hourly rate calculation is incorrect")
expected_total_price = expected_hourly_rate * 2.0
self.assertAlmostEqual(line.price_hour, expected_total_price, places=2,
msg="Total price calculation is incorrect")
def test_accounting_transfer_validation(self):
# Arrange
request = self.env['employee.overtime.request'].create({
'employee_id': self.employee.id,
'date_from': date(2025, 5, 1),
'date_to': date(2025, 5, 2),
'transfer_type': 'accounting',
'line_ids_over_time': [(0, 0, {
'employee_id': self.employee.id,
'over_time_workdays_hours': 10.0,
})]
})
request.state = 'executive_office'
# Act
request.validated()
# Assert
self.assertEqual(request.state, 'validated', "State should be validated")
line = request.line_ids_over_time[0]
self.assertTrue(line.move_id, "Account Move should be created")
self.assertEqual(line.move_id.state, 'draft', "Move should be in draft state initially")
debit_line = line.move_id.line_ids.filtered(lambda l: l.debit > 0)
credit_line = line.move_id.line_ids.filtered(lambda l: l.credit > 0)
self.assertTrue(debit_line and credit_line, "Should have debit and credit lines")
self.assertEqual(debit_line.account_id, self.overtime_account, "Debit account mismatch")
self.assertEqual(credit_line.account_id, self.journal.default_account_id, "Credit account mismatch")
self.assertAlmostEqual(debit_line.debit, line.price_hour, places=2, msg="Debit amount mismatch")