228 lines
6.8 KiB
HTML
228 lines
6.8 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block content %}
|
||
<div class="page-header">
|
||
<h2>Управление заказами</h2>
|
||
<div class="header-actions">
|
||
<a href="{{ url_for('add_order') }}" class="btn-add">+ Новый заказ</a>
|
||
<a href="{{ url_for('export_orders') }}" class="btn-export">Экспорт CSV</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="filters-bar">
|
||
<select id="statusFilter" onchange="filterOrders()">
|
||
<option value="all">Все статусы</option>
|
||
<option value="новый">Новые</option>
|
||
<option value="в_обработке">В обработке</option>
|
||
<option value="завершен">Завершенные</option>
|
||
</select>
|
||
|
||
<select id="supplierFilter" onchange="filterOrders()">
|
||
<option value="all">Все поставщики</option>
|
||
{% for supplier in suppliers %}
|
||
<option value="{{ supplier.id }}">{{ supplier.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
|
||
<input type="text" id="searchInput" placeholder="Поиск по номеру заказа..." onkeyup="filterOrders()">
|
||
|
||
<select id="sortBy" onchange="sortOrders()">
|
||
<option value="date_desc">Сначала новые</option>
|
||
<option value="date_asc">Сначала старые</option>
|
||
<option value="total_desc">По сумме (убыв.)</option>
|
||
<option value="total_asc">По сумме (возр.)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="orders-table-container">
|
||
<table class="orders-table" id="ordersTable">
|
||
<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 %}
|
||
<tr data-status="{{ order.status }}" data-supplier="{{ order.supplier_id }}"
|
||
data-total="{{ order.total }}" data-date="{{ order.order_date }}">
|
||
<td>#{{ order.order_id }}</td>
|
||
<td>{{ order.order_date }}</td>
|
||
<td>{{ order.supplier_name }}</td>
|
||
<td><span class="order-status status-{{ order.status }}">{{ order.status }}</span></td>
|
||
<td>{{ order.items|length }}</td>
|
||
<td>{{ order.subtotal }} ₽</td>
|
||
<td>
|
||
{% if order.discount_percent > 0 %}
|
||
{{ order.discount_percent }}% (-{{ order.discount_amount }} ₽)
|
||
{% else %}
|
||
-
|
||
{% endif %}
|
||
</td>
|
||
<td><strong>{{ order.total }} ₽</strong></td>
|
||
<td class="actions">
|
||
<a href="{{ url_for('order_detail', order_id=order.order_id) }}" class="btn-view-small">👁️</a>
|
||
<a href="{{ url_for('edit_order', order_id=order.order_id) }}" class="btn-edit-small">✏️</a>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<script>
|
||
let currentOrders = [];
|
||
|
||
function filterOrders() {
|
||
const statusFilter = document.getElementById('statusFilter').value;
|
||
const supplierFilter = document.getElementById('supplierFilter').value;
|
||
const searchText = document.getElementById('searchInput').value.toLowerCase();
|
||
const rows = document.querySelectorAll('#ordersTable tbody tr');
|
||
|
||
rows.forEach(row => {
|
||
const status = row.dataset.status;
|
||
const supplier = row.dataset.supplier;
|
||
const orderId = row.cells[0].textContent.toLowerCase();
|
||
|
||
const matchesStatus = statusFilter === 'all' || status === statusFilter;
|
||
const matchesSupplier = supplierFilter === 'all' || supplier === supplierFilter;
|
||
const matchesSearch = orderId.includes(searchText);
|
||
|
||
if (matchesStatus && matchesSupplier && matchesSearch) {
|
||
row.style.display = '';
|
||
} else {
|
||
row.style.display = 'none';
|
||
}
|
||
});
|
||
}
|
||
|
||
function sortOrders() {
|
||
const tbody = document.querySelector('#ordersTable tbody');
|
||
const rows = Array.from(tbody.querySelectorAll('tr'));
|
||
const sortBy = document.getElementById('sortBy').value;
|
||
|
||
rows.sort((a, b) => {
|
||
let aVal, bVal;
|
||
|
||
switch(sortBy) {
|
||
case 'date_desc':
|
||
aVal = new Date(a.dataset.date);
|
||
bVal = new Date(b.dataset.date);
|
||
return bVal - aVal;
|
||
case 'date_asc':
|
||
aVal = new Date(a.dataset.date);
|
||
bVal = new Date(b.dataset.date);
|
||
return aVal - bVal;
|
||
case 'total_desc':
|
||
aVal = parseFloat(a.dataset.total);
|
||
bVal = parseFloat(b.dataset.total);
|
||
return bVal - aVal;
|
||
case 'total_asc':
|
||
aVal = parseFloat(a.dataset.total);
|
||
bVal = parseFloat(b.dataset.total);
|
||
return aVal - bVal;
|
||
}
|
||
});
|
||
|
||
tbody.innerHTML = '';
|
||
rows.forEach(row => tbody.appendChild(row));
|
||
}
|
||
|
||
// Инициализация
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
const supplierId = urlParams.get('supplier');
|
||
|
||
if (supplierId) {
|
||
document.getElementById('supplierFilter').value = supplierId;
|
||
filterOrders();
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<style>
|
||
.filters-bar {
|
||
display: flex;
|
||
gap: 10px;
|
||
margin-bottom: 20px;
|
||
flex-wrap: wrap;
|
||
background: white;
|
||
padding: 15px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.filters-bar select,
|
||
.filters-bar input {
|
||
padding: 8px 12px;
|
||
border: 1px solid #E0E0E0;
|
||
border-radius: 4px;
|
||
font-family: 'Calibri', sans-serif;
|
||
min-width: 150px;
|
||
}
|
||
|
||
.filters-bar input {
|
||
flex: 1;
|
||
min-width: 200px;
|
||
}
|
||
|
||
.orders-table-container {
|
||
background: white;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.orders-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
}
|
||
|
||
.orders-table th {
|
||
background-color: #696969;
|
||
color: white;
|
||
padding: 12px 15px;
|
||
text-align: left;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.orders-table td {
|
||
padding: 12px 15px;
|
||
border-bottom: 1px solid #E0E0E0;
|
||
}
|
||
|
||
.orders-table tbody tr:hover {
|
||
background-color: #F5F5F5;
|
||
}
|
||
|
||
.actions {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.btn-view-small,
|
||
.btn-edit-small {
|
||
display: inline-block;
|
||
padding: 5px 10px;
|
||
text-decoration: none;
|
||
border-radius: 4px;
|
||
margin: 0 2px;
|
||
}
|
||
|
||
.btn-view-small {
|
||
background-color: #E0E0E0;
|
||
color: #696969;
|
||
}
|
||
|
||
.btn-edit-small {
|
||
background-color: #696969;
|
||
color: white;
|
||
}
|
||
</style>
|
||
{% endblock %} |