feat: Add customer prefill from URL parameter in order creation
- Modified order_create view to read customer from GET parameter - Pass preselected_customer to template context - Template renders select with preselected option for Select2 - Fixed draft creation timing with callback after Select2 initialization - Auto-create draft when customer is preselected from URL - Graceful handling if customer not found or invalid ID
This commit is contained in:
@@ -46,9 +46,11 @@
|
||||
<th>Баланс кошелька:</th>
|
||||
<td>
|
||||
{% if customer.wallet_balance > 0 %}
|
||||
<span class="text-success fw-bold">{{ customer.wallet_balance|floatformat:2 }} руб.</span>
|
||||
<span class="badge bg-success" style="font-size: 1.1em;">{{ customer.wallet_balance|floatformat:2 }} руб.</span>
|
||||
{% elif customer.wallet_balance == 0 %}
|
||||
<span class="badge bg-secondary">{{ customer.wallet_balance|floatformat:2 }} руб.</span>
|
||||
{% else %}
|
||||
{{ customer.wallet_balance|floatformat:2 }} руб.
|
||||
<span class="badge bg-danger">{{ customer.wallet_balance|floatformat:2 }} руб.</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -79,6 +81,211 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- История транзакций кошелька -->
|
||||
<div class="col-md-12">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5>История кошелька (последние 20)</h5>
|
||||
<span class="badge bg-primary">{{ wallet_transactions|length }}</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if wallet_transactions %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Дата</th>
|
||||
<th>Тип</th>
|
||||
<th>Сумма</th>
|
||||
<th>Описание</th>
|
||||
<th>Заказ</th>
|
||||
<th>Создал</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for transaction in wallet_transactions %}
|
||||
<tr>
|
||||
<td><small>{{ transaction.created_at|date:"d.m.Y H:i" }}</small></td>
|
||||
<td>
|
||||
{% if transaction.transaction_type == 'deposit' %}
|
||||
<span class="badge bg-success">Пополнение</span>
|
||||
{% elif transaction.transaction_type == 'spend' %}
|
||||
<span class="badge bg-danger">Списание</span>
|
||||
{% else %}
|
||||
<span class="badge bg-warning">Корректировка</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if transaction.transaction_type == 'deposit' or transaction.transaction_type == 'adjustment' and transaction.amount > 0 %}
|
||||
<span class="text-success fw-bold">+{{ transaction.amount|floatformat:2 }} руб.</span>
|
||||
{% else %}
|
||||
<span class="text-danger fw-bold">-{{ transaction.amount|floatformat:2 }} руб.</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ transaction.description|default:"-" }}</td>
|
||||
<td>
|
||||
{% if transaction.order %}
|
||||
<a href="{% url 'orders:order-detail' transaction.order.pk %}" class="btn btn-sm btn-outline-primary">
|
||||
#{{ transaction.order.order_number }}
|
||||
</a>
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><small>{{ transaction.created_by.username|default:"-" }}</small></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-muted mb-0">История транзакций пуста.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- История заказов -->
|
||||
<div class="col-md-12">
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5>История заказов</h5>
|
||||
<div>
|
||||
<span class="badge bg-primary">{{ orders_page.paginator.count }}</span>
|
||||
<a href="{% url 'orders:order-create' %}?customer={{ customer.pk }}" class="btn btn-sm btn-success ms-2">
|
||||
<i class="bi bi-plus-circle"></i> Новый заказ
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if orders_page %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>№</th>
|
||||
<th>Дата создания</th>
|
||||
<th>Дата доставки</th>
|
||||
<th>Статус</th>
|
||||
<th>Оплата</th>
|
||||
<th>Сумма</th>
|
||||
<th>Оплачено</th>
|
||||
<th>Остаток</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for order in orders_page %}
|
||||
<tr>
|
||||
<td><strong>#{{ order.order_number }}</strong></td>
|
||||
<td><small>{{ order.created_at|date:"d.m.Y H:i" }}</small></td>
|
||||
<td>
|
||||
{% if order.delivery_date %}
|
||||
<strong>{{ order.delivery_date|date:"d.m.Y" }}</strong>
|
||||
{% if order.delivery_time %}
|
||||
<br><small class="text-muted">{{ order.delivery_time }}</small>
|
||||
{% endif %}
|
||||
{% if order.is_delivery %}
|
||||
<br><span class="badge bg-info">Доставка</span>
|
||||
{% else %}
|
||||
<br><span class="badge bg-secondary">Самовывоз</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="text-muted">Не указана</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if order.status == 'draft' %}
|
||||
<span class="badge bg-secondary">Черновик</span>
|
||||
{% elif order.status == 'pending' %}
|
||||
<span class="badge bg-warning">Ожидает</span>
|
||||
{% elif order.status == 'in_production' %}
|
||||
<span class="badge bg-info">В производстве</span>
|
||||
{% elif order.status == 'ready' %}
|
||||
<span class="badge bg-primary">Готов</span>
|
||||
{% elif order.status == 'delivered' %}
|
||||
<span class="badge bg-success">Доставлен</span>
|
||||
{% elif order.status == 'cancelled' %}
|
||||
<span class="badge bg-danger">Отменён</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">{{ order.get_status_display }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if order.payment_status == 'paid' %}
|
||||
<span class="badge bg-success">Оплачено</span>
|
||||
{% elif order.payment_status == 'partial' %}
|
||||
<span class="badge bg-warning">Частично</span>
|
||||
{% else %}
|
||||
<span class="badge bg-danger">Не оплачено</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><strong>{{ order.total_amount|floatformat:2 }} руб.</strong></td>
|
||||
<td>
|
||||
{% if order.amount_paid > 0 %}
|
||||
<span class="text-success">{{ order.amount_paid|floatformat:2 }} руб.</span>
|
||||
{% else %}
|
||||
<span class="text-muted">0.00 руб.</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if order.amount_due > 0 %}
|
||||
<span class="text-danger fw-bold">{{ order.amount_due|floatformat:2 }} руб.</span>
|
||||
{% else %}
|
||||
<span class="text-success">0.00 руб.</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url 'orders:order-detail' order.pk %}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-eye"></i>
|
||||
</a>
|
||||
<a href="{% url 'orders:order-update' order.pk %}" class="btn btn-sm btn-outline-secondary">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Пагинация -->
|
||||
{% if orders_page.has_other_pages %}
|
||||
<nav aria-label="Навигация по заказам">
|
||||
<ul class="pagination justify-content-center mt-3">
|
||||
{% if orders_page.has_previous %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page=1">Первая</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ orders_page.previous_page_number }}">Предыдущая</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item active">
|
||||
<span class="page-link">
|
||||
Страница {{ orders_page.number }} из {{ orders_page.paginator.num_pages }}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{% if orders_page.has_next %}
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ orders_page.next_page_number }}">Следующая</a>
|
||||
</li>
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="?page={{ orders_page.paginator.num_pages }}">Последняя</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p class="text-muted mb-0">У клиента пока нет заказов.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -89,10 +89,24 @@ def customer_detail(request, pk):
|
||||
active_orders = customer.orders.exclude(payment_status='paid')
|
||||
total_debt = sum(order.amount_due for order in active_orders)
|
||||
|
||||
# История транзакций кошелька (последние 20)
|
||||
from .models import WalletTransaction
|
||||
wallet_transactions = WalletTransaction.objects.filter(
|
||||
customer=customer
|
||||
).select_related('order', 'created_by').order_by('-created_at')[:20]
|
||||
|
||||
# История заказов с пагинацией
|
||||
orders_list = customer.orders.all().order_by('-created_at')
|
||||
paginator = Paginator(orders_list, 10) # 10 заказов на страницу
|
||||
page_number = request.GET.get('page')
|
||||
orders_page = paginator.get_page(page_number)
|
||||
|
||||
context = {
|
||||
'customer': customer,
|
||||
'total_debt': total_debt,
|
||||
'active_orders_count': active_orders.count(),
|
||||
'wallet_transactions': wallet_transactions,
|
||||
'orders_page': orders_page,
|
||||
}
|
||||
return render(request, 'customers/customer_detail.html', context)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user