my-project/main_flask.py
2026-03-23 11:35:48 +05:00

897 lines
34 KiB
Python
Raw 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.

from flask import Flask, render_template, send_from_directory, request, redirect, url_for, flash, session
import sqlite3
import os
from datetime import datetime, timedelta
app = Flask(__name__)
app.secret_key = 'my_secret_key_12345'
# ========== ФИЛЬТР ДЛЯ ФОРМАТИРОВАНИЯ ДАТ ==========
@app.template_filter('date_format')
def date_format(value):
"""Преобразует дату из формата YYYY-MM-DD в ДД.ММ.ГГГГ"""
if not value:
return '-'
try:
# Если value уже строка, пробуем распарсить
if isinstance(value, str) and len(value) >= 10:
# Проверяем, что это похоже на дату в формате YYYY-MM-DD
if value[4] == '-' and value[7] == '-':
year, month, day = value[:10].split('-')
return f"{day}.{month}.{year}"
return value
except:
return value
def get_db_connection():
conn = sqlite3.connect('partners.db')
conn.row_factory = sqlite3.Row
return conn
def dict_from_row(row):
"""Преобразует sqlite3.Row в словарь"""
if row is None:
return None
return {key: row[key] for key in row.keys()}
def list_from_rows(rows):
"""Преобразует список sqlite3.Row в список словарей"""
return [dict_from_row(row) for row in rows]
def calculate_discount(total_amount):
"""Рассчитывает скидку на основе общей суммы заказов в рублях"""
return 0, '0%'
def calculate_order_discount(order_amount):
"""Рассчитывает скидку на текущий заказ в зависимости от его суммы"""
return 0
# ========== ГЛАВНАЯ СТРАНИЦА ==========
@app.route('/')
def index():
# Получаем параметры фильтрации из URL
search_query = request.args.get('search', '')
client_type = request.args.get('type', 'all')
min_rating = request.args.get('rating', '0')
sort_by = request.args.get('sort', 'name_asc')
conn = get_db_connection()
try:
# Получаем общее количество всех клиентов (без фильтров)
total_count = conn.execute('SELECT COUNT(*) as count FROM Clients').fetchone()['count']
# Базовый SQL запрос для клиентов
sql = '''
SELECT c.*, ct.type_name as contractor_type_name,
COALESCE(SUM(o.total_amount), 0) as total_amount,
COALESCE(SUM(oi.quantity), 0) as total_quantity,
COUNT(DISTINCT o.id) as orders_count
FROM Clients c
LEFT JOIN ContractorType ct ON c.contractor_type_id = ct.id
LEFT JOIN Orders o ON c.id = o.client_id
LEFT JOIN OrderItems oi ON o.id = oi.order_id
WHERE 1=1
'''
params = []
# Поиск по названию или ИНН
if search_query:
sql += " AND (c.name LIKE ? OR c.inn LIKE ?)"
params.extend([f'%{search_query}%', f'%{search_query}%'])
# Фильтр по типу клиента
if client_type != 'all':
sql += " AND ct.type_name = ?"
params.append(client_type)
# Фильтр по минимальному рейтингу
if min_rating != '0':
sql += " AND c.rating >= ?"
params.append(float(min_rating))
# Группировка (обязательно после WHERE)
sql += " GROUP BY c.id"
# Сортировка
if sort_by == 'name_asc':
sql += " ORDER BY c.name ASC"
elif sort_by == 'name_desc':
sql += " ORDER BY c.name DESC"
elif sort_by == 'rating_desc':
sql += " ORDER BY c.rating DESC"
elif sort_by == 'rating_asc':
sql += " ORDER BY c.rating ASC"
elif sort_by == 'discount_desc':
sql += " ORDER BY total_amount DESC"
elif sort_by == 'discount_asc':
sql += " ORDER BY total_amount ASC"
else:
sql += " ORDER BY c.name ASC"
# Выполняем запрос и преобразуем в словари
rows = conn.execute(sql, params).fetchall()
clients = list_from_rows(rows)
# Добавляем информацию о скидке на основе суммы
clients_with_discount = []
for client in clients:
total_amount = client['total_amount'] or 0
discount_percent, discount_text = calculate_discount(total_amount)
client['total_sales'] = total_amount
client['discount_percent'] = discount_percent
client['discount'] = discount_percent
client['discount_text'] = discount_text
clients_with_discount.append(client)
conn.close()
return render_template('index.html',
partners=clients_with_discount,
total_count=total_count)
except Exception as e:
conn.close()
print(f"❌ ОШИБКА: {e}")
return render_template('index.html',
partners=[],
total_count=0,
error_message=f"Ошибка базы данных: {str(e)}")
# ========== МАРШРУТЫ ДЛЯ КЛИЕНТОВ ==========
@app.route('/add_client', methods=['GET', 'POST'])
def add_client():
if request.method == 'POST':
try:
name = request.form['name']
director = request.form.get('director', '')
email = request.form['email']
phone = request.form.get('phone', '')
address = request.form.get('address', '')
inn = request.form.get('inn', '')
contractor_type_id = request.form['contractor_type_id']
rating = request.form.get('rating', 0.0)
conn = get_db_connection()
# Проверяем уникальность ИНН
if inn:
existing = conn.execute('SELECT id FROM Clients WHERE inn = ?', (inn,)).fetchone()
if existing:
flash('Клиент с таким ИНН уже существует', 'error')
conn.close()
return redirect(url_for('add_client'))
conn.execute('''
INSERT INTO Clients (name, director, email, phone, address, inn, contractor_type_id, rating)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (name, director, email, phone, address, inn, contractor_type_id, rating))
conn.commit()
conn.close()
flash('Клиент успешно добавлен!', 'success')
return redirect(url_for('index'))
except Exception as e:
flash(f'Ошибка: {str(e)}', 'error')
return redirect(url_for('add_client'))
# GET запрос
conn = get_db_connection()
contractor_types = conn.execute('SELECT * FROM ContractorType ORDER BY type_name').fetchall()
conn.close()
return render_template('add_client.html', contractor_types=contractor_types)
@app.route('/edit_client/<int:client_id>', methods=['GET', 'POST'])
def edit_client(client_id):
conn = get_db_connection()
if request.method == 'POST':
try:
name = request.form['name']
director = request.form.get('director', '')
email = request.form['email']
phone = request.form.get('phone', '')
address = request.form.get('address', '')
inn = request.form.get('inn', '')
contractor_type_id = request.form['contractor_type_id']
rating = request.form.get('rating', 0.0)
# Проверяем уникальность ИНН
if inn:
existing = conn.execute(
'SELECT id FROM Clients WHERE inn = ? AND id != ?',
(inn, client_id)
).fetchone()
if existing:
flash('Клиент с таким ИНН уже существует', 'error')
conn.close()
return redirect(url_for('edit_client', client_id=client_id))
conn.execute('''
UPDATE Clients
SET name = ?, director = ?, email = ?, phone = ?,
address = ?, inn = ?, contractor_type_id = ?, rating = ?
WHERE id = ?
''', (name, director, email, phone, address, inn, contractor_type_id, rating, client_id))
conn.commit()
conn.close()
flash('Данные обновлены!', 'success')
return redirect(url_for('index'))
except Exception as e:
flash(f'Ошибка: {str(e)}', 'error')
conn.close()
return redirect(url_for('edit_client', client_id=client_id))
# GET запрос
client_row = conn.execute('''
SELECT c.*, ct.type_name as contractor_type_name
FROM Clients c
LEFT JOIN ContractorType ct ON c.contractor_type_id = ct.id
WHERE c.id = ?
''', (client_id,)).fetchone()
client_dict = dict_from_row(client_row)
contractor_types = conn.execute('SELECT * FROM ContractorType ORDER BY type_name').fetchall()
conn.close()
if not client_dict:
flash('Клиент не найден', 'error')
return redirect(url_for('index'))
return render_template('edit_client.html', client=client_dict, contractor_types=contractor_types)
# ========== МАРШРУТЫ ДЛЯ ЗАКАЗОВ ==========
@app.route('/order_history/<int:client_id>')
def order_history(client_id):
conn = get_db_connection()
client_row = conn.execute('''
SELECT c.*, ct.type_name as contractor_type_name
FROM Clients c
LEFT JOIN ContractorType ct ON c.contractor_type_id = ct.id
WHERE c.id = ?
''', (client_id,)).fetchone()
client_dict = dict_from_row(client_row)
# Получаем заказы клиента
orders_rows = conn.execute('''
SELECT
o.*
FROM Orders o
WHERE o.client_id = ?
ORDER BY o.order_date DESC, o.id DESC
''', (client_id,)).fetchall()
# Получаем детальную информацию о товарах в каждом заказе
orders_with_items = []
total_quantity_all = 0
total_amount_all = 0
completed_count = 0
for order_row in orders_rows:
order_dict = dict_from_row(order_row)
# Получаем товары для этого заказа
items_rows = conn.execute('''
SELECT oi.*, cat.product_name, cat.article, cat.min_price, cat2.category_name
FROM OrderItems oi
JOIN Catalog cat ON oi.product_id = cat.id
LEFT JOIN Categories cat2 ON cat.category_id = cat2.id
WHERE oi.order_id = ?
''', (order_dict['id'],)).fetchall()
items_list = list_from_rows(items_rows)
order_dict['items'] = items_list
# Считаем общее количество для этого заказа
order_total_qty = sum(item['quantity'] for item in items_list) if items_list else 0
order_dict['total_items'] = order_total_qty
total_quantity_all += order_total_qty
total_amount_all += order_dict['total_amount']
if order_dict['status'] == 'Выполнен':
completed_count += 1
orders_with_items.append(order_dict)
# Статистика
total_stats = {
'total_orders': len(orders_with_items),
'total_quantity': total_quantity_all,
'total_amount': total_amount_all,
'completed_orders': completed_count
}
conn.close()
if not client_dict:
flash('Клиент не найден', 'error')
return redirect(url_for('index'))
return render_template('order_history.html',
client=client_dict,
orders=orders_with_items,
total_stats=total_stats)
# ========== МАРШРУТ ДЛЯ ОБНОВЛЕНИЯ СТАТУСА ЗАКАЗА ==========
@app.route('/update_order_status/<int:order_id>', methods=['POST'])
def update_order_status(order_id):
"""Обновление статуса заказа"""
try:
new_status = request.form['status']
conn = get_db_connection()
conn.execute('UPDATE Orders SET status = ? WHERE id = ?', (new_status, order_id))
conn.commit()
conn.close()
flash(f'Статус заказа обновлен на "{new_status}"', 'success')
except Exception as e:
flash(f'Ошибка при обновлении статуса: {str(e)}', 'error')
return redirect(request.referrer or url_for('orders_list'))
# ========== МАРШРУТ ДЛЯ ОБНОВЛЕНИЯ СТАТУСА ПРОИЗВОДСТВА ==========
@app.route('/update_production_status/<int:order_id>', methods=['POST'])
def update_production_status(order_id):
"""Обновление статуса производства"""
try:
new_status = request.form['production_status']
conn = get_db_connection()
conn.execute('UPDATE Orders SET production_status = ? WHERE id = ?', (new_status, order_id))
conn.commit()
conn.close()
flash(f'Статус производства обновлен на "{new_status}"', 'success')
except Exception as e:
flash(f'Ошибка при обновлении статуса производства: {str(e)}', 'error')
return redirect(request.referrer)
# ========== МАРШРУТЫ ДЛЯ ТОВАРОВ ==========
@app.route('/add_product', methods=['GET', 'POST'])
def add_product():
if request.method == 'POST':
try:
product_name = request.form['product_name']
article = request.form['article']
category_id = request.form['category_id']
material_id = request.form.get('material_id') or None
description = request.form.get('description', '')
min_price = float(request.form['min_price'])
quantity_in_stock = int(request.form.get('quantity_in_stock', 0))
production_time_days = int(request.form.get('production_time_days', 1))
conn = get_db_connection()
existing = conn.execute('SELECT id FROM Catalog WHERE article = ?', (article,)).fetchone()
if existing:
flash('Товар с таким артикулом уже существует', 'error')
conn.close()
return redirect(url_for('add_product'))
conn.execute('''
INSERT INTO Catalog
(product_name, article, category_id, material_id, description, min_price,
quantity_in_stock, production_time_days)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (product_name, article, category_id, material_id, description, min_price,
quantity_in_stock, production_time_days))
conn.commit()
conn.close()
flash('Товар успешно добавлен!', 'success')
return redirect(url_for('catalog'))
except Exception as e:
flash(f'Ошибка: {str(e)}', 'error')
return redirect(url_for('add_product'))
conn = get_db_connection()
categories = conn.execute('SELECT * FROM Categories ORDER BY category_name').fetchall()
materials = conn.execute('SELECT * FROM Materials ORDER BY material_name').fetchall()
conn.close()
return render_template('add_product.html', categories=categories, materials=materials)
@app.route('/edit_product/<int:product_id>', methods=['GET', 'POST'])
def edit_product(product_id):
conn = get_db_connection()
if request.method == 'POST':
try:
product_name = request.form['product_name']
article = request.form['article']
category_id = request.form['category_id']
material_id = request.form.get('material_id') or None
description = request.form.get('description', '')
min_price = float(request.form['min_price'])
quantity_in_stock = int(request.form.get('quantity_in_stock', 0))
production_time_days = int(request.form.get('production_time_days', 1))
existing = conn.execute(
'SELECT id FROM Catalog WHERE article = ? AND id != ?',
(article, product_id)
).fetchone()
if existing:
flash('Товар с таким артикулом уже существует', 'error')
conn.close()
return redirect(url_for('edit_product', product_id=product_id))
conn.execute('''
UPDATE Catalog
SET product_name = ?, article = ?, category_id = ?, material_id = ?,
description = ?, min_price = ?, quantity_in_stock = ?,
production_time_days = ?
WHERE id = ?
''', (product_name, article, category_id, material_id, description, min_price,
quantity_in_stock, production_time_days, product_id))
conn.commit()
conn.close()
flash('Товар успешно обновлен!', 'success')
return redirect(url_for('catalog'))
except Exception as e:
flash(f'Ошибка: {str(e)}', 'error')
return redirect(url_for('edit_product', product_id=product_id))
product_row = conn.execute('''
SELECT cat.*, c.category_name, m.material_name
FROM Catalog cat
LEFT JOIN Categories c ON cat.category_id = c.id
LEFT JOIN Materials m ON cat.material_id = m.id
WHERE cat.id = ?
''', (product_id,)).fetchone()
product_dict = dict_from_row(product_row)
categories = conn.execute('SELECT * FROM Categories ORDER BY category_name').fetchall()
materials = conn.execute('SELECT * FROM Materials ORDER BY material_name').fetchall()
conn.close()
if not product_dict:
flash('Товар не найден', 'error')
return redirect(url_for('catalog'))
return render_template('edit_product.html',
product=product_dict,
categories=categories,
materials=materials)
@app.route('/delete_product/<int:product_id>', methods=['POST'])
def delete_product(product_id):
try:
conn = get_db_connection()
order_items = conn.execute('SELECT COUNT(*) as count FROM OrderItems WHERE product_id = ?', (product_id,)).fetchone()
if order_items['count'] > 0:
flash('Нельзя удалить товар, по которому есть заказы', 'error')
conn.close()
return redirect(url_for('catalog'))
conn.execute('DELETE FROM Catalog WHERE id = ?', (product_id,))
conn.commit()
conn.close()
flash('Товар успешно удален', 'success')
except Exception as e:
flash(f'Ошибка при удалении: {str(e)}', 'error')
return redirect(url_for('catalog'))
@app.route('/catalog')
def catalog():
conn = get_db_connection()
categories = conn.execute('SELECT * FROM Categories ORDER BY category_name').fetchall()
# Получаем список всех клиентов для выпадающего списка
clients_rows = conn.execute('SELECT id, name FROM Clients ORDER BY name').fetchall()
clients = list_from_rows(clients_rows)
search_query = request.args.get('search', '')
category_id = request.args.get('category', 'all')
sort_by = request.args.get('sort', 'name_asc')
sql = '''
SELECT cat.*, c.category_name, m.material_name, m.color,
m.production_time_days, m.daily_capacity
FROM Catalog cat
LEFT JOIN Categories c ON cat.category_id = c.id
LEFT JOIN Materials m ON cat.material_id = m.id
WHERE 1=1
'''
params = []
if search_query:
sql += " AND (cat.product_name LIKE ? OR cat.article LIKE ?)"
params.extend([f'%{search_query}%', f'%{search_query}%'])
if category_id != 'all':
sql += " AND cat.category_id = ?"
params.append(category_id)
if sort_by == 'name_asc':
sql += " ORDER BY cat.product_name ASC"
elif sort_by == 'name_desc':
sql += " ORDER BY cat.product_name DESC"
elif sort_by == 'price_asc':
sql += " ORDER BY cat.min_price ASC"
elif sort_by == 'price_desc':
sql += " ORDER BY cat.min_price DESC"
elif sort_by == 'stock_desc':
sql += " ORDER BY cat.quantity_in_stock DESC"
else:
sql += " ORDER BY cat.product_name ASC"
products_rows = conn.execute(sql, params).fetchall()
products = list_from_rows(products_rows)
cart = session.get('cart', {})
cart_count = sum(item['quantity'] for item in cart.values()) if cart else 0
conn.close()
return render_template('catalog.html',
products=products,
categories=categories,
clients=clients,
cart_count=cart_count)
@app.route('/product/<int:product_id>')
def product_detail(product_id):
conn = get_db_connection()
product_row = conn.execute('''
SELECT cat.*, c.category_name, m.material_name,
m.price_per_unit, m.unit, m.in_stock as material_stock,
m.daily_capacity as material_capacity,
m.production_time_days as material_production_time,
m.cost_price as material_cost_price
FROM Catalog cat
LEFT JOIN Categories c ON cat.category_id = c.id
LEFT JOIN Materials m ON cat.material_id = m.id
WHERE cat.id = ?
''', (product_id,)).fetchone()
product_dict = dict_from_row(product_row)
material = None
if product_dict and product_dict.get('material_id'):
material_row = conn.execute('SELECT * FROM Materials WHERE id = ?', (product_dict['material_id'],)).fetchone()
material = dict_from_row(material_row)
orders_stats_row = conn.execute('''
SELECT
COUNT(DISTINCT oi.order_id) as total_orders,
SUM(oi.quantity) as total_sold,
AVG(oi.quantity) as avg_order_size
FROM OrderItems oi
WHERE oi.product_id = ?
''', (product_id,)).fetchone()
orders_stats_dict = dict_from_row(orders_stats_row)
conn.close()
if not product_dict:
flash('Товар не найден', 'error')
return redirect(url_for('catalog'))
return render_template('product_detail.html',
product=product_dict,
material=material,
orders_stats=orders_stats_dict)
# ========== МАРШРУТЫ ДЛЯ КОРЗИНЫ ==========
@app.route('/cart')
def view_cart():
cart = session.get('cart', {})
cart_items = []
total_amount = 0
conn = get_db_connection()
for key, item_data in cart.items():
product_id = item_data['product_id']
quantity = item_data['quantity']
client_id = item_data['client_id']
# Получаем информацию о товаре
product_row = conn.execute('''
SELECT cat.*, c.category_name, m.material_name, cat.quantity_in_stock
FROM Catalog cat
LEFT JOIN Categories c ON cat.category_id = c.id
LEFT JOIN Materials m ON cat.material_id = m.id
WHERE cat.id = ?
''', (product_id,)).fetchone()
# Получаем информацию о партнере
client_row = conn.execute('SELECT name FROM Clients WHERE id = ?', (client_id,)).fetchone()
client_name = client_row['name'] if client_row else 'Неизвестный'
if product_row:
product = dict_from_row(product_row)
cart_items.append({
'id': key,
'product_id': product_id,
'product_name': product['product_name'],
'article': product['article'],
'category_name': product['category_name'],
'material_name': product['material_name'],
'client_id': client_id,
'client_name': client_name,
'price': product['min_price'],
'quantity': quantity,
'in_stock': product['quantity_in_stock'] or 0
})
total_amount += product['min_price'] * quantity
conn.close()
return render_template('cart_new.html', cart_items=cart_items, total_amount=total_amount)
@app.route('/add_to_cart/<int:product_id>', methods=['POST'])
def add_to_cart(product_id):
quantity = int(request.form.get('quantity', 1))
client_id = request.form.get('client_id')
if not client_id:
flash('Выберите партнера', 'error')
return redirect(url_for('catalog'))
cart = session.get('cart', {})
# Проверяем, что все товары в корзине от одного партнера
if cart:
existing_client = next(iter(cart.values()))['client_id']
if existing_client != int(client_id):
flash('Нельзя добавлять товары разных партнеров в одну корзину', 'error')
return redirect(url_for('catalog'))
# Создаем уникальный ключ для комбинации товар + партнер
key = f"{product_id}_{client_id}"
if key in cart:
cart[key]['quantity'] += quantity
else:
cart[key] = {
'product_id': product_id,
'client_id': int(client_id),
'quantity': quantity
}
session['cart'] = cart
flash('Товар добавлен в корзину', 'success')
return redirect(url_for('catalog'))
@app.route('/update_cart/<path:item_id>', methods=['POST'])
def update_cart(item_id):
quantity = int(request.form.get('quantity', 1))
cart = session.get('cart', {})
if quantity > 0 and item_id in cart:
cart[item_id]['quantity'] = quantity
elif quantity <= 0 and item_id in cart:
cart.pop(item_id, None)
session['cart'] = cart
return ('', 204)
@app.route('/remove_from_cart/<path:item_id>', methods=['POST'])
def remove_from_cart(item_id):
cart = session.get('cart', {})
cart.pop(item_id, None)
session['cart'] = cart
return redirect(url_for('view_cart'))
# ========== МАРШРУТ ДЛЯ ОФОРМЛЕНИЯ ЗАКАЗА ==========
@app.route('/checkout', methods=['POST'])
def checkout():
cart = session.get('cart', {})
if not cart:
flash('Корзина пуста', 'error')
return redirect(url_for('catalog'))
conn = get_db_connection()
# Проверяем, что все товары от одного партнера
client_ids = set(item_data['client_id'] for item_data in cart.values())
if len(client_ids) > 1:
flash('Ошибка: в корзине товары от разных партнеров', 'error')
conn.close()
return redirect(url_for('view_cart'))
client_id = list(client_ids)[0] if client_ids else None
# Собираем все товары
items = []
subtotal = 0
for key, item_data in cart.items():
product_id = item_data['product_id']
quantity = item_data['quantity']
product_row = conn.execute('SELECT * FROM Catalog WHERE id = ?', (product_id,)).fetchone()
if not product_row:
flash(f'Товар с ID {product_id} не найден', 'error')
conn.close()
return redirect(url_for('view_cart'))
product = dict_from_row(product_row)
if product['quantity_in_stock'] < quantity:
flash(f'Недостаточно товара "{product["product_name"]}" на складе', 'error')
conn.close()
return redirect(url_for('view_cart'))
items.append({
'product': product,
'quantity': quantity
})
subtotal += product['min_price'] * quantity
try:
# Рассчитываем наценку 15% + 10% = 25%
assembly_percent = 15
delivery_percent = 10
assembly_cost = subtotal * assembly_percent / 100
delivery_cost = subtotal * delivery_percent / 100
total_amount = subtotal + assembly_cost + delivery_cost
# Срок изготовления (максимальный из всех товаров)
production_days = max(item['product']['production_time_days'] or 1 for item in items)
today = datetime.now().strftime('%Y-%m-%d')
end_date = (datetime.now() + timedelta(days=production_days)).strftime('%Y-%m-%d')
# Создаем ОДИН заказ
cursor = conn.execute('''
INSERT INTO Orders (
client_id, order_date, total_amount, status,
production_days, production_start_date, production_end_date, production_status,
assembly_percent, delivery_percent, assembly_cost, delivery_cost, base_amount
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (
client_id, today, total_amount, 'Новый',
production_days, today, end_date, 'Ожидает',
assembly_percent, delivery_percent, assembly_cost, delivery_cost, subtotal
))
order_id = cursor.lastrowid
# Добавляем все товары в OrderItems
for item in items:
product = item['product']
quantity = item['quantity']
conn.execute('''
INSERT INTO OrderItems (order_id, product_id, quantity, price_at_moment)
VALUES (?, ?, ?, ?)
''', (order_id, product['id'], quantity, product['min_price']))
conn.execute('''
UPDATE Catalog
SET quantity_in_stock = quantity_in_stock - ?
WHERE id = ?
''', (quantity, product['id']))
conn.commit()
session.pop('cart', None)
flash(f'✅ Заказ успешно оформлен! Сумма: {total_amount:.2f} руб.', 'success')
except Exception as e:
conn.rollback()
flash(f'Ошибка при создании заказа: {str(e)}', 'error')
conn.close()
return redirect(url_for('orders_list'))
# ========== МАРШРУТ ДЛЯ СПИСКА ВСЕХ ЗАКАЗОВ ==========
@app.route('/orders_list')
def orders_list():
"""Список всех заказов"""
conn = get_db_connection()
clients_rows = conn.execute('SELECT id, name FROM Clients ORDER BY name').fetchall()
clients_list = list_from_rows(clients_rows)
# Получаем заказы с основной информацией
orders_rows = conn.execute('''
SELECT
o.*,
c.name as client_name,
c.inn as client_inn,
COUNT(oi.id) as items_count,
COALESCE(SUM(oi.quantity), 0) as total_items
FROM Orders o
LEFT JOIN Clients c ON o.client_id = c.id
LEFT JOIN OrderItems oi ON o.id = oi.order_id
GROUP BY o.id
ORDER BY o.order_date DESC, o.id DESC
LIMIT 100
''').fetchall()
# Для каждого заказа получаем список товаров
orders_with_items = []
for order_row in orders_rows:
order_dict = dict_from_row(order_row)
# Получаем товары для этого заказа
items_rows = conn.execute('''
SELECT oi.*, cat.product_name, cat.article, cat.min_price, cat.category_id,
cat2.category_name
FROM OrderItems oi
JOIN Catalog cat ON oi.product_id = cat.id
LEFT JOIN Categories cat2 ON cat.category_id = cat2.id
WHERE oi.order_id = ?
''', (order_dict['id'],)).fetchall()
order_dict['items'] = list_from_rows(items_rows)
orders_with_items.append(order_dict)
# Считаем общую статистику
total_stats_row = conn.execute('''
SELECT
COUNT(DISTINCT o.id) as total_orders,
COALESCE(SUM(oi.quantity), 0) as total_quantity,
COALESCE(SUM(o.total_amount), 0) as total_amount
FROM Orders o
LEFT JOIN OrderItems oi ON o.id = oi.order_id
''').fetchone()
total_stats = dict_from_row(total_stats_row)
conn.close()
return render_template('orders_list.html',
orders=orders_with_items,
total_stats=total_stats,
clients=clients_list)
# ========== МАРШРУТ ДЛЯ МАТЕРИАЛОВ ==========
@app.route('/materials')
def materials():
conn = get_db_connection()
materials_rows = conn.execute('''
SELECT * FROM Materials
ORDER BY material_name
''').fetchall()
materials_list = list_from_rows(materials_rows)
conn.close()
return render_template('materials.html', materials=materials_list)
# ========== СЛУЖЕБНЫЕ МАРШРУТЫ ==========
@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, 'static'),
'favicon.ico', mimetype='image/vnd.microsoft.icon')
@app.route('/static/<path:filename>')
def static_files(filename):
return send_from_directory(app.root_path + '/static', filename)
if __name__ == '__main__':
app.run(debug=True)