Добавлены кнопки Импорт и Экспорт на страницу списка клиентов

- Добавлены кнопки Импорт и Экспорт в header страницы customers/
- Создан URL-маршрут для customer-import и customer-export
- Реализована функция customer_export: экспорт всех клиентов в CSV файл с BOM для Excel
- Экспортируются поля: ID, Имя, Фамилия, Email, Телефон, Баланс кошелька, Дата создания
- Создан шаблон customer_import.html с инструкцией и формой загрузки файла
- Функция customer_import пока заглушка (TODO: реализовать парсинг CSV/Excel)
- Кнопки оформлены в btn-group с иконками Bootstrap Icons
- Системный клиент исключён из экспорта
This commit is contained in:
2025-12-14 20:41:21 +03:00
parent 34e5a0143b
commit 778c979aa3
4 changed files with 154 additions and 1 deletions

View File

@@ -0,0 +1,75 @@
{% extends "base.html" %}
{% block title %}Импорт клиентов{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-md-8 offset-md-2">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1>Импорт клиентов</h1>
<a href="{% url 'customers:customer-list' %}" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Назад к списку
</a>
</div>
<!-- Инструкция -->
<div class="alert alert-info mb-4">
<h5 class="alert-heading"><i class="bi bi-info-circle"></i> Инструкция</h5>
<p class="mb-2">Загрузите CSV или Excel файл со следующими столбцами:</p>
<ul class="mb-2">
<li><strong>Имя</strong> (обязательно)</li>
<li><strong>Фамилия</strong> (опционально)</li>
<li><strong>Email</strong> (опционально)</li>
<li><strong>Телефон</strong> (опционально, формат: +375XXXXXXXXX)</li>
<li><strong>Баланс кошелька</strong> (опционально, по умолчанию 0)</li>
</ul>
<p class="mb-0">
<a href="{% url 'customers:customer-export' %}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-download"></i> Скачать образец (текущие клиенты)
</a>
</p>
</div>
<!-- Форма загрузки -->
<div class="card">
<div class="card-body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="mb-3">
<label for="file" class="form-label">Выберите файл</label>
<input type="file" class="form-control" id="file" name="file"
accept=".csv,.xlsx,.xls" required>
<small class="form-text text-muted">
Поддерживаемые форматы: CSV, Excel (.xlsx, .xls)
</small>
</div>
<div class="form-check mb-3">
<input type="checkbox" class="form-check-input" id="update_existing" name="update_existing">
<label class="form-check-label" for="update_existing">
Обновлять существующих клиентов (по email или телефону)
</label>
</div>
<div class="alert alert-warning">
<i class="bi bi-exclamation-triangle"></i>
<strong>Внимание!</strong> Функция импорта находится в разработке.
</div>
<button type="submit" class="btn btn-primary" disabled>
<i class="bi bi-upload"></i> Импортировать
</button>
<a href="{% url 'customers:customer-list' %}" class="btn btn-outline-secondary">
Отмена
</a>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -9,7 +9,17 @@
<div class="d-flex justify-content-between align-items-center mb-3"> <div class="d-flex justify-content-between align-items-center mb-3">
<h1>Клиенты</h1> <h1>Клиенты</h1>
<a href="{% url 'customers:customer-create' %}" class="btn btn-primary">Добавить клиента</a> <div class="btn-group" role="group">
<a href="{% url 'customers:customer-import' %}" class="btn btn-outline-success">
<i class="bi bi-upload"></i> Импорт
</a>
<a href="{% url 'customers:customer-export' %}" class="btn btn-outline-info">
<i class="bi bi-download"></i> Экспорт
</a>
<a href="{% url 'customers:customer-create' %}" class="btn btn-primary">
<i class="bi bi-plus-circle"></i> Добавить клиента
</a>
</div>
</div> </div>
<!-- Search Form --> <!-- Search Form -->

View File

@@ -6,6 +6,8 @@ app_name = 'customers'
urlpatterns = [ urlpatterns = [
path('', views.customer_list, name='customer-list'), path('', views.customer_list, name='customer-list'),
path('create/', views.customer_create, name='customer-create'), path('create/', views.customer_create, name='customer-create'),
path('import/', views.customer_import, name='customer-import'),
path('export/', views.customer_export, name='customer-export'),
path('<int:pk>/', views.customer_detail, name='customer-detail'), path('<int:pk>/', views.customer_detail, name='customer-detail'),
path('<int:pk>/edit/', views.customer_update, name='customer-update'), path('<int:pk>/edit/', views.customer_update, name='customer-update'),
path('<int:pk>/delete/', views.customer_delete, name='customer-delete'), path('<int:pk>/delete/', views.customer_delete, name='customer-delete'),

View File

@@ -591,3 +591,69 @@ def wallet_withdraw(request, pk):
messages.error(request, '; '.join(e.messages) if hasattr(e, 'messages') else str(e)) messages.error(request, '; '.join(e.messages) if hasattr(e, 'messages') else str(e))
return redirect('customers:customer-detail', pk=pk) return redirect('customers:customer-detail', pk=pk)
@login_required
@manager_or_owner_required
def customer_import(request):
"""
Импорт клиентов из CSV/Excel файла.
TODO: Реализовать логику импорта
"""
if request.method == 'POST':
# TODO: Обработка загруженного файла
messages.info(request, 'Функция импорта в разработке')
return redirect('customers:customer-list')
context = {
'title': 'Импорт клиентов',
}
return render(request, 'customers/customer_import.html', context)
@login_required
@manager_or_owner_required
def customer_export(request):
"""
Экспорт клиентов в CSV/Excel файл.
TODO: Реализовать логику экспорта
"""
import csv
from django.http import HttpResponse
from django.utils import timezone
# Создаём HTTP ответ с CSV файлом
response = HttpResponse(content_type='text/csv; charset=utf-8')
response['Content-Disposition'] = f'attachment; filename="customers_export_{timezone.now().strftime("%Y%m%d_%H%M%S")}.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.first_name or '',
customer.last_name or '',
customer.email or '',
str(customer.phone) if customer.phone else '',
str(customer.wallet_balance),
customer.created_at.strftime('%Y-%m-%d %H:%M:%S'),
])
return response