odex30_standard/exp_payroll_custom/tests/test_payroll_flow.py

182 lines
6.4 KiB
Python

# -*- coding: utf-8 -*-
from odoo.tests.common import TransactionCase, Form
from odoo.exceptions import UserError
from odoo.tests import tagged
from datetime import date, datetime, timedelta
from dateutil.relativedelta import relativedelta
class TestPayrollAdvanceFlow(TransactionCase):
def setUp(cls):
super(TestPayrollAdvanceFlow, cls).setUp()
cls.company = cls.env.company
cls.account_salary = cls.env['account.account'].create({
'name': 'Basic Salary Account',
'code': '600001',
'account_type': 'expense',
'reconcile': True,
})
cls.account_payable = cls.env['account.account'].create({
'name': 'Salaries Payable',
'code': '200001',
'account_type': 'liability_payable',
'reconcile': True,
})
cls.journal = cls.env['account.journal'].create({
'name': 'Salary Journal',
'type': 'general',
'code': 'SAL',
'default_account_id': cls.account_payable.id,
})
cls.rule_basic = cls.env['hr.salary.rule'].create({
'name': 'Basic Salary',
'sequence': 1,
'code': 'BASIC',
'category_id': cls.env.ref('exp_hr_payroll.ALW').id,
'condition_select': 'none',
'amount_select': 'code',
'amount_python_compute': 'result = contract.wage',
'rule_debit_account_id': cls.account_salary.id,
})
cls.rule_net = cls.env['hr.salary.rule'].create({
'name': 'Net Salary',
'sequence': 100,
'code': 'NET',
'category_id': cls.env.ref('exp_hr_payroll.DED').id,
'condition_select': 'none',
'amount_select': 'code',
'amount_python_compute': 'result = categories.BASIC + categories.ALW + categories.DED',
'rule_credit_account_id': cls.account_payable.id,
})
cls.structure = cls.env['hr.payroll.structure'].create({
'name': 'Standard Structure',
'type': 'scale',
'code': 'STRUCT_001',
'rule_ids': [(4, cls.rule_basic.id), (4, cls.rule_net.id)],
'transfer_type': 'one_by_one',
})
cls.employee = cls.env['hr.employee'].create({
'name': 'Test Employee Payroll',
'first_hiring_date': date.today() - relativedelta(years=1),
'state': 'open',
})
cls.contract = cls.env['hr.contract'].create({
'name': 'Contract For Test',
'employee_id': cls.employee.id,
'state': 'program_directory',
'wage': 5000.0,
'salary_scale': cls.structure.id,
'journal_id': cls.journal.id,
'date_start': date.today() - relativedelta(years=1),
})
def test_01_payslip_compute_and_transfer(self):
date_from = date.today().replace(day=1)
date_to = date.today() + relativedelta(months=+1, day=1, days=-1)
payslip = self.env['hr.payslip'].create({
'name': 'Test Payslip',
'employee_id': self.employee.id,
'date_from': date_from,
'date_to': date_to,
'contract_id': self.contract.id,
'struct_id': self.structure.id
})
payslip.compute_sheet()
self.assertEqual(payslip.state, 'computed', "State should be 'computed' after computing sheet")
basic_line = payslip.line_ids.filtered(lambda l: l.code == 'BASIC')
self.assertEqual(basic_line.total, 5000.0, "Basic salary should be 5000")
payslip.compute_totals()
self.assertEqual(payslip.total_allowances, 5000.0, "Total allowances should be calculated correctly")
payslip.confirm()
self.assertEqual(payslip.state, 'confirmed')
payslip.transfer()
self.assertEqual(payslip.state, 'transfered')
self.assertTrue(payslip.move_id, "Journal Entry should be created")
self.assertEqual(payslip.move_id.state, 'draft', "Move should be created in draft state initially")
def test_02_payslip_loans_integration(self):
payslip = self.env['hr.payslip'].create({
'name': 'Loan Payslip',
'employee_id': self.employee.id,
'date_from': date.today().replace(day=1),
'date_to': date.today() + relativedelta(months=+1, day=1, days=-1),
})
self.env['payslip.loans'].create({
'payslip_loan': payslip.id,
'name': 'Car Loan',
'code': 'LOAN01',
'amount': 500.0,
'date': date.today(),
'account_id': self.account_payable.id,
})
payslip.compute_totals()
self.assertEqual(payslip.total_loans, 500.0, "Total loans field should calculate sum of loan lines")
self.assertEqual(payslip.total_sum, 500.0, "Total sum logic check (depends on allowances setup)")
def test_03_payslip_run_batch_process(self):
date_start = date.today().replace(day=1)
date_end = date.today() + relativedelta(months=+1, day=1, days=-1)
payslip_run = self.env['hr.payslip.run'].create({
'name': 'Monthly Run',
'date_start': date_start,
'date_end': date_end,
'salary_scale': self.structure.id,
})
payslip_run.check_date_start()
self.assertEqual(payslip_run.date_end, date_end)
payslip_run.compute_sheet()
self.assertTrue(payslip_run.slip_ids, "Payslips should be generated for eligible employees")
generated_slip = payslip_run.slip_ids[0]
self.assertEqual(generated_slip.employee_id, self.employee)
self.assertEqual(generated_slip.state, 'computed')
payslip_run.confirm()
self.assertEqual(generated_slip.state, 'confirmed')
payslip_run.transfer()
self.assertEqual(payslip_run.state, 'transfered')
self.assertTrue(payslip_run.move_id or generated_slip.move_id, "Accounting move should be generated")
def test_04_payslip_withdraw_and_reset(self):
payslip = self.env['hr.payslip'].create({
'name': 'Withdraw Test',
'employee_id': self.employee.id,
'date_from': date.today(),
'date_to': date.today(),
})
payslip.compute_sheet()
payslip.confirm()
payslip.withdraw()
self.assertEqual(payslip.state, 'draft', "State should return to draft after withdraw")
self.assertFalse(payslip.move_id, "Account move should be unlinked/deleted")