- Создан новый класс SystemCustomerProtectionTestCase с 5 критичными тестами - Тест создания системного клиента с правильными атрибутами - Тест защиты от удаления системного клиента (ValidationError) - Тест защиты email системного клиента от изменения - Тест защиты флага is_system_customer от изменения - Тест что обычные клиенты не затронуты защитой - Исправлена логика в Customer.save(): проверка теперь использует original.is_system_customer - Добавлен импорт ValidationError из django.core.exceptions - Рефакторинг структуры тестов customers: - Разделены тесты по отдельным модулям в папке customers/tests/ - test_search_strategies.py - тесты стратегий поиска - test_system_customer.py - тесты защиты системного клиента - test_wallet_balance.py - тесты баланса кошелька - test_wallet_service.py - тесты WalletService - test_wallet_model.py - тесты модели WalletTransaction - Обновлён анализ тестов: 50 тестов (было 45), все проходят успешно - Критичная функциональность POS системы теперь покрыта тестами - Учтена tenant-система (используется TenantTestCase)
143 lines
5.7 KiB
Python
143 lines
5.7 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
Тесты для сервиса кошелька (WalletService).
|
||
|
||
Используем TenantTestCase для корректной работы с tenant-системой.
|
||
"""
|
||
from decimal import Decimal
|
||
|
||
from django.core.cache import cache
|
||
from django_tenants.test.cases import TenantTestCase
|
||
|
||
from customers.models import Customer
|
||
from customers.services.wallet_service import WalletService
|
||
|
||
|
||
class WalletServiceTestCase(TenantTestCase):
|
||
"""Тесты WalletService."""
|
||
|
||
def setUp(self):
|
||
"""Создаём тестового клиента."""
|
||
self.customer = Customer.objects.create(name="Тестовый клиент")
|
||
cache.clear()
|
||
|
||
def tearDown(self):
|
||
cache.clear()
|
||
|
||
def test_create_transaction_deposit(self):
|
||
"""create_transaction создаёт пополнение с положительной суммой."""
|
||
txn = WalletService.create_transaction(
|
||
customer=self.customer,
|
||
amount=Decimal('50.00'),
|
||
transaction_type='deposit',
|
||
description='Тестовое пополнение'
|
||
)
|
||
|
||
self.assertEqual(txn.signed_amount, Decimal('50.00'))
|
||
self.assertEqual(txn.transaction_type, 'deposit')
|
||
self.assertEqual(txn.balance_after, Decimal('50.00'))
|
||
self.assertEqual(self.customer.wallet_balance, Decimal('50.00'))
|
||
|
||
def test_create_transaction_spend(self):
|
||
"""create_transaction создаёт списание с отрицательной суммой."""
|
||
# Сначала пополняем
|
||
WalletService.create_transaction(
|
||
customer=self.customer,
|
||
amount=Decimal('100.00'),
|
||
transaction_type='deposit'
|
||
)
|
||
|
||
# Затем списываем
|
||
txn = WalletService.create_transaction(
|
||
customer=self.customer,
|
||
amount=Decimal('30.00'),
|
||
transaction_type='spend',
|
||
description='Тестовое списание'
|
||
)
|
||
|
||
self.assertEqual(txn.signed_amount, Decimal('-30.00'))
|
||
self.assertEqual(txn.transaction_type, 'spend')
|
||
self.assertEqual(txn.balance_after, Decimal('70.00'))
|
||
self.assertEqual(self.customer.wallet_balance, Decimal('70.00'))
|
||
|
||
def test_create_transaction_spend_insufficient_funds(self):
|
||
"""Списание при недостаточном балансе вызывает ValueError."""
|
||
with self.assertRaises(ValueError) as context:
|
||
WalletService.create_transaction(
|
||
customer=self.customer,
|
||
amount=Decimal('100.00'),
|
||
transaction_type='spend'
|
||
)
|
||
|
||
self.assertIn('Недостаточно средств', str(context.exception))
|
||
|
||
def test_adjust_balance_positive(self):
|
||
"""Положительная корректировка увеличивает баланс."""
|
||
txn = WalletService.adjust_balance(
|
||
customer_id=self.customer.pk,
|
||
amount=Decimal('75.00'),
|
||
description='Тестовое пополнение администратором',
|
||
user=None
|
||
)
|
||
|
||
self.assertEqual(txn.signed_amount, Decimal('75.00'))
|
||
self.assertEqual(txn.transaction_type, 'adjustment')
|
||
self.assertEqual(self.customer.wallet_balance, Decimal('75.00'))
|
||
|
||
def test_adjust_balance_negative(self):
|
||
"""Отрицательная корректировка уменьшает баланс."""
|
||
# Сначала пополняем
|
||
WalletService.adjust_balance(
|
||
customer_id=self.customer.pk,
|
||
amount=Decimal('100.00'),
|
||
description='Начальное пополнение',
|
||
user=None
|
||
)
|
||
|
||
# Отрицательная корректировка
|
||
txn = WalletService.adjust_balance(
|
||
customer_id=self.customer.pk,
|
||
amount=Decimal('-40.00'),
|
||
description='Списание администратором',
|
||
user=None
|
||
)
|
||
|
||
self.assertEqual(txn.signed_amount, Decimal('-40.00'))
|
||
self.assertEqual(self.customer.wallet_balance, Decimal('60.00'))
|
||
|
||
def test_adjust_balance_negative_insufficient(self):
|
||
"""Отрицательная корректировка с недостаточным балансом вызывает ValueError."""
|
||
with self.assertRaises(ValueError) as context:
|
||
WalletService.adjust_balance(
|
||
customer_id=self.customer.pk,
|
||
amount=Decimal('-50.00'),
|
||
description='Списание',
|
||
user=None
|
||
)
|
||
|
||
self.assertIn('отрицательному балансу', str(context.exception))
|
||
|
||
def test_adjust_balance_requires_description(self):
|
||
"""Корректировка без описания вызывает ValueError."""
|
||
with self.assertRaises(ValueError) as context:
|
||
WalletService.adjust_balance(
|
||
customer_id=self.customer.pk,
|
||
amount=Decimal('50.00'),
|
||
description='',
|
||
user=None
|
||
)
|
||
|
||
self.assertIn('Описание обязательно', str(context.exception))
|
||
|
||
def test_adjust_balance_zero_amount_fails(self):
|
||
"""Корректировка с нулевой суммой вызывает ValueError."""
|
||
with self.assertRaises(ValueError) as context:
|
||
WalletService.adjust_balance(
|
||
customer_id=self.customer.pk,
|
||
amount=Decimal('0'),
|
||
description='Нулевая корректировка',
|
||
user=None
|
||
)
|
||
|
||
self.assertIn('не может быть нулевой', str(context.exception))
|