# Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.tests import common, tagged @tagged("post_install", "-at_install") class TestPayrollAccount(common.TransactionCase): """Тесты нативного учёта зарплаты (порт payroll_account на Odoo 19). В Odoo 19 «контракт» — это hr.version: параметры контракта (структура, оклад, журнал) задаются на сотруднике/версии, отдельной модели hr.contract с create() нет. """ @classmethod def setUpClass(cls): super().setUpClass() cls.company = cls.env.company cls.account_debit = cls.env["account.account"].create({ "name": "Debit Account", "code": "334411", "account_type": "expense", "reconcile": True, }) cls.account_credit = cls.env["account.account"].create({ "name": "Credit Account", "code": "114433", "account_type": "liability_current", "reconcile": True, }) cls.journal = cls.env["account.journal"].create({ "name": "Salary Journal - Test", "code": "SALTJ", "type": "general", "company_id": cls.company.id, }) # Структура зарплаты с правилами (демо BASE, если есть, иначе своя). cls.structure = cls.env.ref( "payroll.structure_base", raise_if_not_found=False) if not cls.structure: cat = cls.env["hr.salary.rule.category"].create( {"name": "Basic", "code": "BASIC"}) rule = cls.env["hr.salary.rule"].create({ "name": "Basic", "code": "BASIC", "sequence": 1, "category_id": cat.id, "condition_select": "none", "amount_select": "code", "amount_python_compute": "result = contract.wage", }) cls.structure = cls.env["hr.payroll.structure"].create({ "name": "Test", "code": "TST", "rule_ids": [(6, 0, rule.ids)]}) # Счета на правила структуры. for rule in cls.structure.rule_ids: rule.write({ "account_debit": cls.account_debit.id, "account_credit": cls.account_credit.id, }) # Сотрудник с версией-контрактом (Odoo 19). cls.employee = cls.env["hr.employee"].create({ "name": "John Test", "company_id": cls.company.id, "date_version": "2026-04-01", "contract_date_start": "2026-04-01", "struct_id": cls.structure.id, "wage": 5000.0, "journal_id": cls.journal.id, }) def _payslip(self): slip = self.env["hr.payslip"].create({ "name": "Payslip Test", "employee_id": self.employee.id, "struct_id": self.structure.id, "date_from": "2026-04-01", "date_to": "2026-04-30", }) slip.compute_sheet() return slip def test_00_payslip_creates_account_move(self): """Проведение payslip создаёт нативную проводку account.move.""" slip = self._payslip() self.assertEqual(slip.state, "verify") slip.action_payslip_done() self.assertEqual(slip.state, "done") self.assertTrue(slip.move_id, "account.move не создан") self.assertEqual(slip.move_id.state, "posted") def test_01_draft_removes_move(self): """Возврат в черновик удаляет/сторнирует проводку.""" slip = self._payslip() slip.action_payslip_done() self.assertTrue(slip.move_id) slip.action_payslip_draft() self.assertFalse(slip.move_id) def test_02_journal_autofill(self): """Журнал заполняется автоматически (из версии или дефолтный).""" slip = self.env["hr.payslip"].create({ "name": "Payslip J", "employee_id": self.employee.id, "struct_id": self.structure.id, "date_from": "2026-04-01", "date_to": "2026-04-30", }) self.assertTrue(slip.journal_id, "journal_id не заполнен")