Files
ACORE/apps/it_manager/tests_billing.py
T
2026-09-21 20:37:18 +03:00

208 lines
8.1 KiB
Python

from datetime import date
from decimal import Decimal
from django.contrib.auth.models import Group
from django.test import TestCase
from apps.it_manager.admin import InternetContractForm
from apps.it_manager.billing import _build_billing_rows
from apps.it_manager.models import InternetContract, InternetContractPayment, InternetProvider
from apps.locations.models.base import Location
from core.models.directories import Directory, DirectoryType
from core.portal_access import user_can_access
from core.test_utils import login_2fa, grant_all_locations
from core.tests_portal_access import make_employee
def _ensure_contract_status():
dtype, _ = DirectoryType.objects.get_or_create(code='contract_status', defaults={'name': 'Статус договора'})
status, _ = Directory.objects.get_or_create(
directory_type=dtype, code='active', defaults={'name': 'Активный'},
)
return status
def _make_location(**overrides):
region_type, _ = DirectoryType.objects.get_or_create(code='location_region', defaults={'name': 'Регион'})
region, _ = Directory.objects.get_or_create(directory_type=region_type, code='test', defaults={'name': 'Тест'})
defaults = {
'address': 'Test addr',
'location_type': 'office',
'location_region': region,
'is_active': True,
}
defaults.update(overrides)
return Location.objects.create(**defaults)
def _ensure_service_type():
dtype, _ = DirectoryType.objects.get_or_create(code='contract_service_type', defaults={'name': 'Тип услуги'})
service, _ = Directory.objects.get_or_create(
directory_type=dtype, code='internet', defaults={'name': 'Интернет'},
)
return service
class InternetContractHierarchyTests(TestCase):
def setUp(self):
self.status = _ensure_contract_status()
self.service = _ensure_service_type()
self.provider = InternetProvider.objects.create(name='WESTELECOM')
self.location = _make_location(location_type='pharmacy', address='Pharmacy addr')
self.master = InternetContract.objects.create(
provider=self.provider,
location=None,
contract_number='708052',
service_type=self.service,
status=self.status,
start_date=date(2024, 1, 1),
is_framework=True,
monthly_cost=Decimal('1000.00'),
)
self.child = InternetContract.objects.create(
provider=self.provider,
location=self.location,
contract_number='70805208',
service_type=self.service,
status=self.status,
start_date=date(2024, 1, 1),
parent_contract=self.master,
monthly_cost=Decimal('300.00'),
)
def test_child_links_to_master(self):
self.assertIsNone(self.master.location_id)
self.assertEqual(self.child.parent_contract, self.master)
self.assertIn(self.child, self.master.child_contracts.all())
def test_framework_cannot_have_parent(self):
contract = InternetContract(
provider=self.provider,
location=self.location,
contract_number='X',
service_type=self.service,
status=self.status,
start_date=date(2024, 1, 1),
is_framework=True,
parent_contract=self.master,
)
from django.core.exceptions import ValidationError
with self.assertRaises(ValidationError):
contract.full_clean()
def test_billing_tree_nests_child_under_framework(self):
rows = _build_billing_rows(
[self.master, self.child],
payments_by_contract={},
)
contract_rows = [r for r in rows if not r.get('is_provider_header')]
self.assertEqual(len(contract_rows), 2)
self.assertEqual(contract_rows[0]['contract'], self.master)
self.assertEqual(contract_rows[0]['indent'], 0)
self.assertTrue(contract_rows[0]['has_children'])
self.assertEqual(contract_rows[1]['contract'], self.child)
self.assertEqual(contract_rows[1]['indent'], 1)
def test_billing_tree_infers_parent_by_contract_number_prefix(self):
orphan = InternetContract.objects.create(
provider=self.provider,
location=self.location,
contract_number='70805211',
service_type=self.service,
status=self.status,
start_date=date(2024, 1, 1),
monthly_cost=Decimal('400.00'),
)
rows = _build_billing_rows(
[self.master, orphan],
payments_by_contract={},
)
contract_rows = [r for r in rows if not r.get('is_provider_header')]
self.assertEqual(len(contract_rows), 2)
self.assertEqual(contract_rows[1]['contract'], orphan)
self.assertEqual(contract_rows[1]['indent'], 1)
self.assertTrue(contract_rows[1]['is_inferred_child'])
class InternetContractAdminFormTests(TestCase):
def setUp(self):
self.status = _ensure_contract_status()
self.service = _ensure_service_type()
self.provider = InternetProvider.objects.create(name='WESTELECOM')
def test_framework_contract_form_without_location(self):
form = InternetContractForm(data={
'provider': self.provider.pk,
'location': '',
'contract_number': '708052',
'service_type': self.service.pk,
'status': self.status.pk,
'start_date': '2024-01-01',
'is_framework': True,
})
self.assertTrue(form.is_valid(), form.errors)
def test_framework_contract_form_requires_start_date(self):
form = InternetContractForm(data={
'provider': self.provider.pk,
'location': '',
'contract_number': '708052',
'service_type': self.service.pk,
'status': self.status.pk,
'is_framework': True,
})
self.assertFalse(form.is_valid())
self.assertIn('start_date', form.errors)
class InternetBillingPortalTests(TestCase):
def setUp(self):
self.status = _ensure_contract_status()
self.service = _ensure_service_type()
self.provider = InternetProvider.objects.create(name='Лекол')
self.location = _make_location(location_type='pharmacy', address='Pharmacy addr')
self.contract = InternetContract.objects.create(
provider=self.provider,
location=self.location,
contract_number='70805205',
service_type=self.service,
status=self.status,
start_date=date(2024, 1, 1),
monthly_cost=Decimal('500.00'),
)
self.user = grant_all_locations(make_employee())
self.user.groups.add(Group.objects.get(name='Офисный сотрудник'))
for attr in ('_perm_cache', '_user_perm_cache', '_group_perm_cache'):
if hasattr(self.user, attr):
delattr(self.user, attr)
def test_office_user_can_access_internet_billing_tab(self):
self.assertTrue(user_can_access(self.user, 'internet_billing'))
def test_accounting_internet_tab_renders(self):
login_2fa(self.client, self.user)
response = self.client.get('/accounting/?tab=internet', HTTP_HX_REQUEST='true')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.context['accounting_active_tab'], 'internet')
contract_rows = [
r for r in response.context['billing_rows']
if not r.get('is_provider_header')
]
self.assertEqual(len(contract_rows), 1)
def test_mark_payment_paid(self):
login_2fa(self.client, self.user)
response = self.client.post(
'/accounting/internet-payment/',
{
'month': '2026-09',
'contract_id': self.contract.pk,
'action': 'mark_paid',
},
HTTP_HX_REQUEST='true',
)
self.assertEqual(response.status_code, 200)
payment = InternetContractPayment.objects.get(contract=self.contract, period=date(2026, 9, 1))
self.assertTrue(payment.is_paid)
self.assertEqual(payment.amount, Decimal('500.00'))