Добавлена функциональность системного клиента для анонимных покупок

- Добавлено поле is_system_customer в модель Customer с индексом
- Системный клиент создается автоматически при создании нового тенанта
- Реализована защита системного клиента от редактирования и удаления:
  - Защита на уровне модели (save/delete методы)
  - Защита на уровне формы (валидация)
  - Защита на уровне представлений (проверки с дружественными сообщениями)
  - Защита в админке (readonly поля, запрет удаления)
- Системный клиент скрыт из списков и поиска на фронтенде
- Создан информационный шаблон для отображения системного клиента
- Исправлена обработка NULL значений для полей email/phone (Django best practice)
- Добавлено отображение "Не указано" вместо None в карточке клиента

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-20 00:07:38 +03:00
parent 755e4fc9d9
commit 685c06d94d
8 changed files with 215 additions and 65 deletions

View File

@@ -15,6 +15,7 @@ class CustomerForm(forms.ModelForm):
class Meta:
model = Customer
fields = ['name', 'email', 'phone', 'loyalty_tier', 'notes']
exclude = ['is_system_customer']
widgets = {
'notes': forms.Textarea(attrs={'rows': 3}),
}
@@ -43,9 +44,9 @@ class CustomerForm(forms.ModelForm):
"""Проверяет уникальность email при создании/редактировании"""
email = self.cleaned_data.get('email')
# Если email пустой, это нормально (blank=True)
# Нормализуем пустые значения в None (Django best practice для nullable полей)
if not email:
return email
return None
# Проверяем уникальность
queryset = Customer.objects.filter(email=email)
@@ -63,9 +64,9 @@ class CustomerForm(forms.ModelForm):
"""Проверяет уникальность телефона при создании/редактировании"""
phone = self.cleaned_data.get('phone')
# Если телефон пустой, это нормально (blank=True)
# Нормализуем пустые значения в None (Django best practice для nullable полей)
if not phone:
return phone
return None
# Проверяем уникальность
queryset = Customer.objects.filter(phone=phone)
@@ -77,4 +78,17 @@ class CustomerForm(forms.ModelForm):
if queryset.exists():
raise ValidationError('Клиент с таким номером телефона уже существует.')
return phone
return phone
def clean(self):
"""Дополнительная валидация формы"""
cleaned_data = super().clean()
# Защита от редактирования системного клиента
if self.instance and self.instance.pk and self.instance.is_system_customer:
raise ValidationError(
'Системный клиент не может быть изменен. '
'Он необходим для корректной работы системы и создается автоматически.'
)
return cleaned_data