194 lines
8.5 KiB
Python
194 lines
8.5 KiB
Python
|
||
from odoo import Command
|
||
from odoo.tests import tagged, HttpCase
|
||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||
|
||
|
||
@tagged('post_install', '-at_install')
|
||
class TestCommissionTours(TestSaleCommon, HttpCase):
|
||
"""Сквозной UI-тест модуля комиссий через web_tour.
|
||
|
||
Данные готовятся через ORM (R1), действия пользователя выполняются
|
||
в интерфейсе турами, результат каждого этапа проверяется по БД.
|
||
"""
|
||
|
||
@classmethod
|
||
def setUpClass(cls):
|
||
super().setUpClass()
|
||
company = cls.company_data['company']
|
||
cls.purchase_journal = cls.company_data['default_journal_purchase']
|
||
cls.expense_account = cls.company_data['default_account_expense']
|
||
|
||
# --- Клиент ---
|
||
cls.customer = cls.env['res.partner'].create({
|
||
'name': 'Tour Customer',
|
||
'company_id': False,
|
||
})
|
||
|
||
# --- Товар: складируемый/потребляемый, цена 100, без налогов ---
|
||
cls.tour_product = cls.env['product.product'].create({
|
||
'name': 'Tour Product',
|
||
'type': 'consu',
|
||
'list_price': 100.0,
|
||
'taxes_id': [Command.clear()],
|
||
})
|
||
|
||
# --- Партнёры-получатели комиссий ---
|
||
cls.agent_10 = cls.env['res.partner'].create({'name': 'Tour Agent Ten'})
|
||
cls.agent_5 = cls.env['res.partner'].create({'name': 'Tour Agent Five'})
|
||
|
||
Commission = cls.env['commission.commission']
|
||
cls.commission_10 = Commission.create({
|
||
'name': 'Tour Commission 10',
|
||
'calc_type': 'percentage',
|
||
'percentage': 10.0,
|
||
'partner_id': cls.agent_10.id,
|
||
'journal_id': cls.purchase_journal.id,
|
||
'account_id': cls.expense_account.id,
|
||
'company_id': company.id,
|
||
})
|
||
cls.commission_5 = Commission.create({
|
||
'name': 'Tour Commission 5',
|
||
'calc_type': 'percentage',
|
||
'percentage': 5.0,
|
||
'partner_id': cls.agent_5.id,
|
||
'journal_id': cls.purchase_journal.id,
|
||
'account_id': cls.expense_account.id,
|
||
'company_id': company.id,
|
||
})
|
||
|
||
# --- Пользователь: продавец + менеджер комиссий ---
|
||
# group_commission_manager включает group_commission_viewer.
|
||
cls.tour_user = cls.env['res.users'].create({
|
||
'name': 'Tour Commission Manager',
|
||
'login': 'tour_commission',
|
||
'password': 'tour_commission',
|
||
'company_id': company.id,
|
||
'company_ids': [Command.set([company.id])],
|
||
'group_ids': [Command.set([
|
||
cls.env.ref('sales_team.group_sale_salesman_all_leads').id,
|
||
cls.env.ref('ruodoo_commission.group_commission_manager').id,
|
||
# Право просматривать счета поставщика (открытие по смарт-кнопке).
|
||
cls.env.ref('account.group_account_invoice').id,
|
||
])],
|
||
})
|
||
|
||
# ------------------------------------------------------------------
|
||
def _get_order(self):
|
||
return self.env['sale.order'].search(
|
||
[('partner_id', '=', self.customer.id)], limit=1,
|
||
)
|
||
|
||
def test_commission_full_flow(self):
|
||
# =============== Этап 1: заказ + комиссии + начисление ===============
|
||
self.start_tour(
|
||
'/odoo', 'ruodoo_commission_order_tour', login='tour_commission',
|
||
)
|
||
|
||
order = self._get_order()
|
||
self.assertTrue(order, msg="Этап 1: заказ должен быть создан")
|
||
self.assertEqual(
|
||
order.state, 'sale',
|
||
msg="Этап 1: заказ должен быть подтверждён (state='sale')",
|
||
)
|
||
self.assertEqual(
|
||
len(order.order_line), 1,
|
||
msg="Этап 1: в заказе должна быть одна строка",
|
||
)
|
||
line = order.order_line
|
||
self.assertEqual(
|
||
line.product_id, self.tour_product,
|
||
msg="Этап 1: товар строки — Tour Product",
|
||
)
|
||
self.assertEqual(
|
||
line.product_uom_qty, 10.0,
|
||
msg="Этап 1: количество должно быть 10",
|
||
)
|
||
self.assertEqual(
|
||
line.commission_ids, self.commission_10 | self.commission_5,
|
||
msg="Этап 1: к строке должны быть привязаны обе комиссии",
|
||
)
|
||
|
||
# Суммы комиссий: 10 шт × 100 = 1000; 10% = 100; 5% = 50; итог 150.
|
||
self.assertAlmostEqual(
|
||
line.commission_amount, 150.0,
|
||
msg="Этап 1: сумма комиссий строки должна быть 150",
|
||
)
|
||
self.assertAlmostEqual(
|
||
order.amount_commission, 150.0,
|
||
msg="Этап 1: «ИТОГО КОМИССИЙ» заказа должно быть 150",
|
||
)
|
||
# Комиссии не входят в итог заказа.
|
||
self.assertAlmostEqual(
|
||
order.amount_total, 1000.0,
|
||
msg="Этап 1: итог заказа не должен включать комиссии (1000)",
|
||
)
|
||
|
||
# Начислены счета комиссий: два партнёра-получателя → два билла.
|
||
bills = order.commission_bill_ids
|
||
self.assertEqual(
|
||
len(bills), 2,
|
||
msg="Этап 1: должно быть два счёта комиссий (по получателям)",
|
||
)
|
||
self.assertEqual(
|
||
set(bills.mapped('move_type')), {'in_invoice'},
|
||
msg="Этап 1: счета комиссий — счета поставщика (in_invoice)",
|
||
)
|
||
self.assertEqual(
|
||
set(bills.mapped('state')), {'posted'},
|
||
msg="Этап 1: счета комиссий должны быть проведены",
|
||
)
|
||
|
||
# Суммы в биллах совпадают с суммами комиссий заказа.
|
||
bill_10 = bills.filtered(lambda m: m.partner_id == self.agent_10)
|
||
bill_5 = bills.filtered(lambda m: m.partner_id == self.agent_5)
|
||
self.assertAlmostEqual(
|
||
bill_10.amount_total, 100.0,
|
||
msg="Этап 1: счёт агенту 10% должен быть на 100",
|
||
)
|
||
self.assertAlmostEqual(
|
||
bill_5.amount_total, 50.0,
|
||
msg="Этап 1: счёт агенту 5% должен быть на 50",
|
||
)
|
||
self.assertAlmostEqual(
|
||
sum(bills.mapped('amount_total')), order.amount_commission,
|
||
msg="Этап 1: сумма счетов должна совпадать с итогом комиссий заказа",
|
||
)
|
||
|
||
# Счета подставляются правильно: журнал и счёт расходов из карточки.
|
||
self.assertEqual(
|
||
set(bills.mapped('journal_id')), {self.purchase_journal},
|
||
msg="Этап 1: журнал счетов — из настроек комиссии",
|
||
)
|
||
self.assertEqual(
|
||
set(bills.invoice_line_ids.mapped('account_id')),
|
||
{self.expense_account},
|
||
msg="Этап 1: счёт расходов строк — из настроек комиссии",
|
||
)
|
||
|
||
# =============== Этап 2: смарт-кнопка «Комиссии» ===============
|
||
self.assertEqual(
|
||
order.commission_bill_count, 2,
|
||
msg="Этап 2: счётчик смарт-кнопки должен быть 2",
|
||
)
|
||
self.start_tour(
|
||
'/odoo', 'ruodoo_commission_smart_button_tour',
|
||
login='tour_commission',
|
||
)
|
||
|
||
# =============== Этап 3: отмена заказа ===============
|
||
bill_ids = bills.ids
|
||
self.start_tour(
|
||
'/odoo', 'ruodoo_commission_cancel_tour', login='tour_commission',
|
||
)
|
||
order.invalidate_recordset()
|
||
self.assertEqual(
|
||
order.state, 'cancel',
|
||
msg="Этап 3: заказ должен быть отменён",
|
||
)
|
||
remaining = self.env['account.move'].search([('id', 'in', bill_ids)])
|
||
self.assertFalse(
|
||
remaining,
|
||
msg="Этап 3: счета комиссий должны быть удалены при отмене заказа",
|
||
)
|