217 lines
10 KiB
Python
217 lines
10 KiB
Python
"""
|
|
تستهای قرارداد مشتری: افزودن، ویرایش و نگهبان حذف (عدم حذف مشتری دارای سابقه).
|
|
"""
|
|
from django.test import TestCase
|
|
from django.urls import reverse
|
|
|
|
from admin_panel.models import Article, Customer, Factor, PhoneNumber
|
|
|
|
from .factories import login_superuser, make_customer, make_user
|
|
|
|
|
|
class CustomerCrudTests(TestCase):
|
|
|
|
def setUp(self):
|
|
self.user = login_superuser(self.client, 'csUser')
|
|
|
|
def test_add_customer_creates_phones(self):
|
|
url = reverse('admin_panel:customersAdd')
|
|
response = self.client.post(url, {
|
|
'an_name': 'علی رضایی',
|
|
'an_address': 'تهران',
|
|
'installDate': '1400/01/01',
|
|
'idnCode': '1234567890',
|
|
'phone_titles': ['موبایل', 'ثابت', ''],
|
|
'phones': ['09120000000', '02112345678', ''],
|
|
})
|
|
|
|
self.assertIn(response.status_code, (200, 302))
|
|
customer = Customer.objects.get(name_family='علی رضایی')
|
|
self.assertEqual(customer.phone1, '09120000000')
|
|
self.assertEqual(customer.phone2, '02112345678')
|
|
# ردیف خالی نباید ذخیره شود
|
|
self.assertEqual(PhoneNumber.objects.filter(customer=customer).count(), 2)
|
|
|
|
def test_edit_customer_replaces_phones(self):
|
|
customer = make_customer('مشتری ویرایش', phones=['09120000001'])
|
|
url = reverse('admin_panel:customerEdit', kwargs={'c_id': customer.id})
|
|
|
|
response = self.client.post(url, {
|
|
'an_name': 'مشتری ویرایش شده',
|
|
'an_address': 'شیراز',
|
|
'installDate': '1401/02/03',
|
|
'idnCode': '999',
|
|
'laghv_bazdid': 'true',
|
|
'phone_titles': ['موبایل جدید'],
|
|
'phones': ['09120009999'],
|
|
})
|
|
self.assertIn(response.status_code, (200, 302))
|
|
|
|
customer.refresh_from_db()
|
|
self.assertEqual(customer.name_family, 'مشتری ویرایش شده')
|
|
self.assertTrue(customer.laghv_bazdid)
|
|
phones = list(PhoneNumber.objects.filter(customer=customer))
|
|
self.assertEqual(len(phones), 1)
|
|
self.assertEqual(phones[0].phone_number, '09120009999')
|
|
|
|
|
|
class CustomerInfoCardUITests(TestCase):
|
|
"""کارت پروفایل مشتری (ستون راست): ساختار حرفهای، ویرایش و تعیین شمارهٔ اصلی.
|
|
|
|
این تستها قرارداد ویوها/قالبها را قفل میکنند تا بازطراحی UI به ویرایش مشتری
|
|
یا تعیین «شمارهٔ اصلی پیامک» آسیب نزند.
|
|
"""
|
|
|
|
def setUp(self):
|
|
self.user = login_superuser(self.client, 'cardUser')
|
|
|
|
def _customer_page(self, customer):
|
|
return self.client.get(
|
|
reverse('admin_panel:customer', kwargs={'c_id': customer.id}),
|
|
).content.decode('utf-8')
|
|
|
|
def test_profile_card_structure_is_rendered(self):
|
|
customer = make_customer('مشتری کارت', phones=['09120000000'])
|
|
html = self._customer_page(customer)
|
|
for needle in ('has-background-white brad5', 'id="formcsEdit"',
|
|
'dynamic-phones-edit', 'شمارههای تماس', 'لغو بازدید'):
|
|
self.assertIn(needle, html, msg=needle)
|
|
|
|
def test_template_comments_never_leak_into_the_page(self):
|
|
"""رگرسیون: کامنت چندخطی {# #} جنگو معتبر نیست و بهصورت متن چاپ میشود.
|
|
|
|
قالب کارت پروفایل باید از ``{% comment %}`` استفاده کند؛ این تست تضمین میکند
|
|
هیچ متن کامنتی در HTML نهایی دیده نشود.
|
|
"""
|
|
customer = make_customer('مشتری کامنت', phones=['09120000000'])
|
|
html = self._customer_page(customer)
|
|
for leaked in ('تکمنبع', 'DRY', 'شناسههای موردنیاز', 'کارت پروفایل مشتری —'):
|
|
self.assertNotIn(leaked, html, msg=f'متن کامنت در صفحه لو رفته: {leaked}')
|
|
|
|
def test_edit_controls_present_and_single_form(self):
|
|
customer = make_customer('مشتری ویرایشکارت', phones=['09120000000'])
|
|
html = self._customer_page(customer)
|
|
for needle in ('id="formcsEdit"', 'id="enEdit"', 'id="editCs"',
|
|
'id="cancelEdit"', 'id="showUserDT"'):
|
|
self.assertIn(needle, html, msg=needle)
|
|
# نباید فرم تودرتو ساخته شود؛ فقط یک فرم ویرایش در ستون وجود دارد.
|
|
self.assertEqual(html.count('id="formcsEdit"'), 1)
|
|
|
|
def test_primary_toggle_present_next_to_phone(self):
|
|
customer = make_customer('مشتری اصلیکارت')
|
|
PhoneNumber.objects.create(customer=customer, phone_number='09120000000')
|
|
html = self._customer_page(customer)
|
|
self.assertIn('sms-primary-toggle', html)
|
|
self.assertIn('data-phone="09120000000"', html)
|
|
self.assertIn(
|
|
'data-url="%s"' % reverse('admin_panel:sms_primary_toggle',
|
|
kwargs={'c_id': customer.id}),
|
|
html,
|
|
)
|
|
|
|
def test_card_also_renders_on_legacy_base_page(self):
|
|
"""صفحهٔ جزئیات فاکتور (customerFactor) از customerBase.html استفاده میکند."""
|
|
factor = Factor.objects.create(customer=make_customer('مشتری فاکتورکارت'),
|
|
amount=1000, pay_status='unpaid')
|
|
html = self.client.get(
|
|
reverse('admin_panel:customerFactor',
|
|
kwargs={'c_id': factor.customer_id, 'f_id': factor.id}),
|
|
).content.decode('utf-8')
|
|
self.assertIn('has-background-white brad5', html)
|
|
self.assertIn('id="formcsEdit"', html)
|
|
|
|
def test_edit_persists_phones_and_primary_selection(self):
|
|
"""ویرایش مشتری با markup جدید باید شمارهها و انتخاب «اصلی» را ذخیره کند."""
|
|
customer = make_customer('مشتری ویرایشنهایی', phones=['09120000001'])
|
|
url = reverse('admin_panel:customerEdit', kwargs={'c_id': customer.id})
|
|
response = self.client.post(url, {
|
|
'an_name': 'مشتری ویرایشنهایی', 'an_address': 'قم',
|
|
'installDate': '1401/02/03', 'idnCode': '555',
|
|
'laghv_bazdid': 'true', 'notes': 'یادداشت',
|
|
'phone_titles': ['موبایل'], 'phones': ['09120009999'],
|
|
'phone_primary': ['0'],
|
|
})
|
|
self.assertIn(response.status_code, (200, 302))
|
|
customer.refresh_from_db()
|
|
self.assertEqual(customer.name_family, 'مشتری ویرایشنهایی')
|
|
self.assertTrue(customer.laghv_bazdid)
|
|
self.assertEqual(customer.notes, 'یادداشت')
|
|
phones = list(PhoneNumber.objects.filter(customer=customer))
|
|
self.assertEqual(len(phones), 1)
|
|
self.assertEqual(phones[0].phone_number, '09120009999')
|
|
# شمارهٔ تیکخورده بهعنوان «اصلی» ذخیره شده است.
|
|
self.assertEqual(customer.sms_primary_phones, '+989120009999')
|
|
|
|
|
|
class InactiveCustomerHiddenTests(TestCase):
|
|
"""مشتری غیرفعال (is_active=False) در فهرست و در جستجو دیده نمیشود."""
|
|
|
|
def setUp(self):
|
|
self.user = login_superuser(self.client, 'hideUser')
|
|
self.active = make_customer('خطیبی فعال', phones=['09120000041'])
|
|
self.inactive = make_customer('خطیبی غیرفعال', is_active=False,
|
|
phones=['09120000042'])
|
|
# جستجوی تلفن از ستون phone1 میخواند (فیلد قدیمی مشتری).
|
|
Customer.objects.filter(pk=self.active.pk).update(phone1='09120000041')
|
|
Customer.objects.filter(pk=self.inactive.pk).update(phone1='09120000042')
|
|
|
|
def test_inactive_absent_from_default_listing(self):
|
|
html = self.client.get(reverse('admin_panel:customers')).content.decode('utf-8')
|
|
self.assertIn('خطیبی فعال', html)
|
|
self.assertNotIn('خطیبی غیرفعال', html)
|
|
|
|
def test_inactive_absent_from_search_by_name(self):
|
|
html = self.client.get(
|
|
reverse('admin_panel:customers'),
|
|
{'searchVal': 'خطیبی', 'searchOn': 'name'},
|
|
).content.decode('utf-8')
|
|
self.assertIn('خطیبی فعال', html)
|
|
self.assertNotIn('خطیبی غیرفعال', html)
|
|
|
|
def test_inactive_absent_from_search_by_phone(self):
|
|
html = self.client.get(
|
|
reverse('admin_panel:customers'),
|
|
{'searchVal': '0912000004', 'searchOn': 'phone'},
|
|
).content.decode('utf-8')
|
|
self.assertIn('09120000041', html)
|
|
self.assertNotIn('09120000042', html)
|
|
|
|
def test_inactive_absent_from_path_search_view(self):
|
|
# مسیر <slug:> فقط نویسههای لاتین میپذیرد.
|
|
make_customer('khatibi-active')
|
|
make_customer('khatibi-inactive', is_active=False)
|
|
html = self.client.get(
|
|
reverse('admin_panel:customersSearch',
|
|
kwargs={'searchVal': 'khatibi', 'searchOn': 'name'}),
|
|
).content.decode('utf-8')
|
|
self.assertIn('khatibi-active', html)
|
|
self.assertNotIn('khatibi-inactive', html)
|
|
|
|
|
|
class CustomerDeleteGuardTests(TestCase):
|
|
|
|
def setUp(self):
|
|
self.user = make_user('delUser', superuser=True)
|
|
self.client.force_login(self.user)
|
|
|
|
def test_customer_without_history_is_deactivated(self):
|
|
customer = make_customer('مشتری خام')
|
|
url = reverse('admin_panel:customerDel', kwargs={'c_id': customer.id})
|
|
|
|
self.client.get(url)
|
|
|
|
customer.refresh_from_db()
|
|
# حذف نرم: رکورد باقی میماند ولی غیرفعال میشود
|
|
self.assertFalse(customer.is_active)
|
|
|
|
def test_customer_with_financial_history_is_never_deleted(self):
|
|
customer = make_customer('مشتری دارای سابقه')
|
|
Article.objects.create(customer=customer, debit=1000, credit=0, desc='سابقه مالی')
|
|
|
|
url = reverse('admin_panel:customerDel', kwargs={'c_id': customer.id})
|
|
self.client.get(url)
|
|
|
|
customer.refresh_from_db()
|
|
self.assertTrue(customer.is_active, msg="مشتری دارای سابقه مالی نباید حذف/غیرفعال شود.")
|
|
self.assertTrue(Customer.objects.filter(id=customer.id).exists())
|