3cbc019268
Фундамент интеграции Carbonio на уровне модели Pharmacy (без обращений к серверу): - Поля Pharmacy: carbonio_email, carbonio_account_id, carbonio_sync_enabled (default False), carbonio_sync_status, carbonio_last_sync, carbonio_sync_error - Генерация адреса <mail_prefix организации><номер>@домен (a1@, t1@, p1@...); префикс из Directory.extra_data['mail_prefix'], домен из ConnectorConfig(carbonio) с дефолтом aks-apteka.com.ua - Ручной override адреса не перетирается автогенерацией - Уникальность carbonio_email: clean() + частичный unique-констрейнт в БД (пустые не конфликтуют); автоген при коллизии оставляет поле пустым - 10 тестов (apps.locations.tests) — у приложения было 0 API-слой (клиент/sync/сигналы/задачи) — следующим шагом. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
76 lines
3.7 KiB
Python
76 lines
3.7 KiB
Python
from django.core.exceptions import ValidationError
|
|
from django.db import IntegrityError, transaction
|
|
from django.test import TestCase
|
|
|
|
from core.models import Directory, DirectoryType
|
|
from apps.locations.models import Pharmacy
|
|
|
|
|
|
class CarbonioEmailTests(TestCase):
|
|
"""Генерация адреса Carbonio (<префикс организации><номер>@домен),
|
|
ручной override и проверка уникальности."""
|
|
|
|
@classmethod
|
|
def setUpTestData(cls):
|
|
org_type = DirectoryType.objects.create(code='organization', name='Организация')
|
|
region_type = DirectoryType.objects.create(code='region', name='Регион')
|
|
cls.region = Directory.objects.create(directory_type=region_type, code='od', name='Одесса')
|
|
cls.aks = Directory.objects.create(
|
|
directory_type=org_type, code='akc', name='АКС', extra_data={'mail_prefix': 'a'})
|
|
cls.tira = Directory.objects.create(
|
|
directory_type=org_type, code='tira', name='Тира', extra_data={'mail_prefix': 't'})
|
|
cls.noprefix = Directory.objects.create(
|
|
directory_type=org_type, code='xx', name='Без префикса', extra_data={})
|
|
|
|
def _pharmacy(self, org, number, **kw):
|
|
return Pharmacy.objects.create(
|
|
organization=org, location_region=self.region,
|
|
pharmacy_number=number, location_type='pharmacy', **kw)
|
|
|
|
def test_build_email_format(self):
|
|
self.assertEqual(self._pharmacy(self.aks, 5).build_carbonio_email(), 'a5@aks-apteka.com.ua')
|
|
|
|
def test_build_email_uses_org_prefix(self):
|
|
self.assertEqual(self._pharmacy(self.tira, 5).build_carbonio_email(), 't5@aks-apteka.com.ua')
|
|
|
|
def test_build_email_empty_without_prefix(self):
|
|
self.assertEqual(self._pharmacy(self.noprefix, 5).build_carbonio_email(), '')
|
|
|
|
def test_autogenerate_on_save_when_enabled(self):
|
|
p = self._pharmacy(self.aks, 7, carbonio_sync_enabled=True)
|
|
self.assertEqual(p.carbonio_email, 'a7@aks-apteka.com.ua')
|
|
|
|
def test_no_autogenerate_when_disabled(self):
|
|
self.assertEqual(self._pharmacy(self.aks, 8).carbonio_email, '')
|
|
|
|
def test_manual_override_respected(self):
|
|
p = self._pharmacy(self.aks, 9, carbonio_sync_enabled=True,
|
|
carbonio_email='custom@aks-apteka.com.ua')
|
|
self.assertEqual(p.carbonio_email, 'custom@aks-apteka.com.ua')
|
|
|
|
def test_uniqueness_rejected_in_clean(self):
|
|
self._pharmacy(self.aks, 10, carbonio_sync_enabled=True) # a10@
|
|
p2 = self._pharmacy(self.tira, 11)
|
|
p2.carbonio_email = 'a10@aks-apteka.com.ua'
|
|
with self.assertRaises(ValidationError):
|
|
p2.clean()
|
|
|
|
def test_uniqueness_enforced_by_db(self):
|
|
self._pharmacy(self.aks, 12, carbonio_sync_enabled=True) # a12@
|
|
with self.assertRaises(IntegrityError):
|
|
with transaction.atomic():
|
|
self._pharmacy(self.tira, 13, carbonio_email='a12@aks-apteka.com.ua')
|
|
|
|
def test_autogenerate_skips_on_collision(self):
|
|
# ручной a15@ занят другой аптекой -> автоген для АКС №15 оставляет пусто
|
|
self._pharmacy(self.tira, 99, carbonio_sync_enabled=True,
|
|
carbonio_email='a15@aks-apteka.com.ua')
|
|
p = self._pharmacy(self.aks, 15, carbonio_sync_enabled=True)
|
|
self.assertEqual(p.carbonio_email, '')
|
|
|
|
def test_blank_emails_do_not_clash(self):
|
|
# несколько аптек без адреса — частичный уникальный индекс их не блокирует
|
|
self._pharmacy(self.aks, 16)
|
|
self._pharmacy(self.tira, 17)
|
|
self.assertEqual(Pharmacy.objects.filter(carbonio_email='').count(), 2)
|