my-project/templates/order_history.html
2026-03-23 11:35:48 +05:00

465 lines
18 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "base.html" %}
{% block title %}История заказов - {{ client.name }}{% endblock %}
{% block content %}
<div class="sales-history-container">
<!-- Заголовок с кнопкой назад -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<a href="javascript:history.back()" class="btn btn-back me-3">
<i class="fas fa-arrow-left"></i> Назад
</a>
<h2 class="page-title">История заказов - {{ client.name }}</h2>
</div>
</div>
<!-- Информация о клиенте -->
<div class="partner-info-card mb-4">
<div class="partner-header">
<div class="partner-name-line">
<span class="partner-type">
{% if client.contractor_type_name %}
{{ client.contractor_type_name }}
{% else %}
Тип не указан
{% endif %}
</span>
<span class="divider">|</span>
<span class="partner-name">{{ client.name }}</span>
</div>
</div>
<div class="partner-details">
<div class="row">
<div class="col-md-6">
<div class="info-item">
<span class="info-label">Директор:</span>
<span class="info-value">{{ client.director or 'Не указан' }}</span>
</div>
<div class="info-item">
<span class="info-label">Телефон:</span>
<span class="info-value">{{ client.phone or 'Не указан' }}</span>
</div>
</div>
<div class="col-md-6">
<div class="info-item">
<span class="info-label">Email:</span>
<span class="info-value">{{ client.email or 'Не указан' }}</span>
</div>
<div class="info-item">
<span class="info-label">ИНН:</span>
<span class="info-value">{{ client.inn or 'Не указан' }}</span>
</div>
</div>
</div>
</div>
</div>
<!-- Общая статистика -->
<div class="stats-card mb-4">
<h4 class="stats-title">Общая статистика</h4>
<div class="row">
<div class="col-md-3">
<div class="stat-item">
<div class="stat-number">{{ total_stats.total_orders or 0 }}</div>
<div class="stat-label">Всего заказов</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-item">
<div class="stat-number">{{ total_stats.total_quantity or 0 }}</div>
<div class="stat-label">Общее количество</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-item">
<div class="stat-number">{{ "{:,.2f}".format(total_stats.total_amount or 0) }} руб.</div>
<div class="stat-label">Общая сумма</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-item">
<div class="stat-number">{{ total_stats.completed_orders or 0 }}</div>
<div class="stat-label">Выполненных</div>
</div>
</div>
</div>
</div>
<!-- Таблица истории заказов -->
<div class="sales-table-card">
<h4 class="table-title">Детализация заказов</h4>
{% if orders %}
<div class="accordion" id="ordersAccordion">
{% for order in orders %}
<div class="accordion-item mb-3 border rounded">
<h2 class="accordion-header" id="heading{{ order.id }}">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapse{{ order.id }}" aria-expanded="false" aria-controls="collapse{{ order.id }}">
<div class="row w-100">
<div class="col-md-3">
<strong>Заказ #{{ order.id }}</strong>
</div>
<div class="col-md-3">
{{ order.order_date[:10] }}
</div>
<div class="col-md-3">
{{ order['items']|length }} позиций
</div>
<div class="col-md-3 text-end">
<span class="badge {% if order.status == 'Выполнен' %}bg-success{% elif order.status == 'Отменен' %}bg-danger{% elif order.status == 'В обработке' %}bg-warning{% else %}bg-secondary{% endif %} me-2">
{{ order.status }}
</span>
<strong>{{ "{:,.2f}".format(order.total_amount) }} руб.</strong>
</div>
</div>
</button>
</h2>
<div id="collapse{{ order.id }}" class="accordion-collapse collapse" aria-labelledby="heading{{ order.id }}" data-bs-parent="#ordersAccordion">
<div class="accordion-body">
<!-- Детальная информация о заказе -->
<div class="row mb-3">
<div class="col-md-6">
<p><strong>Дата заказа:</strong> {{ order.order_date[:10] }}</p>
<p><strong>Срок изготовления:</strong> {{ order.production_days or 1 }} дн.</p>
</div>
<div class="col-md-6">
<p><strong>Дата готовности:</strong> {{ order.production_end_date[:10] if order.production_end_date else '-' }}</p>
</div>
</div>
<!-- Таблица с товарами -->
<h5>Состав заказа:</h5>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<thead class="table-light">
<tr>
<th>Товар</th>
<th>Артикул</th>
<th>Количество</th>
<th>Цена за ед.</th>
<th>Сумма</th>
</tr>
</thead>
<tbody>
{% for item in order['items'] %}
{% set item_sum = item['price_at_moment'] * item['quantity'] %}
<tr>
<td>{{ item['product_name'] }}</td>
<td>{{ item['article'] }}</td>
<td>{{ "{:,}".format(item['quantity']) }} ед.</td>
<td>{{ "{:,.2f}".format(item['price_at_moment']) }} руб.</td>
<td>{{ "{:,.2f}".format(item_sum) }} руб.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Расчет стоимости с учетом сборки и доставки -->
<div class="row mt-3">
<div class="col-md-8 offset-md-4">
<div class="calculation-details p-3" style="background-color: #f8f9fa; border-radius: 8px;">
<div class="d-flex justify-content-between mb-2">
<span>Базовая сумма товаров:</span>
<strong>{{ "{:,.2f}".format(order.base_amount) }} руб.</strong>
</div>
<div class="d-flex justify-content-between mb-2">
<span>Сборка ({{ order.assembly_percent }}%):</span>
<span class="text-primary">+{{ "{:,.2f}".format(order.assembly_cost) }} руб.</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span>Доставка ({{ order.delivery_percent }}%):</span>
<span class="text-primary">+{{ "{:,.2f}".format(order.delivery_cost) }} руб.</span>
</div>
<div class="d-flex justify-content-between pt-2 border-top">
<span class="fw-bold">ИТОГОВАЯ СУММА ЗАКАЗА:</span>
<span class="fw-bold fs-5" style="color: var(--steel-blue);">{{ "{:,.2f}".format(order.total_amount) }} руб.</span>
</div>
</div>
</div>
</div>
<!-- Форма изменения статуса заказа -->
<div class="row mt-3">
<div class="col-md-6">
<form method="POST" action="{{ url_for('update_order_status', order_id=order.id) }}" class="d-flex align-items-center gap-2">
<label class="mb-0"><strong>Статус заказа:</strong></label>
<select name="status" class="form-select form-select-sm" style="width: 150px;" 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>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="alert alert-info">
<i class="fas fa-info-circle"></i> Нет данных о заказах
</div>
{% endif %}
</div>
</div>
<style>
.btn-back {
background: linear-gradient(135deg, var(--light-steel-blue) 0%, #9fb6d4 100%);
border: none;
border-radius: 8px;
padding: 10px 20px;
color: #2c3e50;
transition: all 0.3s ease;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
}
.btn-back:hover {
background: linear-gradient(135deg, #9fb6d4 0%, var(--light-steel-blue) 100%);
transform: translateY(-2px);
box-shadow: 0 4px 10px rgba(176, 196, 222, 0.3);
color: #2c3e50;
}
.btn-primary {
background: linear-gradient(135deg, var(--steel-blue) 0%, #3a6d99 100%);
border: none;
border-radius: 8px;
padding: 10px 20px;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
color: white;
transition: all 0.3s ease;
}
.btn-primary:hover {
background: linear-gradient(135deg, #3a6d99 0%, var(--steel-blue) 100%);
transform: translateY(-2px);
box-shadow: 0 4px 10px rgba(70, 130, 180, 0.3);
}
.page-title {
color: var(--steel-blue);
font-size: 1.8rem;
font-weight: 600;
display: inline-block;
margin: 0;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
}
.partner-info-card {
background: linear-gradient(135deg, var(--alice-blue) 0%, #E6F2FF 100%);
border: 1px solid var(--light-steel-blue);
border-radius: 15px;
padding: 20px;
box-shadow: 0 4px 10px rgba(70, 130, 180, 0.1);
}
.partner-header {
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 2px solid var(--light-steel-blue);
}
.partner-name-line {
display: flex;
align-items: center;
gap: 10px;
}
.partner-type {
background-color: transparent;
color: #2c3e50 !important;
padding: 5px 15px;
border-radius: 20px;
font-size: 1rem;
font-weight: 600;
text-transform: uppercase;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
border: 2px solid var(--light-steel-blue);
}
.divider {
color: var(--steel-blue);
font-weight: 600;
}
.partner-name {
color: #2c3e50;
font-size: 1.3rem;
font-weight: 600;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
}
.info-item {
margin-bottom: 10px;
padding: 8px 15px;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 8px;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
}
.info-label {
color: var(--steel-blue);
font-weight: 600;
margin-right: 10px;
}
.info-value {
color: #2c3e50;
}
.stats-card {
background: linear-gradient(135deg, var(--alice-blue) 0%, #E6F2FF 100%);
border: 1px solid var(--light-steel-blue);
border-radius: 15px;
padding: 20px;
box-shadow: 0 4px 10px rgba(70, 130, 180, 0.1);
}
.stats-title, .table-title {
color: var(--steel-blue);
font-size: 1.3rem;
font-weight: 600;
margin-bottom: 20px;
border-bottom: 2px solid var(--light-steel-blue);
padding-bottom: 10px;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
}
.stat-item {
text-align: center;
padding: 15px;
background: linear-gradient(135deg, white 0%, #f8f9fa 100%);
border: 2px solid var(--light-steel-blue);
border-radius: 12px;
box-shadow: 0 4px 8px rgba(70, 130, 180, 0.15);
transition: all 0.3s ease;
}
.stat-item:hover {
transform: translateY(-3px);
box-shadow: 0 8px 15px rgba(70, 130, 180, 0.25);
border-color: var(--steel-blue);
}
.stat-number {
color: #2c3e50 !important;
font-size: 2rem;
font-weight: 700;
line-height: 1.2;
margin-bottom: 5px;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
}
.stat-label {
color: #6c757d;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 0.5px;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
}
.sales-table-card {
background: linear-gradient(135deg, var(--alice-blue) 0%, #E6F2FF 100%);
border: 1px solid var(--light-steel-blue);
border-radius: 15px;
padding: 20px;
box-shadow: 0 4px 10px rgba(70, 130, 180, 0.1);
}
.accordion-item {
border: 1px solid var(--light-steel-blue);
border-radius: 10px !important;
overflow: hidden;
}
.accordion-button {
background: linear-gradient(135deg, var(--alice-blue) 0%, #E6F2FF 100%);
color: #2c3e50;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
padding: 15px 20px;
}
.accordion-button:not(.collapsed) {
background: linear-gradient(135deg, var(--light-steel-blue) 0%, #9fb6d4 100%);
color: #2c3e50;
}
.accordion-button:focus {
box-shadow: none;
border-color: var(--steel-blue);
}
.accordion-body {
background-color: white;
padding: 20px;
}
.badge {
padding: 6px 12px;
font-size: 0.85rem;
border-radius: 20px;
font-family: 'Franklin Gothic', 'Arial Narrow', Arial, sans-serif;
font-weight: 500;
}
.badge.bg-success {
background: linear-gradient(135deg, #28a745 0%, #218838 100%) !important;
color: white !important;
}
.badge.bg-warning {
background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%) !important;
color: #2c3e50 !important;
}
.badge.bg-danger {
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%) !important;
color: white !important;
}
.badge.bg-secondary {
background: linear-gradient(135deg, #6c757d 0%, #5a6268 100%) !important;
color: white !important;
}
.table-sm td, .table-sm th {
padding: 8px;
}
.calculation-details {
background-color: #f8f9fa;
border: 1px solid var(--light-steel-blue);
border-radius: 8px;
}
.text-primary {
color: var(--steel-blue) !important;
}
small {
font-size: 0.8rem;
color: #6c757d;
}
@media (max-width: 768px) {
.page-title {
font-size: 1.4rem;
}
.stat-number {
font-size: 1.6rem;
}
.accordion-button .row > div {
margin-bottom: 5px;
text-align: left !important;
}
}
</style>
{% endblock %}