- Создан модуль customers/services/import_export.py согласно best practices - Класс CustomerExporter: содержит логику экспорта в CSV (ранее была в views) - Класс CustomerImporter: заглушка для будущей реализации импорта - Views стали тонкими: customer_export и customer_import делегируют работу сервисам - Улучшена организация кода: соблюдён принцип Single Responsibility - Уменьшен размер views.py на 30 строк - Добавлена подробная документация в docstrings классов и методов - Логику теперь легко тестировать и переиспользовать (например, в Celery tasks) Преимущества: - Чистое разделение ответственности - Упрощённое тестирование - Возможность переиспользования в асинхронных задачах - Соответствие Django best practices
107 lines
3.8 KiB
Python
107 lines
3.8 KiB
Python
"""
|
||
Сервис для импорта и экспорта клиентов.
|
||
|
||
Этот модуль содержит логику импорта/экспорта клиентов в различных форматах (CSV, Excel).
|
||
Разделение на отдельный модуль улучшает организацию кода и следует принципам SRP.
|
||
"""
|
||
import csv
|
||
from django.http import HttpResponse
|
||
from django.utils import timezone
|
||
from ..models import Customer
|
||
|
||
|
||
class CustomerExporter:
|
||
"""
|
||
Класс для экспорта клиентов в различные форматы.
|
||
"""
|
||
|
||
@staticmethod
|
||
def export_to_csv():
|
||
"""
|
||
Экспортирует всех клиентов (кроме системного) в CSV файл.
|
||
|
||
Поля экспорта:
|
||
- ID
|
||
- Имя
|
||
- Email
|
||
- Телефон
|
||
- Дата создания
|
||
|
||
Примечание: Баланс кошелька НЕ экспортируется (требование безопасности).
|
||
|
||
Returns:
|
||
HttpResponse: HTTP ответ с CSV файлом для скачивания
|
||
"""
|
||
# Создаём HTTP ответ с CSV файлом
|
||
response = HttpResponse(content_type='text/csv; charset=utf-8')
|
||
timestamp = timezone.now().strftime("%Y%m%d_%H%M%S")
|
||
response['Content-Disposition'] = f'attachment; filename="customers_export_{timestamp}.csv"'
|
||
|
||
# Добавляем BOM для корректного открытия в Excel
|
||
response.write('\ufeff')
|
||
|
||
writer = csv.writer(response)
|
||
|
||
# Заголовки
|
||
writer.writerow([
|
||
'ID',
|
||
'Имя',
|
||
'Email',
|
||
'Телефон',
|
||
'Дата создания',
|
||
])
|
||
|
||
# Данные (исключаем системного клиента)
|
||
customers = Customer.objects.filter(is_system_customer=False).order_by('-created_at')
|
||
|
||
for customer in customers:
|
||
writer.writerow([
|
||
customer.id,
|
||
customer.name or '',
|
||
customer.email or '',
|
||
str(customer.phone) if customer.phone else '',
|
||
customer.created_at.strftime('%Y-%m-%d %H:%M:%S'),
|
||
])
|
||
|
||
return response
|
||
|
||
|
||
class CustomerImporter:
|
||
"""
|
||
Класс для импорта клиентов из различных форматов.
|
||
|
||
TODO: Реализовать:
|
||
- Парсинг CSV файлов
|
||
- Парсинг Excel файлов (.xlsx, .xls)
|
||
- Валидация данных (email, телефон)
|
||
- Обработка дубликатов
|
||
- Пакетное создание клиентов
|
||
- Отчёт об ошибках
|
||
"""
|
||
|
||
def __init__(self):
|
||
self.errors = []
|
||
self.success_count = 0
|
||
self.skip_count = 0
|
||
|
||
def import_from_file(self, file, update_existing=False):
|
||
"""
|
||
Импорт клиентов из загруженного файла.
|
||
|
||
Args:
|
||
file: Загруженный файл (UploadedFile)
|
||
update_existing: Обновлять ли существующих клиентов (по email/телефону)
|
||
|
||
Returns:
|
||
dict: Результат импорта с статистикой
|
||
"""
|
||
# TODO: Реализовать логику импорта
|
||
return {
|
||
'success': False,
|
||
'message': 'Функция импорта находится в разработке',
|
||
'created': 0,
|
||
'updated': 0,
|
||
'skipped': 0,
|
||
'errors': []
|
||
}
|