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

653 lines
28 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

import sqlite3
import pandas as pd
import os
import sys
from datetime import datetime
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
RESOURCE_DIR = os.path.join(BASE_DIR, "Resource")
DB_PATH = os.path.join(BASE_DIR, "partners.db")
def create_tables(db_connection):
"""Создает все необходимые таблицы в базе данных"""
cursor = db_connection.cursor()
cursor.executescript('''
-- Типы контрагентов
CREATE TABLE IF NOT EXISTS ContractorType (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type_name VARCHAR(100) NOT NULL UNIQUE
);
-- Контрагенты/Клиенты
CREATE TABLE IF NOT EXISTS Clients (
id INTEGER PRIMARY KEY AUTOINCREMENT,
contractor_type_id INTEGER REFERENCES ContractorType(id),
name VARCHAR(255) NOT NULL,
director VARCHAR(255),
email VARCHAR(255),
phone VARCHAR(50),
address TEXT,
inn VARCHAR(20) UNIQUE,
rating DECIMAL(3,2) DEFAULT 0.0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Категории продукции
CREATE TABLE IF NOT EXISTS Categories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category_name VARCHAR(100) NOT NULL UNIQUE,
coefficient DECIMAL(5,2) NOT NULL DEFAULT 1.0
);
-- Таблица материалов
CREATE TABLE IF NOT EXISTS Materials (
id INTEGER PRIMARY KEY AUTOINCREMENT,
material_name VARCHAR(100) NOT NULL UNIQUE,
description TEXT,
category VARCHAR(50),
color VARCHAR(50),
density DECIMAL(10,2),
thickness DECIMAL(10,2),
supplier VARCHAR(255),
country VARCHAR(100),
wear_class VARCHAR(20),
price_per_unit DECIMAL(15,2),
unit VARCHAR(20) DEFAULT 'шт',
in_stock INTEGER DEFAULT 0,
production_time_days INTEGER DEFAULT 1,
daily_capacity INTEGER DEFAULT 10,
cost_price DECIMAL(15,2),
markup_percent DECIMAL(5,2) DEFAULT 30,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Каталог продукции
CREATE TABLE IF NOT EXISTS Catalog (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category_id INTEGER REFERENCES Categories(id),
material_id INTEGER REFERENCES Materials(id),
product_name VARCHAR(255) NOT NULL,
article VARCHAR(100) UNIQUE NOT NULL,
description TEXT,
min_price DECIMAL(15,2) NOT NULL,
quantity_in_stock INTEGER DEFAULT 0,
production_time_days INTEGER DEFAULT 1,
daily_capacity INTEGER DEFAULT 10,
cost_price DECIMAL(15,2),
profit_per_unit DECIMAL(15,2),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица корзин
CREATE TABLE IF NOT EXISTS Cart (
id INTEGER PRIMARY KEY AUTOINCREMENT,
client_id INTEGER REFERENCES Clients(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(50) DEFAULT 'активна'
);
-- Таблица товаров в корзине
CREATE TABLE IF NOT EXISTS CartItems (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cart_id INTEGER REFERENCES Cart(id),
product_id INTEGER REFERENCES Catalog(id),
quantity INTEGER NOT NULL CHECK (quantity > 0),
price_at_moment DECIMAL(15,2) NOT NULL,
added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Заказы
CREATE TABLE IF NOT EXISTS Orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
client_id INTEGER REFERENCES Clients(id),
order_date DATE NOT NULL,
total_amount DECIMAL(15,2) NOT NULL,
status VARCHAR(50) DEFAULT 'Новый',
production_days INTEGER DEFAULT 1,
production_start_date DATE,
production_end_date DATE,
production_status VARCHAR(50) DEFAULT 'Ожидает',
assembly_percent INTEGER DEFAULT 15,
delivery_percent INTEGER DEFAULT 10,
assembly_cost DECIMAL(15,2) DEFAULT 0,
delivery_cost DECIMAL(15,2) DEFAULT 0,
base_amount DECIMAL(15,2) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Состав заказа
CREATE TABLE IF NOT EXISTS OrderItems (
id INTEGER PRIMARY KEY AUTOINCREMENT,
order_id INTEGER NOT NULL REFERENCES Orders(id),
product_id INTEGER NOT NULL REFERENCES Catalog(id),
quantity INTEGER NOT NULL CHECK (quantity > 0),
price_at_moment DECIMAL(15,2) NOT NULL
);
-- Индексы для оптимизации
CREATE INDEX IF NOT EXISTS idx_client_type ON Clients(contractor_type_id);
CREATE INDEX IF NOT EXISTS idx_client_inn ON Clients(inn);
CREATE INDEX IF NOT EXISTS idx_catalog_category ON Catalog(category_id);
CREATE INDEX IF NOT EXISTS idx_catalog_material ON Catalog(material_id);
CREATE INDEX IF NOT EXISTS idx_catalog_article ON Catalog(article);
CREATE INDEX IF NOT EXISTS idx_material_name ON Materials(material_name);
CREATE INDEX IF NOT EXISTS idx_material_category ON Materials(category);
CREATE INDEX IF NOT EXISTS idx_material_supplier ON Materials(supplier);
CREATE INDEX IF NOT EXISTS idx_cart_client ON Cart(client_id);
CREATE INDEX IF NOT EXISTS idx_cart_status ON Cart(status);
CREATE INDEX IF NOT EXISTS idx_cart_items_cart ON CartItems(cart_id);
CREATE INDEX IF NOT EXISTS idx_order_client ON Orders(client_id);
CREATE INDEX IF NOT EXISTS idx_order_date ON Orders(order_date);
CREATE INDEX IF NOT EXISTS idx_order_status ON Orders(status);
CREATE INDEX IF NOT EXISTS idx_production_status ON Orders(production_status);
CREATE INDEX IF NOT EXISTS idx_orderitems_order ON OrderItems(order_id);
CREATE INDEX IF NOT EXISTS idx_orderitems_product ON OrderItems(product_id);
''')
db_connection.commit()
print("✅ Таблицы успешно созданы")
def calculate_discount(total_quantity):
"""Рассчитывает скидку на основе общего количества заказанной продукции"""
if total_quantity >= 300000:
return 15, '15% (более 300000 ед.)'
elif total_quantity >= 50000:
return 10, '10% (50000-300000 ед.)'
elif total_quantity >= 10000:
return 5, '5% (10000-50000 ед.)'
else:
return 0, '0% (до 10000 ед.)'
def get_clients(db_path=DB_PATH, sort_by='rating', ascending=False):
"""Получает данные о клиентах с возможностью сортировки"""
try:
conn = sqlite3.connect(db_path)
query = """
SELECT
ct.type_name AS "Тип клиента",
c.name AS "Наименование клиента",
c.director AS "Директор",
c.email AS "Электронная почта",
c.phone AS "Телефон",
c.address AS "Адрес",
c.inn AS "ИНН",
c.rating AS "Рейтинг",
c.created_at AS "Дата создания",
COALESCE(SUM(oi.quantity), 0) as total_quantity,
COALESCE(SUM(o.total_amount), 0) as total_amount
FROM Clients c
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
GROUP BY c.id
"""
if sort_by == 'discount':
query += " ORDER BY total_quantity"
elif sort_by == 'rating':
query += " ORDER BY c.rating"
elif sort_by == 'name':
query += " ORDER BY c.name"
elif sort_by == 'type':
query += " ORDER BY ct.type_name, c.name"
else:
query += " ORDER BY c.rating"
query += " DESC" if not ascending else " ASC"
df = pd.read_sql_query(query, conn)
conn.close()
if not df.empty:
df['Скидка_процент'] = df['total_quantity'].apply(lambda x: calculate_discount(x)[0])
df['Скидка_текст'] = df['total_quantity'].apply(lambda x: calculate_discount(x)[1])
df['Общая_сумма'] = df['total_amount'].apply(lambda x: f"{x:,.2f} руб.")
return df
except Exception as e:
print(f"❌ Ошибка: {e}")
return None
def get_orders_history(db_path=DB_PATH, limit=50, sort_by='date_desc'):
"""Получает историю заказов с разными вариантами сортировки"""
try:
conn = sqlite3.connect(db_path)
query = """
SELECT
o.order_date AS "Дата заказа",
c.name AS "Клиент",
GROUP_CONCAT(cat.product_name || ' x' || oi.quantity, ', ') AS "Товары",
SUM(oi.quantity) AS "Количество",
o.total_amount AS "Сумма заказа",
o.status AS "Статус"
FROM Orders o
JOIN Clients c ON o.client_id = c.id
LEFT JOIN OrderItems oi ON o.id = oi.order_id
LEFT JOIN Catalog cat ON oi.product_id = cat.id
GROUP BY o.id
"""
if sort_by == 'date_desc':
query += " ORDER BY o.order_date DESC, o.created_at DESC"
elif sort_by == 'date_asc':
query += " ORDER BY o.order_date ASC, o.created_at ASC"
elif sort_by == 'quantity_desc':
query += " ORDER BY SUM(oi.quantity) DESC"
elif sort_by == 'amount_desc':
query += " ORDER BY o.total_amount DESC"
elif sort_by == 'status':
query += " ORDER BY o.status, o.order_date DESC"
else:
query += " ORDER BY o.order_date DESC, o.created_at DESC"
query += " LIMIT ?"
df = pd.read_sql_query(query, conn, params=(limit,))
conn.close()
return df
except Exception as e:
print(f"❌ Ошибка: {e}")
return None
def print_client_cards(clients_df):
"""Выводит карточки клиентов в красивом формате"""
if clients_df is None or clients_df.empty:
print("📭 Нет данных о клиентах")
return
for index, row in clients_df.iterrows():
print("╔" + "═" * 79 + "╗")
print(f"║ {'КАРТОЧКА КЛИЕНТА':^77} ║")
print("╠" + "═" * 79 + "╣")
type_text = f"Тип: {row['Тип клиента']}"
name_text = f"Наименование: {row['Наименование клиента']}"
director_text = f"Директор: {row['Директор']}"
rating_text = f"Рейтинг: {row['Рейтинг']}"
quantity_text = f"Заказано единиц: {row['total_quantity']:,}"
amount_text = f"На сумму: {row['total_amount']:,.2f} руб."
discount_text = f"Скидка: {row['Скидка_текст']}"
email_text = f"Email: {row['Электронная почта']}"
phone_text = f"Телефон: {row['Телефон']}"
inn_text = f"ИНН: {row['ИНН']}"
address = row['Адрес'] if row['Адрес'] else 'Не указан'
if len(address) > 70:
address = address[:67] + "..."
address_text = f"Адрес: {address}"
print(f"║ {type_text:<77} ║")
print(f"║ {name_text:<77} ║")
print(f"║ {director_text:<77} ║")
print(f"║ {rating_text:<77} ║")
print(f"║ {quantity_text:<77} ║")
print(f"║ {amount_text:<77} ║")
print(f"║ {discount_text:<77} ║")
print(f"║ {'':<77} ║")
print(f"║ {email_text:<77} ║")
print(f"║ {phone_text:<77} ║")
print(f"║ {inn_text:<77} ║")
print(f"║ {address_text:<77} ║")
print("╚" + "═" * 79 + "╝")
print()
def print_orders_cards(orders_df):
"""Выводит карточки заказов в виде таблицы"""
if orders_df is None or orders_df.empty:
print("📭 Нет данных о заказах")
return
print("╔" + "═" * 167 + "╗")
print(f"║ {'ИСТОРИЯ ЗАКАЗОВ':^165} ║")
print("╠" + "═" * 167 + "╣")
headers = ["Дата", "Клиент", "Товары", "Кол-во", "Статус", "Сумма"]
print("║ {:<12} {:<25} {:<55} {:>12} {:<15} {:>15} ║".format(
headers[0], headers[1], headers[2], headers[3], headers[4], headers[5]
))
print("╠" + "═" * 167 + "╣")
for index, row in orders_df.iterrows():
date = str(row['Дата заказа'])[:10]
client = str(row['Клиент'])[:25] if len(str(row['Клиент'])) > 25 else str(row['Клиент'])
products = str(row['Товары'])[:55] if len(str(row['Товары'])) > 55 else str(row['Товары'])
quantity = f"{int(row['Количество']):,}"
status = str(row['Статус'])[:15] if len(str(row['Статус'])) > 15 else str(row['Статус'])
amount = f"{float(row['Сумма заказа']):,.2f}"
line = f"║ {date:<12} {client:<25} {products:<55} {quantity:>12} {status:<15} {amount:>15} ║"
print(line)
print("╚" + "═" * 167 + "╝")
total_quantity = orders_df['Количество'].sum()
total_amount = orders_df['Сумма заказа'].sum()
print(f"📊 ИТОГО: {len(orders_df)} заказов, {total_quantity:,.0f} единиц, общая сумма: {total_amount:,.2f} руб.")
status_stats = orders_df['Статус'].value_counts()
print("📊 Статусы заказов:")
for status, count in status_stats.items():
print(f" - {status}: {count}")
def simple_choice(options):
"""Упрощенная функция выбора"""
print("\n" + "=" * 60)
print("ВЫБЕРИТЕ ОПЦИЮ:")
print("=" * 60)
for i, option in enumerate(options, 1):
print(f"{i}. {option}")
while True:
try:
choice = input(f"\nВведите номер (1-{len(options)}): ").strip()
if choice.isdigit():
choice_num = int(choice)
if 1 <= choice_num <= len(options):
return options[choice_num - 1]
print(f"❌ Пожалуйста, введите число от 1 до {len(options)}")
except KeyboardInterrupt:
print("\n👋 Программа прервана пользователем.")
sys.exit(0)
def safe_float(value, default=None):
"""Безопасное преобразование в float"""
if pd.isna(value) or value == '-':
return default
try:
return float(value)
except (ValueError, TypeError):
return default
def safe_int(value, default=None):
"""Безопасное преобразование в int"""
if pd.isna(value) or value == '-':
return default
try:
return int(float(value))
except (ValueError, TypeError):
return default
def load_data_from_files():
"""Загружает данные из Excel файлов в базу данных"""
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
try:
print("\n📁 Введите имена файлов (или нажмите Enter для значений по умолчанию):")
clients_file = input("Файл с клиентами (Enter = Clients_import.xlsx): ").strip() or "Clients_import.xlsx"
categories_file = input("Файл с категориями (Enter = Categories_import.xlsx): ").strip() or "Categories_import.xlsx"
materials_file = input("Файл с материалами (Enter = Materials_import.xlsx): ").strip() or "Materials_import.xlsx"
catalog_file = input("Файл с каталогом (Enter = Products_import.xlsx): ").strip() or "Products_import.xlsx"
orders_file = input("Файл с заказами (Enter = Orders_import.xlsx): ").strip() or "Orders_import.xlsx"
orderitems_file = input("Файл с составом заказов (Enter = OrderItems_import.xlsx): ").strip() or "OrderItems_import.xlsx"
# Формируем полные пути
clients_file = os.path.join(RESOURCE_DIR, os.path.basename(clients_file))
categories_file = os.path.join(RESOURCE_DIR, os.path.basename(categories_file))
materials_file = os.path.join(RESOURCE_DIR, os.path.basename(materials_file))
catalog_file = os.path.join(RESOURCE_DIR, os.path.basename(catalog_file))
orders_file = os.path.join(RESOURCE_DIR, os.path.basename(orders_file))
orderitems_file = os.path.join(RESOURCE_DIR, os.path.basename(orderitems_file))
print(f"\n📂 Загружаем файлы из папки: {RESOURCE_DIR}")
# 1. Загрузка типов контрагентов
print("\n1. 📊 Загрузка типов контрагентов...")
clients_df = pd.read_excel(clients_file)
if 'Тип партнера' in clients_df.columns:
contractor_types = clients_df['Тип партнера'].unique()
for contractor_type in contractor_types:
cursor.execute("INSERT OR IGNORE INTO ContractorType (type_name) VALUES (?)", (contractor_type,))
print(f" Загружено {len(contractor_types)} типов")
# 2. Загрузка клиентов
print("2. 👥 Загрузка клиентов...")
loaded_clients = 0
for _, row in clients_df.iterrows():
type_value = row.get('Тип партнера', 'Клиент')
cursor.execute("SELECT id FROM ContractorType WHERE type_name = ?", (type_value,))
result = cursor.fetchone()
contractor_type_id = result[0] if result else 1
cursor.execute("""INSERT OR IGNORE INTO Clients
(contractor_type_id, name, director, email, phone, address, inn, rating)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
(contractor_type_id,
row.get('Наименование партнера', ''),
row.get('Директор', ''),
row.get('Электронная почта партнера', ''),
row.get('Телефон партнера', ''),
row.get('Юридический адрес партнера', ''),
row.get('ИНН', ''),
safe_float(row.get('Рейтинг', 0.0), 0.0))
)
loaded_clients += 1
print(f" Загружено {loaded_clients} клиентов")
# 3. Загрузка категорий
print("3. 📦 Загрузка категорий...")
categories_df = pd.read_excel(categories_file)
loaded_categories = 0
for _, row in categories_df.iterrows():
cursor.execute("INSERT OR IGNORE INTO Categories (category_name, coefficient) VALUES (?, ?)",
(row.get('Тип продукции', ''),
safe_float(row.get('Коэффициент типа продукции', 1.0), 1.0))
)
loaded_categories += 1
print(f" Загружено {loaded_categories} категорий")
# 4. Загрузка материалов
print("4. 📦 Загрузка материалов...")
materials_df = pd.read_excel(materials_file)
loaded_materials = 0
for _, row in materials_df.iterrows():
cursor.execute("""
INSERT OR IGNORE INTO Materials
(material_name, description, category, color, density, thickness,
supplier, country, wear_class, price_per_unit, unit, in_stock,
production_time_days, daily_capacity, markup_percent)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
row.get('Наименование материала', ''),
row.get('Описание', ''),
row.get('Категория', ''),
row.get('Цвет', ''),
safe_float(row.get('Плотность', None)),
safe_float(row.get('Толщина', None)),
row.get('Поставщик', ''),
row.get('Страна', ''),
row.get('Класс износостойкости', ''),
safe_float(row.get('Цена за ед.', 0), 0),
row.get('Единица', 'шт'),
safe_int(row.get('В наличии', 0), 0),
1, 10, 30
))
loaded_materials += 1
print(f" ✅ Загружено {loaded_materials} материалов")
# 5. Загрузка каталога
print("5. 🏷️ Загрузка каталога продукции...")
catalog_df = pd.read_excel(catalog_file)
loaded_products = 0
for index, row in catalog_df.iterrows():
prod_days = 1
if 'production_time_days' in catalog_df.columns:
val = row['production_time_days']
if not pd.isna(val):
try:
prod_days = int(float(val))
except:
prod_days = 1
cursor.execute("""
INSERT OR IGNORE INTO Catalog
(category_id, material_id, product_name, article, description, min_price, quantity_in_stock,
production_time_days, daily_capacity)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
safe_int(row.get('category_id', 1), 1),
safe_int(row.get('material_id', None)),
row.get('product_name', ''),
row.get('article', ''),
row.get('description', ''),
safe_float(row.get('min_price', 0), 0),
safe_int(row.get('quantity_in_stock', 0), 0),
prod_days,
10
))
loaded_products += 1
print(f" ✅ Загружено {loaded_products} товаров")
# 6. Загрузка заказов
print("6. 📝 Загрузка заказов...")
orders_df = pd.read_excel(orders_file)
loaded_orders = 0
for _, row in orders_df.iterrows():
# Преобразование дат
date_val = row.get('order_date')
if pd.isna(date_val):
order_date = datetime.now().strftime('%Y-%m-%d')
else:
if hasattr(date_val, 'strftime'):
order_date = date_val.strftime('%Y-%m-%d')
else:
order_date = str(date_val)
prod_start = row.get('production_start_date')
if pd.isna(prod_start):
prod_start = None
else:
if hasattr(prod_start, 'strftime'):
prod_start = prod_start.strftime('%Y-%m-%d')
else:
prod_start = str(prod_start)
prod_end = row.get('production_end_date')
if pd.isna(prod_end):
prod_end = None
else:
if hasattr(prod_end, 'strftime'):
prod_end = prod_end.strftime('%Y-%m-%d')
else:
prod_end = str(prod_end)
cursor.execute("""
INSERT INTO Orders
(id, 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
safe_int(row.get('id')),
safe_int(row.get('client_id')),
order_date,
safe_float(row.get('total_amount'), 0),
row.get('status', 'Новый'),
safe_int(row.get('production_days', 1)),
prod_start,
prod_end,
row.get('production_status', 'Ожидает'),
safe_int(row.get('assembly_percent', 15)),
safe_int(row.get('delivery_percent', 10)),
safe_float(row.get('assembly_cost', 0), 0),
safe_float(row.get('delivery_cost', 0), 0),
safe_float(row.get('base_amount', 0), 0)
))
loaded_orders += 1
print(f" ✅ Загружено {loaded_orders} заказов")
# 7. Загрузка состава заказов (OrderItems)
print("7. 📦 Загрузка состава заказов...")
orderitems_df = pd.read_excel(orderitems_file)
loaded_items = 0
for _, row in orderitems_df.iterrows():
cursor.execute("""
INSERT INTO OrderItems (order_id, product_id, quantity, price_at_moment)
VALUES (?, ?, ?, ?)
""", (
safe_int(row.get('order_id')),
safe_int(row.get('product_id')),
safe_int(row.get('quantity'), 1),
safe_float(row.get('price_at_moment'), 0)
))
loaded_items += 1
print(f" ✅ Загружено {loaded_items} позиций")
conn.commit()
print(f"✅ Данные успешно загружены!")
except Exception as e:
print(f"❌ Ошибка при загрузке данных: {e}")
import traceback
traceback.print_exc()
conn.rollback()
finally:
conn.close()
def display_menu():
"""Главное меню программы"""
menu_options = [
'КАРТОЧКИ КЛИЕНТОВ (сортировка по рейтингу)',
'КАРТОЧКИ КЛИЕНТОВ (сортировка по скидкам)',
'ИСТОРИЯ ЗАКАЗОВ',
'ЗАПОЛНЕНИЕ БД из файлов',
'ВЫХОД'
]
while True:
choice = simple_choice(menu_options)
if choice == 'КАРТОЧКИ КЛИЕНТОВ (сортировка по рейтингу)':
print("\n🎯 КАРТОЧКИ КЛИЕНТОВ (сортировка по рейтингу)")
print("═" * 80)
clients = get_clients(sort_by='rating', ascending=False)
print_client_cards(clients)
elif choice == 'КАРТОЧКИ КЛИЕНТОВ (сортировка по скидкам)':
print("\n📊 КАРТОЧКИ КЛИЕНТОВ (сортировка по скидкам)")
print("═" * 80)
clients = get_clients(sort_by='discount', ascending=False)
print_client_cards(clients)
elif choice == 'ИСТОРИЯ ЗАКАЗОВ':
print("\n📈 ИСТОРИЯ ЗАКАЗОВ")
print("═" * 80)
orders = get_orders_history(limit=50)
print_orders_cards(orders)
elif choice == 'ЗАПОЛНЕНИЕ БД из файлов':
if os.path.exists(DB_PATH):
os.remove(DB_PATH)
print("🗑️ База данных удалена")
else:
print("ℹ️ Создаем новую базу")
conn = sqlite3.connect(DB_PATH)
create_tables(conn)
conn.close()
load_data_from_files()
elif choice == 'ВЫХОД':
print("\n👋 До свидания!")
break
if __name__ == "__main__":
display_menu()