522 lines
18 KiB
HTML
522 lines
18 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}История заказов - {{ client.name }}{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container">
|
||
<!-- Хлебные крошки -->
|
||
<nav aria-label="breadcrumb" class="mb-3">
|
||
<ol class="breadcrumb">
|
||
<li class="breadcrumb-item"><a href="{{ url_for('index') }}">Поставщики</a></li>
|
||
<li class="breadcrumb-item active">{{ client.name }}</li>
|
||
</ol>
|
||
</nav>
|
||
|
||
<!-- Заголовок с информацией о клиенте -->
|
||
<div class="mb-4">
|
||
<h2 class="page-title">История заказов - {{ client.name }}</h2>
|
||
<div class="mt-2">
|
||
{% if client.rating %}
|
||
<span class="rating-badge">Рейтинг: {{ client.rating }}</span>
|
||
{% endif %}
|
||
{% if total_stats %}
|
||
<span class="stats-badge">Всего заказов: {{ total_stats.total_orders }}</span>
|
||
<span class="stats-badge">Выполнено: {{ total_stats.completed_orders }}</span>
|
||
<span class="stats-badge">Общая сумма: {{ "%.2f"|format(total_stats.total_amount or 0) }} руб.</span>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Кнопка добавления заказа -->
|
||
<div class="mb-3">
|
||
<a href="{{ url_for('add_order', client_id=client.id) }}" class="btn-custom">
|
||
<i class="fas fa-plus"></i> Добавить заказ
|
||
</a>
|
||
</div>
|
||
|
||
<!-- Детальная таблица заказов -->
|
||
<div class="table-responsive">
|
||
<table class="custom-table">
|
||
<thead>
|
||
<tr>
|
||
<th>ID заказа</th>
|
||
<th>Дата</th>
|
||
<th>Товары</th>
|
||
<th>Базовая стоимость</th>
|
||
<th>Транспортные расходы (10%)</th>
|
||
<th>Скидка</th>
|
||
<th>Итоговая стоимость</th>
|
||
<th>Статус</th>
|
||
<th>Действия</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for order in orders %}
|
||
<tr>
|
||
<td>{{ order.id }}</td>
|
||
<td>{{ order.order_date }}</td>
|
||
<td>
|
||
<button class="btn-toggle" type="button"
|
||
onclick="toggleDetails('products-{{ order.id }}')">
|
||
<i class="fas fa-eye"></i> {{ order.items_count }} товар(ов)
|
||
</button>
|
||
</td>
|
||
<td>{{ "%.2f"|format(order.base_amount) }} руб.</td>
|
||
<td>{{ "%.2f"|format(order.shipping_cost) }} руб.</td>
|
||
<td>
|
||
{% if order.discount and order.discount > 0 %}
|
||
<span class="discount-badge">{{ order.discount }}%</span>
|
||
{% else %}
|
||
<span class="text-muted">-</span>
|
||
{% endif %}
|
||
</td>
|
||
<td><strong>{{ "%.2f"|format(order.display_total) }} руб.</strong></td>
|
||
<td>
|
||
<span class="status-badge
|
||
{% if order.status == 'Выполнен' %}status-success
|
||
{% elif order.status == 'Отменен' %}status-danger
|
||
{% elif order.status == 'В обработке' %}status-warning
|
||
{% elif order.status == 'Новый' %}status-new
|
||
{% else %}status-default{% endif %}">
|
||
{{ order.status }}
|
||
</span>
|
||
</td>
|
||
<td>
|
||
<form action="{{ url_for('update_order_status', order_id=order.id) }}" method="POST" class="d-inline">
|
||
<select name="status" class="status-select" onchange="this.form.submit()">
|
||
<option value="Новый" {% if order.status == 'Новый' %}selected{% endif %}>Новый</option>
|
||
<option value="В обработке" {% if order.status == 'В обработке' %}selected{% endif %}>В обработке</option>
|
||
<option value="Выполнен" {% if order.status == 'Выполнен' %}selected{% endif %}>Выполнен</option>
|
||
<option value="Отменен" {% if order.status == 'Отменен' %}selected{% endif %}>Отменен</option>
|
||
</select>
|
||
</form>
|
||
</td>
|
||
</tr>
|
||
<tr id="products-{{ order.id }}" class="details-row" style="display: none;">
|
||
<td colspan="9">
|
||
<div class="details-container">
|
||
<div class="details-header">
|
||
<h6>Детали заказа №{{ order.id }}</h6>
|
||
<button class="btn-close" onclick="toggleDetails('products-{{ order.id }}')">
|
||
<i class="fas fa-times"></i>
|
||
</button>
|
||
</div>
|
||
<table class="details-table">
|
||
<thead>
|
||
<tr>
|
||
<th>Товар</th>
|
||
<th>Артикул</th>
|
||
<th>Категория</th>
|
||
<th>Количество</th>
|
||
<th>Цена за ед.</th>
|
||
<th>Стоимость</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% if order.order_items and order.order_items|length > 0 %}
|
||
{% for item in order.order_items %}
|
||
<tr>
|
||
<td>{{ item.product_name }}</td>
|
||
<td>{{ item.article or '—' }}</td>
|
||
<td>{{ item.category_name or '—' }}</td>
|
||
<td>{{ item.quantity }}</td>
|
||
<td>{{ "%.2f"|format(item.price_at_moment) }} руб.</td>
|
||
<td>{{ "%.2f"|format(item.item_total) }} руб.</td>
|
||
</tr>
|
||
{% endfor %}
|
||
{% else %}
|
||
<tr>
|
||
<td colspan="6" class="text-center">Нет данных о товарах</td>
|
||
</tr>
|
||
{% endif %}
|
||
</tbody>
|
||
<tfoot>
|
||
<tr>
|
||
<td colspan="5" class="text-end"><strong>Базовая стоимость:</strong></td>
|
||
<td><strong>{{ "%.2f"|format(order.base_amount) }} руб.</strong></td>
|
||
</tr>
|
||
<tr>
|
||
<td colspan="5" class="text-end">Транспортные расходы (10%):</td>
|
||
<td>+ {{ "%.2f"|format(order.shipping_cost) }} руб.</td>
|
||
</tr>
|
||
{% if order.discount and order.discount > 0 %}
|
||
<tr>
|
||
<td colspan="5" class="text-end">Скидка ({{ order.discount }}%):</td>
|
||
<td>- {{ "%.2f"|format(((order.base_amount + order.shipping_cost) * order.discount / 100)) }} руб.</td>
|
||
</tr>
|
||
{% endif %}
|
||
<tr class="total-row">
|
||
<td colspan="5" class="text-end"><strong>ИТОГО к оплате:</strong></td>
|
||
<td><strong class="total-amount">{{ "%.2f"|format(order.display_total) }} руб.</strong></td>
|
||
</tr>
|
||
</tfoot>
|
||
</table>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
{% else %}
|
||
<tr>
|
||
<td colspan="9" class="text-center py-4">
|
||
<p class="text-muted mb-2">У этого клиента пока нет заказов</p>
|
||
<a href="{{ url_for('add_order', client_id=client.id) }}" class="btn-custom btn-sm">
|
||
<i class="fas fa-plus"></i> Создать первый заказ
|
||
</a>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="mt-3">
|
||
<a href="{{ url_for('index') }}" class="btn-custom">
|
||
<i class="fas fa-arrow-left"></i> Назад к поставщикам
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
/* Основные цвета */
|
||
:root {
|
||
--antique-white: #FAEBD7;
|
||
--light-brown: #DEB887;
|
||
--brown: #A0522D;
|
||
--white: #ffffff;
|
||
--text-dark: #333333;
|
||
}
|
||
|
||
body {
|
||
background-color: var(--antique-white);
|
||
}
|
||
|
||
.container {
|
||
background-color: var(--antique-white);
|
||
padding: 20px;
|
||
border-radius: 12px;
|
||
}
|
||
|
||
/* Хлебные крошки */
|
||
.breadcrumb {
|
||
background-color: var(--white);
|
||
border: 2px solid var(--light-brown);
|
||
border-radius: 8px;
|
||
padding: 10px 15px;
|
||
}
|
||
|
||
.breadcrumb-item a {
|
||
color: var(--brown);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.breadcrumb-item a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.breadcrumb-item.active {
|
||
color: var(--text-dark);
|
||
}
|
||
|
||
.breadcrumb-item + .breadcrumb-item::before {
|
||
color: var(--light-brown);
|
||
}
|
||
|
||
/* Заголовок */
|
||
.page-title {
|
||
color: var(--brown);
|
||
font-size: 1.5rem;
|
||
font-weight: 600;
|
||
font-family: 'Verdana', sans-serif;
|
||
border-bottom: 2px solid var(--light-brown);
|
||
padding-bottom: 10px;
|
||
}
|
||
|
||
/* Бейджи */
|
||
.rating-badge, .stats-badge {
|
||
display: inline-block;
|
||
padding: 6px 12px;
|
||
border-radius: 20px;
|
||
font-size: 0.9rem;
|
||
font-weight: 500;
|
||
margin-right: 8px;
|
||
border: 1px solid var(--light-brown);
|
||
background-color: var(--white);
|
||
color: var(--brown);
|
||
}
|
||
|
||
/* Кнопки */
|
||
.btn-custom {
|
||
background: var(--white);
|
||
border: 2px solid var(--light-brown);
|
||
color: var(--brown);
|
||
padding: 8px 16px;
|
||
border-radius: 8px;
|
||
text-decoration: none;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.btn-custom:hover {
|
||
background: var(--light-brown);
|
||
color: var(--white);
|
||
}
|
||
|
||
.btn-custom i {
|
||
color: inherit;
|
||
}
|
||
|
||
.btn-custom.btn-sm {
|
||
padding: 5px 10px;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.btn-toggle {
|
||
background: none;
|
||
border: 1px solid var(--light-brown);
|
||
color: var(--brown);
|
||
padding: 4px 8px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.btn-toggle:hover {
|
||
background-color: var(--light-brown);
|
||
color: var(--white);
|
||
}
|
||
|
||
.btn-close {
|
||
background: none;
|
||
border: 1px solid var(--light-brown);
|
||
color: var(--brown);
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.btn-close:hover {
|
||
background-color: var(--light-brown);
|
||
color: var(--white);
|
||
}
|
||
|
||
/* Таблица */
|
||
.custom-table {
|
||
width: 100%;
|
||
background: var(--white);
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
border: 2px solid var(--light-brown);
|
||
border-collapse: separate;
|
||
border-spacing: 0;
|
||
}
|
||
|
||
.custom-table thead th {
|
||
background: var(--brown);
|
||
color: var(--white);
|
||
padding: 12px;
|
||
font-weight: 500;
|
||
border-bottom: 2px solid var(--light-brown);
|
||
}
|
||
|
||
.custom-table tbody td {
|
||
padding: 12px;
|
||
border-bottom: 1px solid var(--light-brown);
|
||
color: var(--text-dark);
|
||
}
|
||
|
||
.custom-table tbody tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.custom-table tbody tr:hover {
|
||
background-color: var(--antique-white);
|
||
}
|
||
|
||
/* Бейджи статусов */
|
||
.status-badge {
|
||
display: inline-block;
|
||
padding: 6px 12px;
|
||
border-radius: 20px;
|
||
font-size: 0.85rem;
|
||
font-weight: 500;
|
||
border: 1px solid;
|
||
}
|
||
|
||
.status-success {
|
||
background-color: #d4edda;
|
||
color: #155724;
|
||
border-color: #c3e6cb;
|
||
}
|
||
|
||
.status-danger {
|
||
background-color: #f8d7da;
|
||
color: #721c24;
|
||
border-color: #f5c6cb;
|
||
}
|
||
|
||
.status-warning {
|
||
background-color: #fff3cd;
|
||
color: #856404;
|
||
border-color: #ffeeba;
|
||
}
|
||
|
||
.status-new {
|
||
background-color: #cce5ff;
|
||
color: #004085;
|
||
border-color: #b8daff;
|
||
}
|
||
|
||
.status-default {
|
||
background-color: #e2e3e5;
|
||
color: #383d41;
|
||
border-color: #d6d8db;
|
||
}
|
||
|
||
/* Бейдж скидки */
|
||
.discount-badge {
|
||
display: inline-block;
|
||
padding: 4px 8px;
|
||
border-radius: 4px;
|
||
background-color: var(--light-brown);
|
||
color: var(--white);
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* Селект статуса */
|
||
.status-select {
|
||
border: 1px solid var(--light-brown);
|
||
border-radius: 4px;
|
||
padding: 4px 8px;
|
||
color: var(--brown);
|
||
background-color: var(--white);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.status-select:hover {
|
||
background-color: var(--antique-white);
|
||
}
|
||
|
||
/* Детали заказа */
|
||
.details-row {
|
||
background-color: var(--antique-white);
|
||
}
|
||
|
||
.details-container {
|
||
padding: 20px;
|
||
border: 2px solid var(--light-brown);
|
||
border-radius: 8px;
|
||
margin: 10px;
|
||
background-color: var(--white);
|
||
}
|
||
|
||
.details-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 15px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 2px solid var(--light-brown);
|
||
}
|
||
|
||
.details-header h6 {
|
||
color: var(--brown);
|
||
font-size: 1.1rem;
|
||
font-weight: 600;
|
||
margin: 0;
|
||
}
|
||
|
||
/* Детальная таблица */
|
||
.details-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
}
|
||
|
||
.details-table th {
|
||
background-color: var(--antique-white);
|
||
color: var(--brown);
|
||
padding: 8px;
|
||
text-align: left;
|
||
border-bottom: 2px solid var(--light-brown);
|
||
}
|
||
|
||
.details-table td {
|
||
padding: 8px;
|
||
border-bottom: 1px solid var(--light-brown);
|
||
}
|
||
|
||
.details-table tfoot td {
|
||
background-color: var(--antique-white);
|
||
font-weight: 500;
|
||
}
|
||
|
||
.details-table .total-row {
|
||
border-top: 2px solid var(--light-brown);
|
||
}
|
||
|
||
.details-table .total-amount {
|
||
color: var(--brown);
|
||
font-size: 1.1rem;
|
||
}
|
||
|
||
/* Иконки */
|
||
i {
|
||
color: var(--brown);
|
||
}
|
||
|
||
.btn-custom i, .btn-toggle i, .btn-close i {
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
/* Адаптивность */
|
||
@media (max-width: 768px) {
|
||
.custom-table {
|
||
font-size: 0.9rem;
|
||
}
|
||
|
||
.custom-table th, .custom-table td {
|
||
padding: 8px;
|
||
}
|
||
|
||
.status-select {
|
||
max-width: 100px;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
// Функция для открытия/закрытия деталей заказа
|
||
function toggleDetails(elementId) {
|
||
var element = document.getElementById(elementId);
|
||
if (element.style.display === "none" || element.style.display === "") {
|
||
element.style.display = "table-row";
|
||
// Плавный скролл к открытому элементу
|
||
element.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||
} else {
|
||
element.style.display = "none";
|
||
}
|
||
}
|
||
|
||
// Закрытие по клику вне области (опционально)
|
||
document.addEventListener('click', function(event) {
|
||
// Можно добавить логику для закрытия при клике вне
|
||
});
|
||
|
||
// Инициализация - скрываем все детали при загрузке
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
var detailsRows = document.querySelectorAll('.details-row');
|
||
detailsRows.forEach(function(row) {
|
||
row.style.display = 'none';
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<!-- Добавляем Font Awesome для иконок -->
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||
{% endblock %} |