From 99edd3938fde86a2bc6526cdc16110d7a2ccd201 Mon Sep 17 00:00:00 2001 From: user_2i Date: Wed, 18 Mar 2026 13:45:40 +0500 Subject: [PATCH] 18.03.2026 --- Catalog_import.xlsx | Bin 0 -> 9393 bytes Categories_import.xlsx | Bin 0 -> 10064 bytes Clients_import.xlsx | Bin 0 -> 10067 bytes Materials_import.xlsx | Bin 0 -> 10823 bytes OrderItems.xlsx | Bin 0 -> 9656 bytes Orders_import.xlsx | Bin 0 -> 9811 bytes Products_import.xlsx | Bin 0 -> 9919 bytes Resource/Catalog_import.xlsx | Bin 0 -> 9393 bytes Resource/Categories_import.xlsx | Bin 0 -> 10064 bytes Resource/Clients_import.xlsx | Bin 0 -> 10067 bytes Resource/Materials_import.xlsx | Bin 0 -> 10823 bytes Resource/OrderItems.xlsx | Bin 0 -> 9656 bytes Resource/Orders_import.xlsx | Bin 0 -> 9811 bytes Resource/Products_import.xlsx | Bin 0 -> 9919 bytes Resource/favicon.png | Bin 0 -> 7049 bytes main.py | 588 +++++++++++++++ main_flask.py | 999 +++++++++++++++++++++++++ materials.db | Bin 0 -> 131072 bytes static/css/style.css | 470 ++++++++++++ static/favicon.png | Bin 0 -> 7049 bytes static/js/script.js | 37 + templates/about.html | 18 + templates/add_client.html | 521 +++++++++++++ templates/add_order.html | 737 ++++++++++++++++++ templates/add_product.html | 458 ++++++++++++ templates/base.html | 686 +++++++++++++++++ templates/cart_new.html | 731 ++++++++++++++++++ templates/catalog.html | 868 +++++++++++++++++++++ templates/components/header.html | 8 + templates/components/partner_card.html | 249 ++++++ templates/edit_client.html | 815 ++++++++++++++++++++ templates/edit_product.html | 454 +++++++++++ templates/home.html | 16 + templates/index.html | 547 ++++++++++++++ templates/materials.html | 266 +++++++ templates/order_history.html | 522 +++++++++++++ templates/orders_list.html | 410 ++++++++++ 37 files changed, 9400 insertions(+) create mode 100644 Catalog_import.xlsx create mode 100644 Categories_import.xlsx create mode 100644 Clients_import.xlsx create mode 100644 Materials_import.xlsx create mode 100644 OrderItems.xlsx create mode 100644 Orders_import.xlsx create mode 100644 Products_import.xlsx create mode 100644 Resource/Catalog_import.xlsx create mode 100644 Resource/Categories_import.xlsx create mode 100644 Resource/Clients_import.xlsx create mode 100644 Resource/Materials_import.xlsx create mode 100644 Resource/OrderItems.xlsx create mode 100644 Resource/Orders_import.xlsx create mode 100644 Resource/Products_import.xlsx create mode 100644 Resource/favicon.png create mode 100644 main.py create mode 100644 main_flask.py create mode 100644 materials.db create mode 100644 static/css/style.css create mode 100644 static/favicon.png create mode 100644 static/js/script.js create mode 100644 templates/about.html create mode 100644 templates/add_client.html create mode 100644 templates/add_order.html create mode 100644 templates/add_product.html create mode 100644 templates/base.html create mode 100644 templates/cart_new.html create mode 100644 templates/catalog.html create mode 100644 templates/components/header.html create mode 100644 templates/components/partner_card.html create mode 100644 templates/edit_client.html create mode 100644 templates/edit_product.html create mode 100644 templates/home.html create mode 100644 templates/index.html create mode 100644 templates/materials.html create mode 100644 templates/order_history.html create mode 100644 templates/orders_list.html diff --git a/Catalog_import.xlsx b/Catalog_import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5b09b945a2862283cd2dcee9905538079347a8a8 GIT binary patch literal 9393 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 literal 0 HcmV?d00001 diff --git a/Materials_import.xlsx b/Materials_import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0c403738bb557d39dbea47f07009bdd059f0ad2c GIT binary patch literal 10823 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 Ty8r+(NcdGCEQ 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 V0T%Lf0RSY(FAyTT6qLXH`#(?75T*bC literal 0 HcmV?d00001 diff --git a/Orders_import.xlsx b/Orders_import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4c54efcf4f678a4a42b96110f3c5b02605145f0e GIT binary patch literal 9811 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 QsL)R^bZ*y1^Yh#P0ZKq2t^fc4 literal 0 HcmV?d00001 diff --git a/Products_import.xlsx b/Products_import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3ea8c7641bfe45fe38d0f4f1fe745539da7f3a6e GIT binary patch literal 9919 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 literal 0 HcmV?d00001 diff --git a/Resource/Materials_import.xlsx b/Resource/Materials_import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0c403738bb557d39dbea47f07009bdd059f0ad2c GIT binary patch literal 10823 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 Ty8r+(NcdGCEQ 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 V0T%Lf0RSY(FAyTT6qLXH`#(?75T*bC literal 0 HcmV?d00001 diff --git a/Resource/Orders_import.xlsx b/Resource/Orders_import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4c54efcf4f678a4a42b96110f3c5b02605145f0e GIT binary patch literal 9811 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 QsL)R^bZ*y1^Yh#P0ZKq2t^fc4 literal 0 HcmV?d00001 diff --git a/Resource/Products_import.xlsx b/Resource/Products_import.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3ea8c7641bfe45fe38d0f4f1fe745539da7f3a6e GIT binary patch literal 9919 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 literal 0 HcmV?d00001 diff --git a/main.py b/main.py new file mode 100644 index 0000000..8d3b487 --- /dev/null +++ b/main.py @@ -0,0 +1,588 @@ +import openpyxl # Добавь это +openpyxl.__version__ = "3.1.5" # И это +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") +# ========== ИЗМЕНЕНО: partners.db -> materials.db ========== +DB_PATH = os.path.join(BASE_DIR, "materials.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, + 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, + 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 + ); + + -- ========== НОВАЯ СТРУКТУРА ЗАКАЗОВ ========== + + -- Заказы (без product_id и quantity) + CREATE TABLE IF NOT EXISTS Orders ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + client_id INTEGER NOT NULL REFERENCES Clients(id), + order_date DATE NOT NULL, + total_amount DECIMAL(15,2) NOT NULL DEFAULT 0, + status VARCHAR(50) DEFAULT 'Новый', + discount_percent INTEGER DEFAULT 0, + notes TEXT, + 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) ON DELETE CASCADE, + product_id INTEGER NOT NULL REFERENCES Catalog(id), + quantity INTEGER NOT NULL CHECK (quantity > 0), + price_at_moment DECIMAL(15,2) NOT NULL, + transport_cost DECIMAL(15,2) DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + + -- Индексы для оптимизации + 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_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_orderitems_order ON OrderItems(order_id); + CREATE INDEX IF NOT EXISTS idx_orderitems_product ON OrderItems(product_id); + ''') + + db_connection.commit() + print("✅ Таблицы успешно созданы (новая структура с OrderItems)") + + +def calculate_discount(total_amount): + """Рассчитывает скидку на основе общей суммы заказов""" + if total_amount >= 500000: + return 20 + elif total_amount >= 300000: + return 15 + elif total_amount >= 150000: + return 10 + return 0 + + +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(o.total_amount), 0) as total_amount, + COUNT(DISTINCT o.id) as orders_count + FROM Clients c + JOIN ContractorType ct ON c.contractor_type_id = ct.id + LEFT JOIN Orders o ON c.id = o.client_id + GROUP BY c.id + """ + + if sort_by == 'discount': + query += " ORDER BY total_amount" + 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_amount'].apply(calculate_discount) + df['Скидка_текст'] = df['Скидка_процент'].apply(lambda x: f'{x}%') + 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 "Клиент", + COUNT(oi.id) AS "Кол-во позиций", + o.total_amount AS "Сумма заказа", + o.status AS "Статус", + o.discount_percent AS "Скидка", + GROUP_CONCAT(cat.product_name, ', ') 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 == 'amount_desc': + query += " ORDER BY o.total_amount 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 + "╣") + + print(f"║ Тип: {row['Тип клиента']:<70} ║") + print(f"║ Наименование: {row['Наименование клиента']:<63} ║") + print(f"║ Директор: {row['Директор']:<68} ║") + print(f"║ Рейтинг: {row['Рейтинг']:<69} ║") + print(f"║ Заказов: {row['orders_count']:<69} ║") + print(f"║ Сумма заказов: {row['total_amount']:,.2f} руб. ║") + print(f"║ Скидка: {row['Скидка_текст']:<70} ║") + print(f"║ {'':<77} ║") + print(f"║ Email: {row['Электронная почта']:<70} ║") + print(f"║ Телефон: {row['Телефон']:<69} ║") + print(f"║ ИНН: {row['ИНН']:<73} ║") + + address = row['Адрес'] if row['Адрес'] else 'Не указан' + if len(address) > 70: + address = address[:67] + "..." + print(f"║ Адрес: {address:<70} ║") + print("╚" + "═" * 79 + "╝") + print() + + +def print_orders_cards(orders_df): + """Выводит карточки заказов""" + if orders_df is None or orders_df.empty: + print("📭 Нет данных о заказах") + return + + print("╔" + "═" * 120 + "╗") + print(f"║ {'ИСТОРИЯ ЗАКАЗОВ':^118} ║") + print("╠" + "═" * 120 + "╣") + + for index, row in orders_df.iterrows(): + date = str(row['Дата заказа'])[:10] + client = row['Клиент'][:20] if len(row['Клиент']) > 20 else row['Клиент'] + items = row['Кол-во позиций'] + amount = f"{row['Сумма заказа']:,.2f}" + status = row['Статус'] + discount = f"{row['Скидка']}%" + products = row['Товары'][:50] if row['Товары'] else '-' + + print(f"║ {date} | {client:<20} | Позиций: {items:2} | Скидка: {discount:3} | {amount:>15} руб. | {status} ║") + print(f"║ Товары: {products:<106} ║") + print("╠" + "═" * 120 + "╣") + + total_amount = orders_df['Сумма заказа'].sum() + print(f"║ {'ИТОГО:':<20} {len(orders_df)} заказов, общая сумма: {total_amount:,.2f} руб. {'':>30} ║") + print("╚" + "═" * 120 + "╝") + + +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 (ValueError, EOFError): + print("❌ Неверный ввод. Попробуйте еще раз.") + except KeyboardInterrupt: + print("\n👋 Программа прервана пользователем.") + sys.exit(0) + + +def check_database(): + """Проверяет загруженные данные в базе""" + conn = sqlite3.connect(DB_PATH) + try: + cursor = conn.cursor() + print("\n🔍 Проверка загруженных данных:") + tables = ['ContractorType', 'Clients', 'Categories', 'Materials', 'Catalog', 'Cart', 'CartItems', 'Orders', 'OrderItems'] + for table in tables: + cursor.execute(f"SELECT COUNT(*) FROM {table}") + count = cursor.fetchone()[0] + print(f" {table}: {count} записей") + finally: + conn.close() + + +def load_data_from_files(): + """Загружает данные из Excel файлов в базу данных""" + conn = sqlite3.connect(DB_PATH) + cursor = conn.cursor() + + try: + print("\n📁 Введите имена файлов:") + 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" + + # Формируем пути + 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)) + + # 1. Загрузка типов контрагентов + print("\n1. 📊 Загрузка типов контрагентов...") + clients_df = pd.read_excel(clients_file) + + type_column = 'Тип партнера' + if type_column in clients_df.columns: + contractor_types = clients_df[type_column].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('Юридический адрес партнера', ''), + str(row.get('ИНН', '')), + float(row.get('Рейтинг', 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('Тип продукции', ''), + float(row.get('Коэффициент типа продукции', 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) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """, ( + row.get('Наименование материала', ''), + row.get('Описание', ''), + row.get('Категория', ''), + row.get('Цвет', ''), + row.get('Плотность', None), + row.get('Толщина', None), + row.get('Поставщик', ''), + row.get('Страна', ''), + row.get('Класс прочности', ''), + float(row.get('Цена за ед.', 0)), + row.get('Единица', 'шт'), + int(row.get('В наличии', 0)) + )) + loaded_materials += 1 + print(f" ✅ Загружено {loaded_materials} материалов") + + # 5. Загрузка каталога + print("5. 🏷️ Загрузка каталога...") + catalog_df = pd.read_excel(catalog_file) + loaded_products = 0 + for _, row in catalog_df.iterrows(): + cursor.execute(""" + INSERT OR IGNORE INTO Catalog + (category_id, material_id, product_name, article, description, min_price, quantity_in_stock) + VALUES (?, ?, ?, ?, ?, ?, ?) + """, ( + int(row.get('category_id', 1)), + int(row.get('material_id')) if pd.notna(row.get('material_id')) else None, + row.get('product_name', ''), + str(row.get('article', '')), + row.get('description', ''), + float(row.get('min_price', 0)), + int(row.get('quantity_in_stock', 0)) + )) + loaded_products += 1 + print(f" ✅ Загружено {loaded_products} товаров") + + # 6. Загрузка заказов + print("6. 📝 Загрузка заказов...") + + # Получаем соответствие товаров + products_dict = {} + cursor.execute("SELECT id, product_name, article, min_price FROM Catalog") + for row in cursor.fetchall(): + products_dict[row[1]] = {'id': row[0], 'price': row[3]} + + # Получаем соответствие поставщиков + suppliers_dict = {} + cursor.execute("SELECT id, name FROM Clients") + for row in cursor.fetchall(): + suppliers_dict[row[1]] = row[0] + + # Читаем заказы + orders_df = pd.read_excel(orders_file) + + # Группируем заказы + order_groups = {} + for _, row in orders_df.iterrows(): + supplier_name = row.get('Наименование партнера', '') + date = pd.to_datetime(row.get('Дата', datetime.now())).strftime('%Y-%m-%d') + key = f"{supplier_name}_{date}" + + if key not in order_groups: + order_groups[key] = { + 'supplier_id': suppliers_dict.get(supplier_name), + 'date': date, + 'items': [] + } + + product_name = row.get('Продукция', '') + quantity = int(row.get('Количество', 1)) + + if product_name in products_dict: + order_groups[key]['items'].append({ + 'product_id': products_dict[product_name]['id'], + 'quantity': quantity, + 'price': products_dict[product_name]['price'] + }) + + # Создаем заказы + orders_count = 0 + items_count = 0 + + for key, data in order_groups.items(): + if not data['supplier_id'] or not data['items']: + continue + + # Считаем сумму + total = 0 + for item in data['items']: + total += item['quantity'] * item['price'] * 1.1 + + # Создаем заказ + cursor.execute(''' + INSERT INTO Orders (client_id, order_date, total_amount, status) + VALUES (?, ?, ?, ?) + ''', (data['supplier_id'], data['date'], total, 'Выполнен')) + + order_id = cursor.lastrowid + orders_count += 1 + + # Создаем позиции + for item in data['items']: + transport = item['quantity'] * item['price'] * 0.1 + cursor.execute(''' + INSERT INTO OrderItems (order_id, product_id, quantity, price_at_moment, transport_cost) + VALUES (?, ?, ?, ?, ?) + ''', (order_id, item['product_id'], item['quantity'], item['price'], transport)) + items_count += 1 + + conn.commit() + print(f" ✅ Загружено {orders_count} заказов и {items_count} позиций") + + check_database() + + 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🎯 КАРТОЧКИ КЛИЕНТОВ (сортировка по рейтингу)") + clients = get_clients(sort_by='rating', ascending=False) + print_client_cards(clients) + + elif choice == 'КАРТОЧКИ КЛИЕНТОВ (сортировка по скидкам)': + print("\n📊 КАРТОЧКИ КЛИЕНТОВ (сортировка по скидкам)") + clients = get_clients(sort_by='discount', ascending=False) + print_client_cards(clients) + + elif choice == 'ИСТОРИЯ ЗАКАЗОВ': + print("\n📈 ИСТОРИЯ ЗАКАЗОВ") + orders = get_orders_history(limit=50) + print_orders_cards(orders) + + elif choice == 'ЗАПОЛНЕНИЕ БД из файлов': + if os.path.exists(DB_PATH): + os.remove(DB_PATH) + print("🗑️ База данных materials.db удалена") + 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() \ No newline at end of file diff --git a/main_flask.py b/main_flask.py new file mode 100644 index 0000000..051d9ad --- /dev/null +++ b/main_flask.py @@ -0,0 +1,999 @@ +from flask import Flask, render_template, send_from_directory, request, redirect, url_for, flash, session +import sqlite3 +import os +from datetime import datetime + +app = Flask(__name__) +app.secret_key = 'my_secret_key_12345' + +# ========== ПОДКЛЮЧЕНИЕ К БАЗЕ ДАННЫХ ========== +def get_db_connection(): + conn = sqlite3.connect('materials.db') + conn.row_factory = sqlite3.Row + return conn + +# ========== ФУНКЦИИ РАСЧЕТА СКИДОК И СТОИМОСТИ ========== + +def calculate_supplier_discount(supplier_id, year): + """Расчет накопительной скидки поставщика за год (по сумме заказов)""" + conn = get_db_connection() + + # Получаем все заказы поставщика за указанный год + orders = conn.execute(''' + SELECT total_amount FROM Orders + WHERE client_id = ? AND strftime('%Y', order_date) = ? + ''', (supplier_id, str(year))).fetchall() + + conn.close() + + total_year = sum(order['total_amount'] for order in orders) + + if total_year >= 500000: + return 20 + elif total_year >= 300000: + return 15 + elif total_year >= 150000: + return 10 + return 0 + +def calculate_order_total_with_transport(items): + """Расчет общей суммы заказа с транспортными расходами (10%)""" + total = 0 + for item in items: + total += item['quantity'] * item['price'] * 1.1 + return round(total, 2) + +# ========== ГЛАВНАЯ СТРАНИЦА (ПОСТАВЩИКИ) ========== + +@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, + 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 + 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" + + # Выполняем запрос + clients = conn.execute(sql, params).fetchall() + + # Добавляем информацию о скидке на основе суммы + clients_with_discount = [] + for client in clients: + total_amount = client['total_amount'] or 0 + + # Рассчитываем текущую скидку на основе истории заказов + current_discount = calculate_supplier_discount(client['id'], datetime.now().year) + + client_dict = dict(client) + client_dict['total_amount'] = total_amount + client_dict['total_sales'] = total_amount + client_dict['orders_count'] = client['orders_count'] or 0 + client_dict['discount_percent'] = current_discount + client_dict['discount'] = current_discount + client_dict['discount_text'] = f'{current_discount}%' + + clients_with_discount.append(client_dict) + + conn.close() + + return render_template('index.html', + partners=clients_with_discount, + total_count=total_count) + + except sqlite3.OperationalError as e: + conn.close() + 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/', 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 = 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() + + contractor_types = conn.execute('SELECT * FROM ContractorType ORDER BY type_name').fetchall() + conn.close() + + if not client: + flash('Клиент не найден', 'error') + return redirect(url_for('index')) + + return render_template('edit_client.html', client=client, contractor_types=contractor_types) + +# ========== МАРШРУТЫ ДЛЯ ЗАКАЗОВ ========== + +@app.route('/order_history/') +def order_history(client_id): + conn = get_db_connection() + + client = 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() + + if not client: + conn.close() + flash('Клиент не найден', 'error') + return redirect(url_for('index')) + + # Получаем все заказы + orders = 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 = [] + + for order in orders: + order_dict = dict(order) + + # Получаем позиции для заказа + items = conn.execute(''' + SELECT oi.*, cat.product_name, cat.article, + cat2.category_name, m.material_name + FROM OrderItems oi + JOIN Catalog cat ON oi.product_id = cat.id + LEFT JOIN Categories cat2 ON cat.category_id = cat2.id + LEFT JOIN Materials m ON cat.material_id = m.id + WHERE oi.order_id = ? + ''', (order['id'],)).fetchall() + + # Рассчитываем базовую стоимость (сумма quantity * price_at_moment) + base_amount = 0 + items_list = [] + + for item in items: + item_dict = dict(item) + # Рассчитываем стоимость позиции + item_total = item_dict['quantity'] * item_dict['price_at_moment'] + item_dict['item_total'] = item_total + base_amount += item_total + items_list.append(item_dict) + + # Транспортные расходы (10% от базовой стоимости) + shipping_cost = base_amount * 0.1 + + # Получаем скидку клиента + try: + if order_dict['order_date']: + order_year = datetime.strptime(order_dict['order_date'], '%Y-%m-%d').year + else: + order_year = datetime.now().year + except: + order_year = datetime.now().year + + discount = calculate_supplier_discount(client_id, order_year) + + # Рассчитываем итоговую стоимость с учётом скидки + total_with_shipping = base_amount + shipping_cost + total_amount_calculated = total_with_shipping * (1 - discount / 100) if discount > 0 else total_with_shipping + + # Добавляем рассчитанные поля в словарь заказа + order_dict['base_amount'] = base_amount + order_dict['shipping_cost'] = shipping_cost + order_dict['discount'] = discount + order_dict['total_amount_calculated'] = total_amount_calculated + order_dict['display_total'] = order_dict.get('total_amount', total_amount_calculated) + order_dict['order_items'] = items_list + order_dict['items_count'] = len(items_list) + + orders_with_items.append(order_dict) + + # Считаем общую статистику + total_stats = conn.execute(''' + SELECT + COUNT(DISTINCT o.id) as total_orders, + SUM(o.total_amount) as total_amount, + SUM(CASE WHEN o.status = 'Выполнен' THEN 1 ELSE 0 END) as completed_orders, + COALESCE(SUM(oi.quantity), 0) as total_quantity + FROM Orders o + LEFT JOIN OrderItems oi ON o.id = oi.order_id + WHERE o.client_id = ? + ''', (client_id,)).fetchone() + + conn.close() + + return render_template('order_history.html', + client=client, + orders=orders_with_items, + total_stats=total_stats) + +@app.route('/update_order_status/', 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('/add_order/', methods=['GET', 'POST']) +def add_order(client_id): + if request.method == 'POST': + try: + order_date = request.form['order_date'] + status = request.form.get('status', 'Новый') + + conn = get_db_connection() + + # Проверяем наличие таблицы OrderItems + cursor = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='OrderItems'") + has_orderitems = cursor.fetchone() is not None + + if has_orderitems: + # Новая структура + cursor = conn.execute(''' + INSERT INTO Orders (client_id, order_date, status, total_amount) + VALUES (?, ?, ?, 0) + ''', (client_id, order_date, status)) + + order_id = cursor.lastrowid + + # Получаем позиции из формы + product_ids = request.form.getlist('product_id[]') + quantities = request.form.getlist('quantity[]') + + total = 0 + + for i in range(len(product_ids)): + if product_ids[i] and quantities[i]: + product_id = int(product_ids[i]) + quantity = int(quantities[i]) + + # Получаем цену товара + product = conn.execute('SELECT min_price FROM Catalog WHERE id = ?', (product_id,)).fetchone() + + if product: + price = product['min_price'] + + # Добавляем позицию + conn.execute(''' + INSERT INTO OrderItems (order_id, product_id, quantity, price_at_moment) + VALUES (?, ?, ?, ?) + ''', (order_id, product_id, quantity, price)) + + # Считаем сумму с транспортными расходами + total += quantity * price * 1.1 + + # Рассчитываем скидку + year = datetime.strptime(order_date, '%Y-%m-%d').year + discount = calculate_supplier_discount(client_id, year) + + # Применяем скидку + total_with_discount = total * (1 - discount/100) + + # Обновляем сумму заказа + conn.execute('UPDATE Orders SET total_amount = ? WHERE id = ?', (total_with_discount, order_id)) + + discount_msg = f' Применена накопительная скидка {discount}% (экономия {total * discount/100:.2f} руб.)' if discount > 0 else '' + + else: + # Старая структура (для совместимости) + product_id = request.form.get('product_id') + quantity = int(request.form.get('quantity', 1)) + + product = conn.execute('SELECT min_price FROM Catalog WHERE id = ?', (product_id,)).fetchone() + + if not product: + flash('Товар не найден', 'error') + return redirect(url_for('add_order', client_id=client_id)) + + base_amount = product['min_price'] * quantity + total_amount = base_amount * 1.1 # с транспортом + + cursor = conn.execute(''' + INSERT INTO Orders (client_id, product_id, quantity, order_date, total_amount, status) + VALUES (?, ?, ?, ?, ?, ?) + ''', (client_id, product_id, quantity, order_date, total_amount, status)) + + order_id = cursor.lastrowid + discount_msg = '' + + conn.commit() + conn.close() + + flash(f'Заказ успешно добавлен!{discount_msg}', 'success') + return redirect(url_for('order_history', client_id=client_id)) + + except Exception as e: + flash(f'Ошибка при добавлении заказа: {str(e)}', 'error') + return redirect(url_for('add_order', client_id=client_id)) + + # GET запрос + conn = get_db_connection() + + client = 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() + + products = 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 + ORDER BY c.category_name, cat.product_name + ''').fetchall() + + conn.close() + + if not client: + flash('Клиент не найден', 'error') + return redirect(url_for('index')) + + today = datetime.now().strftime('%Y-%m-%d') + + return render_template('add_order.html', client=client, products=products, today=today) + +@app.route('/orders_list') +def orders_list(): + """Список всех заказов""" + conn = get_db_connection() + + # Получаем всех клиентов для выпадающего списка + clients = conn.execute(''' + SELECT id, name FROM Clients ORDER BY name + ''').fetchall() + + # Проверяем наличие таблицы OrderItems + cursor = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='OrderItems'") + has_orderitems = cursor.fetchone() is not None + + if has_orderitems: + # Новая структура + orders = conn.execute(''' + SELECT + o.id, + o.client_id, + o.order_date, + o.total_amount, + o.status, + c.name as client_name, + c.inn as client_inn, + COUNT(oi.id) as items_count, + SUM(oi.quantity) as total_quantity, + GROUP_CONCAT(cat.product_name, ', ') as products_list + FROM Orders o + LEFT 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 + ORDER BY o.order_date DESC, o.id DESC + LIMIT 100 + ''').fetchall() + + # Считаем общую статистику + total_stats = conn.execute(''' + SELECT + COUNT(*) as total_orders, + SUM(o.total_amount) as total_amount, + SUM(CASE WHEN o.status = 'Выполнен' THEN 1 ELSE 0 END) as completed_orders + FROM Orders o + ''').fetchone() + + else: + # Старая структура (с product_id и quantity в Orders) + orders = conn.execute(''' + SELECT + o.id, + o.client_id, + o.order_date, + o.total_amount, + o.status, + o.quantity, + c.name as client_name, + c.inn as client_inn, + cat.product_name, + cat.article, + cat2.category_name + FROM Orders o + LEFT JOIN Clients c ON o.client_id = c.id + LEFT JOIN Catalog cat ON o.product_id = cat.id + LEFT JOIN Categories cat2 ON cat.category_id = cat2.id + ORDER BY o.order_date DESC, o.id DESC + LIMIT 100 + ''').fetchall() + + # Считаем общую статистику + total_stats = conn.execute(''' + SELECT + COUNT(*) as total_orders, + SUM(quantity) as total_quantity, + SUM(total_amount) as total_amount, + SUM(CASE WHEN status = 'Выполнен' THEN 1 ELSE 0 END) as completed_orders + FROM Orders + ''').fetchone() + + conn.close() + + return render_template('orders_list.html', orders=orders, total_stats=total_stats, clients=clients, has_orderitems=has_orderitems) + +# ========== МАРШРУТ ДЛЯ КАТАЛОГА ========== + +@app.route('/catalog') +def catalog(): + conn = get_db_connection() + + # Получаем список всех категорий для фильтра + categories = conn.execute('SELECT * FROM Categories ORDER BY category_name').fetchall() + + # Получаем список всех поставщиков для фильтра + suppliers = conn.execute('SELECT id, name FROM Clients ORDER BY name').fetchall() + + # Получаем параметры фильтрации из URL + search_query = request.args.get('search', '') + category_id = request.args.get('category', 'all') + supplier_id = request.args.get('supplier', 'all') + sort_by = request.args.get('sort', 'name_asc') + + # Базовый SQL запрос с добавлением поставщика + sql = ''' + SELECT cat.*, c.category_name, m.material_name, m.color, + cl.name as supplier_name, cl.id as supplier_id + FROM Catalog cat + LEFT JOIN Categories c ON cat.category_id = c.id + LEFT JOIN Materials m ON cat.material_id = m.id + LEFT JOIN Clients cl ON m.supplier = cl.name + 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 supplier_id != 'all': + sql += " AND cl.id = ?" + params.append(supplier_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 = conn.execute(sql, params).fetchall() + + # Получаем количество товаров в корзине для бейджа + cart_count = 0 + if 'cart' in session: + cart_count = len(session['cart']) + + conn.close() + + return render_template('catalog.html', + products=products, + categories=categories, + suppliers=suppliers, + cart_count=cart_count) + +# ========== МАРШРУТЫ ДЛЯ УПРАВЛЕНИЯ ТОВАРАМИ ========== + +@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)) + + 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) + VALUES (?, ?, ?, ?, ?, ?, ?) + ''', (product_name, article, category_id, material_id, description, min_price, quantity_in_stock)) + + 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')) + + # GET запрос + 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/', 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)) + + # Проверяем уникальность артикула (исключая текущий товар) + 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 = ? + WHERE id = ? + ''', (product_name, article, category_id, material_id, description, min_price, quantity_in_stock, 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)) + + # GET запрос + product = 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() + + 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: + flash('Товар не найден', 'error') + return redirect(url_for('catalog')) + + return render_template('edit_product.html', product=product, categories=categories, materials=materials) + +@app.route('/delete_product/', methods=['POST']) +def delete_product(product_id): + """Удаление товара""" + try: + conn = get_db_connection() + + # Проверяем наличие таблицы OrderItems + cursor = conn.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='OrderItems'") + has_orderitems = cursor.fetchone() is not None + + if has_orderitems: + # Новая структура + items = conn.execute('SELECT COUNT(*) as count FROM OrderItems WHERE product_id = ?', (product_id,)).fetchone() + if items['count'] > 0: + flash('Нельзя удалить товар, который есть в заказах', 'error') + conn.close() + return redirect(url_for('catalog')) + else: + # Старая структура + orders = conn.execute('SELECT COUNT(*) as count FROM Orders WHERE product_id = ?', (product_id,)).fetchone() + if orders['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('/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'] + supplier_id = item_data.get('supplier_id') + + product = 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() + + if product: + # Получаем информацию о поставщике + supplier = None + if supplier_id: + supplier = conn.execute('SELECT name FROM Clients WHERE id = ?', (supplier_id,)).fetchone() + + cart_items.append({ + 'key': key, + 'product_id': product_id, + 'supplier_id': supplier_id, + 'supplier_name': supplier['name'] if supplier else 'Не указан', + 'product_name': product['product_name'], + 'article': product['article'], + 'category_name': product['category_name'], + 'material_name': product['material_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/', methods=['POST']) +def add_to_cart(product_id): + """Добавление товара в корзину с выбором поставщика""" + quantity = int(request.form.get('quantity', 1)) + supplier_id = request.form.get('supplier_id') + + if not supplier_id: + flash('Пожалуйста, выберите поставщика', 'error') + return redirect(url_for('catalog')) + + # Получаем информацию о товаре для проверки наличия + conn = get_db_connection() + product = conn.execute('SELECT quantity_in_stock FROM Catalog WHERE id = ?', (product_id,)).fetchone() + conn.close() + + if not product or product['quantity_in_stock'] < quantity: + flash('Недостаточно товара на складе', 'error') + return redirect(url_for('catalog')) + + cart = session.get('cart', {}) + + # Создаем уникальный ключ для комбинации товар + поставщик + key = f"{product_id}_{supplier_id}" + + if key in cart: + cart[key]['quantity'] += quantity + else: + cart[key] = { + 'product_id': product_id, + 'supplier_id': int(supplier_id), + 'quantity': quantity + } + + session['cart'] = cart + flash('Товар добавлен в корзину!', 'success') + + return redirect(url_for('catalog')) + +@app.route('/update_cart/', methods=['POST']) +def update_cart(item_key): + """Обновление количества товара в корзине""" + quantity = int(request.form.get('quantity', 1)) + + cart = session.get('cart', {}) + + if item_key in cart: + if quantity > 0: + cart[item_key]['quantity'] = quantity + else: + cart.pop(item_key, None) + + session['cart'] = cart + + return redirect(url_for('view_cart')) + +@app.route('/remove_from_cart/', methods=['POST']) +def remove_from_cart(item_key): + """Удаление товара из корзины""" + cart = session.get('cart', {}) + cart.pop(item_key, 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')) + + # Группируем товары по поставщикам для создания отдельных заказов + orders_by_supplier = {} + + conn = get_db_connection() + + for key, item_data in cart.items(): + supplier_id = item_data['supplier_id'] + product_id = item_data['product_id'] + quantity = item_data['quantity'] + + if supplier_id not in orders_by_supplier: + orders_by_supplier[supplier_id] = [] + + # Получаем цену товара + product = conn.execute('SELECT min_price FROM Catalog WHERE id = ?', (product_id,)).fetchone() + if product: + orders_by_supplier[supplier_id].append({ + 'product_id': product_id, + 'quantity': quantity, + 'price': product['min_price'] + }) + + # Создаем заказы для каждого поставщика + orders_created = 0 + today = datetime.now().strftime('%Y-%m-%d') + + for supplier_id, items in orders_by_supplier.items(): + # Считаем общую сумму с транспортом + total = 0 + for item in items: + total += item['quantity'] * item['price'] * 1.1 + + # Рассчитываем скидку + discount = calculate_supplier_discount(supplier_id, datetime.now().year) + total_with_discount = total * (1 - discount/100) + + # Создаем заказ + cursor = conn.execute(''' + INSERT INTO Orders (client_id, order_date, total_amount, status) + VALUES (?, ?, ?, ?) + ''', (supplier_id, today, total_with_discount, 'Новый')) + + order_id = cursor.lastrowid + + # Добавляем позиции + for item in items: + conn.execute(''' + INSERT INTO OrderItems (order_id, product_id, quantity, price_at_moment) + VALUES (?, ?, ?, ?) + ''', (order_id, item['product_id'], item['quantity'], item['price'])) + + orders_created += 1 + + conn.commit() + conn.close() + + # Очищаем корзину + session.pop('cart', None) + + flash(f'Заказ успешно оформлен! Создано {orders_created} заказов.', 'success') + return redirect(url_for('orders_list')) + +# ========== МАРШРУТ ДЛЯ МАТЕРИАЛОВ ========== + +@app.route('/materials') +def materials(): + """Список всех материалов""" + conn = get_db_connection() + + materials = conn.execute(''' + SELECT * FROM Materials + ORDER BY material_name + ''').fetchall() + + conn.close() + + return render_template('materials.html', materials=materials) + +# ========== СЛУЖЕБНЫЕ МАРШРУТЫ ========== + +@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/') +def static_files(filename): + return send_from_directory(app.root_path + '/static', filename) + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/materials.db b/materials.db new file mode 100644 index 0000000000000000000000000000000000000000..005f7943e06bf06b8d0e3ecc67ab1d3b94a64754 GIT binary patch literal 131072 zcmeI536LArnSi_1x;4@>G0xzOje8OdBe2HZIz}2h#-ofU;NS~;%#jKighs}S$D?5+ zXJb-qMq|!}#2h9N$AC=;VM#&BC*zwC!m=r{X(c33yPGUU2%C`X7Re^;ZiTJd|9^c* znrTtS5YAs4y{`dX=Yq{V5zt?LnT$V58>Y5g-CY z;O!@Hsy_&oI@z-V`!jom{Tm$6hX@b>B0vO)01+SpM1Tko0U|&IhyW3IUl8y)C1Iv^ zuXd|;uTR3m`}m>Y5g-DB;Fo5K`t!e&AM)pa$w-Cge}_++>C>P8gX|lEhkaFGzX$LCkJ;mF zFZ(L{7C|HeM1Tko0U|&IhyW2F0z`la5CI}U1paCS{BC$~UpYFM8!a+u1by@H33;S; zJ#}d*x3S0qE~!oI&6F}jg)0L=r!+@go+;%<^O>PyAS6LvxR$%JFq+R5odE~t9m?m1 zOGVd5L@6xx7KTfsnQW;r+P`@u=fwDbSKw}eg+sl;FSL~5kUm6!2oM1xKm>>Y5g-CY zfC#+91j_4NErM@(E)gluZ5LzO-P&W?G3{`5YxR0gatx_#(6>VSjW(e`E zXnVB7kY|sqZPWH^Mp}5M)Fq|hB`+# zos*Pf303Y^6geK3RW+W7D=BrJtnKZTweLW6(6Y80>N*N79-1dtw`hmq${pH%UhjTv z^?nfHsCEdN*$asvmR6Z3C!(Fncp|E*sZ>mHMwMt+M2SVzl&qu{#MA|euJSr(iy*Ga zbVtgwp`%W1yCEsIc?-06v$kK>c0xlp8ok;Ip391M5I{h)T1AF1=A-Z*9PHxa?1gl^ z0!f+9t23KR#oQM&J)?!fx=5)oqIWjcrOMGnLRJ+yro^&SH2U#scjtP(fU_hR&^W>S24#ug1+M;TAR8dWR?E-nh>Z;?=7;hIX z(&`jks%X2xQtt)p-NRLiiUoi&a^RN_qn$?MoynA{D&6r|qD!(cIiI z9oUb7)<6T?NTDO!umwom1uft(Fh--Huj(x_kiqLPFySg!UcR$f*igXXc*STwyCG5- zDd`=KcPHdz5_<~+QjI2*c+ybd4yXgo4ou%t+8xjpygwX=+OcLZUC6z!Q&tn5$z(JE zRVdw2JFCPw1{XUZuph8z*#Y)P_N#aJMn}yN0U|&IhyW2F0z`la5CI}U1c(3;AOcMY zguu&Rn^tq-X>Ib!iKn$G8;NJO<~AHbsohtb6VUhn>lfJbY(GT)_cv*fl8FEjAOb{y z2oM1xKm>>Y5g-CYfCvzQNd%Hkr;znDhU|b#9)eW#V3s2gGGYc`R3OUb=Ebi+gP$Lr zDLI9-2SPtEegdxW2m;-wk6|X`J=64j?GC4q^gyu476=iUfcO{)2!Kcu_@3zT8dZtB zs=6oz9x}9>S9u8XIoI)zzW?85fo*0lvcG3fPwEPt5&>Y z5g-C@g}{6%E53;-0_W*cT5LWuAkCDLqV0r$W44s`)vs1)oCiSvf57vIznV_MPs%43gvQdM}+Dc8Ck-PIt_JWr*91)qt@2 z^%yLB#3hxF;i^Vht_#Z$!6N|2uuKpZ9KtHgaaol+5=!+t6~DR^MG50tVO|Os4c>!J z2EHB?oDbrkqOfWb{*ynheUm#E_+n1&$j7yvSTlMXs#{+i+jj9w+L0&rM(oy1p6h4A z;>~m0r+bnpuOntH2t^Ug;N_Um4$IoEs0vNMvPh5+mU8NA7;Ec)VQJ+tT=ooo!DW@O z@X_$49JCe-AhwLI0{(c2~ds2x)bQlu~sXCP|!ENq!oICE}w(27V}8;X2=c4a!2)ANUuOY^_ASw zPSC-{#uek^u!#0B{~H`mGH>TNWZ)~Y(WqoF8g4oD`EWTeM^WKj8uz~L zx1`2p%wuw0?un0UcN^X25^~J<>wSs}5serMa{;;rbvDKCOEO$fAd(f1p zc1hR=)$ToOnq7Amx!?wLRb;LxqBd|qgMxWg=+dmn9k3!=x1UNFRy*UWWZpZjf<4^+ z;r@cd#mvVCj+{`y5RWuI55bVG8w{U_f|lTgWiXZ}?S(K|CC(SonjC*;C;$0Q7zba* zajepuS#y-{;#oU~gQfrY$3?Yg`}p*82U1UM+{8N@3q;v0I%l*mY}>I8BI@ zU7&~QON}96?SCL^J78}K?S8Q2113=!`e~{MbOAS6eYXt#?u*JfBJ<4`cEi>Es0m${ zwL$H>y#8mw%22o2LPHNe6-~@I4SyMguiMCv{{KMeA%WclZvc3ZofCS9h1e5pIm?G$ z4pB6~yZtXdYM%%Y0U|&IhyW2F0z`la5CJ0ap(8Ly>J{H$vO6$aS}Zo5T=t(Ot%0k2 z_5db0n$Fz%W=V_0x*3OtnNe@Mbe{NzlaHP@X<>tpzHZ*m%{$P1vdqPsZZa9=7Hld(TPH_Lf_tyfuIJ7qu3|`gpWXp`eu>U3hYTtH9 zrVkMy0z`la5CI}U1m2$n%F#eT5XFnz$`?8uG0AQHLlL46a9d`>rOG|X=oJHhSTfw* zl}vRjYJ*2_k_!sm@VGpaZ@ms%vwsa7H|S&LiTbwJ_4V(Ci&GreT19-q-e;fi8$w^| zfL*n{@NYbHQA6#9xTXgc{9$rOG=ZMNaCd@Bt$hppWY9Utudh0VQimoLKLr0Ap6pmd zub}0b#d`7oTE>Qd4{Mca>j!N-N@eClx!1OpnIShe!~J#@8C+p|Y zaFK%B8a%kL!8~+1+#Tb>z~cfBnZfEo)_oA#U~SiKl)_E#&2p9Mbx7_Qc(Re$-r37O zX(!1U9%Qqjtvtiyh&kNN9w(XvFLbL>6wVA>Fk>EWmsRk+qAW)&JFYp?O@N&ygruq*@-#NjbdKbR!##j7%%tp$dldZt>nv*K`VUdm`aRu7jhVe3ks;! zJH9b|!L|^_Re%GXS85;Az^xAh2zH|?&?H*MzGNrv*)9|}(^ign_((CLX<%rh-xeCd zUDe*+LKIS*XD4O51ElmVZYwXs zLDcv}%LnuAQ5X;5R4S3`PNcNA;C`>kHZ|0v=g9s4H}b9L{KC_AGM*_01fRIFt(@dC z)<2(vNo|GupBaUr?SK%2R5Fo@r4o44fg28>stanc?sz;p36a)4>tkV4N+^c`JzMZs z2nM}njl0*sjBEXy`~TTBxc`5Z{eu0O{gxeMkFZ_rPKXG&=Kc9|Pf`;BB0vO)01+Sp zM1Tko0U|&IhyW3IPZ0=6ZK5&F9N@?L?5&?4>r58b)^fzzXIwlCBb~|jr&R-^h>y)*lHmjx=hOh!>T?O%on($71?(!2Tyg1m< zdMu)JN7U~0U3V``onY%NR_jh({6s{Ji;EV#dIGI43`{N@gT9NW{cq(23NQ9sq8ly8 z;B_kLM~3dZ^#n!tS*=UD=*ftZ5EmR+eF8yr}wrbBj^P>|f@2D@2b`w!k>AQ~IIqw_a*nR@# z7l>G%3$N=BtS9EY;o9;El;zL=!Oa5uIr}y%vOacd=r^G!LbruBgnC1>g0BUi4(^1@ z^dSO7fCvx)B0vO)01+SpM1Tkofs-XLmw92UJ%_^?WB$xT)7A?+lRM$*4IUlg0Wc*i zsRc20L89x-5N4Ag8_bQ|I1zeY_~9R9n|$+vJfFuI3rfQGSD72=2{)a0woUFcTJ*-H zSd0IZZPV7z`nhJ4Yi>YqTZ+NGi$ZEO=UXy$w$WkwM~IDJZ7~X_w2uI89U<_V>Y?Y zcI(wjF}Fkdjk$MUVE%V)^3HdeBDh@67tPHa(`Wqfxh5jab7BDr;5(h5By)>J;m1FS z*;KDcdTvill7!n&GgXzo^t(T}1ttt^O3Zhd0y!MYxu)>x%#wfHW?!H~^a?(o!z0B$ zc}tJ6{a-%+37e|%{eLb7`~Sbre$8HEud-Jlfj&fl2oM1xKm>>Y5g-CYfCvx)B0vO) z!26GYQ}T%}mn4c#Cw@y3emfkJ>2hHdxiayJ ze$PsQF?Kj~wB^~**8)$r+~->xxXrWDccy!_^WUXUi(e7v2vwo*mV3MG6sYorw_FWX zKm>>Y5g-CY;5|lQOTXXK+SVps|CLhailJO@rj!{fTxt9j=w02H?(dWP)1O+_CmV@! zhhH{6`9XQP0#g-eFCzTo*EevkTmIj718*}nS z>D9gGr&o7G6N#|AVr9R)V(qeJwH7j?rF?d%mQ7WZu)KD~(hJx2+2kI~6| ztY21Y;$=s3(8s}nOiAuvy1Z{qe|q^UXhF}{yLL73>mRVLaNJ?`Kf?SsVQJTPdp)gl z=7=|@xfNJUtpi_!C0NNPZ3`Psr8ek?gE#eKXrRWSIe62uEJY`jIs?iUh6!GL+BNYDWvJmCqJ74VOkYTWw?iYFGazml++% z4rQQv%RuX|b5j}^$&C(d8qSw$BA`vxYT?)F%3GFkR`tf}_*u1#e=So}eeTx2Iiips z9?X5Ic-2t8lpDxwDi!$ofMqHJs&(iuU*h((wzrGpUp8+##>lVT13V1|S4%%>i!*Jc z@s9Au7MCsL)~(BD^SR*~{)Q24!B#sJec;7B?$-0#o6)HCV?eDPd$%N=`c1e`=K&@) zTq^eJf4Le-=!qwfp#T<{$(9PE1EtL)xh6N&UMp8WWNN%0H;mXOchtfBXb#(`8Fs_C z$ZgEzhnid)Szj2g-HICqa%OOF6bEDDT{k~GT&v2uao6mAG*ikCUug}W7~YZ1yQk9m z7VonWm%BCH)>PfPvOw4RfqRwYZawE5@lvj4W2_W&S8d7-XLFNIoegTAbg=`KFb_(G z%VE*e8V-x&LEUs36xXOmM?;N`*G}4=xDhp&gx!$R$Hqd3yLDx_DXa$3fmy@31ixlp z{6*9K|KAh9`~Oq+7hL}jp8x0B_aGMFN9-To#BUyDB?3f%2oM1xKm>>Y5g-CYfCvx) zB0vQGdIZq9@8$sjULFA8_2FuN?*Dgl|G%62|GnJ*@8nnVF)K#a;h>79;nOw@NCP|s))BAd*vzk<@ z=c%h!Pr$x^{xo-MY>v3usx=E9=>c7rc-RYnxE|Z4)IBLDR&V9*&@T>#FK7j?!wfOk zSiepQbAQafT0MhVrAc+gM|ov6Me$bj&R}IT?JKKwA2W5-I-i;0X`MeuEQ^+O4ZdN^ zX?WU{dK>bgm{#77hD+hko(g>1#7$NU;0wekhXIfT9sl5o!_(F&ElkR%qu_ZvjH2Po zr^DcAs~a3<8B+wK@)=DlH#64PZlg$Fx;ycc$s6=p3b zkm;@rZ-JLSqx1OsHQeLHM;#v>wWDc9^?KY&E&ZguTm`(90xBy^V}%h!BG(15@OF3@ z3ie=0-?Bako#{=l=}j-`tGOd(vY!nOd^<{J!1`( zV_{>xFS}WI3V4Wziz5ZN31th#n(JH7Zuw4YeL9&4l`W@-JgqZlir2T+)M(u3*;Mrv zPg-@>on|VuI^7v|*@#=$I{!6Tf?-gm(rXk!sD?Tq|bWSo zaB^F@&eHDDj%j<~&4UN)VmAi!MIK9n(I8pWpc!^$qm1D~DL2_ieliLgUmxT#LD$XE zJek>e;hFlB-`>#! zVG3_DTC03@i>GzQ3~|fF7HY&9oC5gd*&4U&+8wN(mU;KCr}gGcrbhVr=0vanSisXgvY5=BGsKpIs8(aFO^KBVyOgw z{trDQz|;Qk*@Nty&_gW5o?y#aKJ;?v>30JPwMhhs01+SpM1Tko0U|&IhyW2F0v~1q zbEIBT+om0>mbF7#MTVe`-PJK|zxEiqzN=dUv!%tNb{`}it6s~K%G@)4Sk`t$RsUJi z8n~+MhtkKiLvj@^VpeSeGVRw6S8vgdVu*-umb6IJwnM%#t)d-)414*}QOxLVm(CNl zJHXw3T(1V&9fR`6w4*X4Z`Z!*X_FR;+72i_4#f{^hj~MISiQx~JFo*v9|d=P1#`$9 z+HuH*GE~AY-t?`|+!4H5-GU9v+N}vi(RMj`#dknWk3n<0c>~z&61XabrHfJK2`F$J zzHi`cc)iy{<~;!92EBKV=~Bd}-DZ{6cEl12KK~2TKFpRyeJ27$fCvx)B0vO)01+Sp zM1Tko0V43hCqU2tAAB8C4~YN~AOb{y2oM1xKm>>Y5g-CYfC$j@KiL2gAOb{y2oM1x zKm>>Y5g-CYfCvzQ4?Y2W{%7oAfxXWDoBa{?0C<_b!2X#%%l?Ty4f_BbVFy?RF4Kny z5CI}U1c(3;AOb{y2oM1xKm>>Y5qL)k;EVoTjDLstcM!jwE&Q9m0MN-_04Vt|MdEJ& zbnrI-I`|s^9sCV|4ky0*Pk#ZRB>8;$^S_My|K9}9{|DH)>{sk_Yy+DQdjLMmzQbg8 zH@o^B=^!;i1c(3;AOb{y2oM1xKm>>Y5g-CY;9VmSlG??n5{*Zcu810CwbOV+O@xfo zSVZZLsNKQZ)kH*%x71E!P&QD18ddzY(_}5DiN{vLL-iE8Hr*_&EQIhUjW@sqs zGESq=N<@h|8#7B*X1J=R96_nw2R(v@Vv%T!KmUiG62SBS9QgYmfv5c~Y?xijmcR_a z$CxYhYUp3!GJS{u5g-CYfCvx)B0vO)01+SpM1Tmq2MC-hMMUj(*uwufY+dNB;+S^uM1+|ND6Kzn4e)faBkX2_yjuhJiqWz;)79Yg5Px z;S<0m#N5op?w|DEmxB%XK?c3?0fAsT<|c;MBff1FuNT^n=X6IyPhDc+GGW6da=aNh zC%68}OMcz@=9-M0k4E~{Nsm8X(Hn%9hxh&%Cm5>wd`<6ur9L?_=vkg_kP~kx1lHo? zVEuG)KcPOnG?I7qt8VCy9<3yJ=MYLCsy}(p4PYCrkg^l)mm&iet_dGMX zqSwG2&1Ajy{-gzHoQHA2jWQ1z=>4hNgVV(2;oid~xtaZ&s@+C?WuJgPea?YX9hpm+ zd>VfG7lYG5tuc~WiYOHa-J&sHIY54r9uDGVrhz`3pbI_6OkTE=-6Wz(3bSEGoX(?0cPo)*!_bz!=jM*slzGe706whwvC!ss z;PhA%`reN6S;2`izTFc%SN03~0iW$JcOUgM&R2!x#A!)XijxV~K;-AZTQ!dD$>rLpV*p zvjm)RwVGKJ=;8|iRfv6=e#UaOVB%f{7XyoX)Dm(wP*Cf{=JTk-z{bNibgY2EdK09H zm!1sP*MZ`^h#Oz}{8SN0+7TeEf~n&nFG_M0J|NHGm`i-b*hb{C#_V5{+3b&6_{!MEHyv%sR-&w6x+ z;+DT##WyR_pLs8l>~f`6@&-5`2N`o>Zga({SR{s{_2Sr?O)Np0o=YFt+$c7~k#dSA zz|aT*)0K`ah?hBN%#BjbHkSe!J@w*8gz3uPy#Pb4p?b)5}ma4;|h&grDE+-Il2oaC&%tTRB+#18yV3@-bh{ZH?Zt zm+1p(V60RF7k*ea?)0{oUW3E4Ytcqz`4IF$xxyo!puR&ip^NqC0#eE;39^LT6!<9P zc0uyR*sTmp4bv4D*u3VW`%`!U*ca{o$SbvmiA}FW3;vq+*FKMT4*t0IvV*OHO)$GR z-aDV20s?~cROhW&Jot?ZXC%f!Cd= z8xJQ<<1c+IgP$89p<|Jc;u43z34Ck?g`8sV5 za;~eFDmbYE6J)MH8abtZ7H{I|W0N#W2MvK>G0@#Y-x&Z0vd1MRU8VE1$JQ&qwwtHV`6`a39dO(v-_u9z zWU3m8{F~C>Fc$eqm=41q%#gG@Rxd;86|?)w14}PPvKL)8RV}}T7|#Z81%GAj$b+~h z>Py4#W~9vf4l{ZN-B#yYh|$6u5x(6RjKeC4C>lbXk@J5$`3CEU18SM^M(RrMgM6)8 z$q=-=k)0%vRnFm#u~51VYP4GDL(EVMk&w;P;!=NqB$76hCS%>9Hk;TpEtBx1;p#wY zQ>7t12<=xK45w;>=SdC8h3A;*+^QUHDR8s;d}o3!@Q4|r&hn*DU~AHaUT=`ACUwG3 zTX;E3o_ZY9ys4LT7PQLAXg!y9?AOv%?~0xZKb_=QYNffjC|cn0`a&#nxfhetsB*)G zAwOGxs~bXm9dn+DRp=~8xBk%)IC;{?I>7inISf|*^6zHYdY$wK|FB;vB<8&YOcMn> zum6*GgJH=U~Pl*FbmpQc~=splw?#Y_79IdOlUP=>Lkge?Ry$rQLZxY%H zF=O#pFesuNEq_oKJtO<-BJOwrF!-0HUu<84@%$Txx7Ir+KeMPB+*NvAtU62W@w^$( z{LdEOZq^yXrOAP4o}njgV}EJtaB5-SCv&GH{lpxGw+ngL+$fWVQsY?^4EvfA#0&XW(Fk8;n-{2{VZ3) zIS(9!=%4tZVRVE=^&{)iGi-K>a>WHy%R=kwN@j0-j!doLZ1DRf(E?uEO$q3bNw^J9 z3pV7L$<9aq%AhGwn?aHEjOZ26HPyd$f=U%F&tJm|{4nwz7_;!9vy$3uN>jr+>xOW5 z1YNN@$1Xz3;Zaqm;Ir4cYc$>Dd+b$!AGIWk+bu(!SI(Y%L;Eppbgmqhjlbi`4@7*L zhsfN}B;Y=fwt3bg{ieIu1ux@&gEmyBsn;$Y;iUu&3L330OZSI(aa=GKy@s$V({EYT zx$;#4O3-4+H3U33Pt^~h{rJ-SahT!w*N-mwIn_Hk=t z+f^;Cy6Ylrjr#S>thxh8h?=Mz%q=lGL0SlW|BZ!8N4zfQTp6+Yl(T!}f}e5fH8fD> ziQ;xHk3uflpun}=uVuH;A2EseJTYp8|l zD^?q=x%(aA<8B6a2e;3d?*A-@RofLgdPtkD6j}uB#4#In>j>RC8+NPeKg~C5VuCe- zjLS-Yt4ym}?8`D8=Xo%ZlHGo>;ph@eAk)_ANRZi&+(M$%t^$K+cOtA1BC-jXH%!Ni zQ9n_YbrC6al2+H)P2p}^H>0t%ytm>|!LbSz-QKcWrYl>iz6NGOnC;qI=*Wp-(u)=N zqyi5vD%+$AR}=VS9!+=}!-_>TT2G`gYcZt;$BcT&4JS zOvJQ&jK(Tn;D-2qna9BCzCG3S@7u=ejCWVGdSx$WXY^E5k7MPZ6kWURo=gy6i7L@% zYF`cu6|4|&XF+`Fb*wG358n(co`wQjc_c6LG7HY zRQ5Xv#*XZ*$oS|s@I=7dTf8qo9?}MxwsaPJ~BM*XG9wRM?XA z0@O<`M#IZJ6N9TniF6D_0*wdzvTIrD+zj`-xFK&dJ2ZgQk(qnfqW*FdoT^%!)fvEG ze@;niV{2IF*pJwP&SZt?FugM8U5Xg_+ng6s)shw;IP(x~oYR+8bZ=J|3I2 z{r)bPjeg$Y$8pR9Ym>3oV$f&=wsOKu*dZRDEP0@sUht*$2VAybLH?boSl>O_0C~JH zJ++nnowbs+2>_hHw4Ad{=uEM0+qepV`!RM&S`N+2l&u;W*gNw-d;_2Za_P7_P5CFJ zg?M}%U!e%t;aM%W57E-OWJGA*1%; z{QFfcyThtH{Q6XJSpuuGpK+G^70_*+g?AUesirf@z{rzYJKN(BVzxGOv~XCuWTT`x z0bpcl$k0fV#U@Im-%Mu`m_wsgv++jxOB>J82BClC`G&kuu)iVv2lE3_TeJA+>H|ovF0rZ2p1MbLkI__O3Wz^G})0Ex6+|)U%Z@22Ro+Ic1E;+{C|E zj^=jwS4+2Q9+V!YY}@R76DEl%>5^>H2gZqo>3-caiN9Em&=hH)D`kA@D$}2-m}_nV z0H{X}-q>J0Y@V^#%++=HmO16fnFaaI$=Cw^S2&q8?i0aPTR)jiz~9Z^uOp1kUfq4G z>4{8jS-mmC{ap9!RqE@~1*j_mNJAv8`&%wMo)|yU1X!FbNYh!=b?X0p{OXD(04*Pn zAVW?6>&~1iwamc$7hepg64LuReL_BC@%HWFVMFgZ1Y*&~hjCRcdP3Z-g^J}B+o4Fk z-b?8NTkJ=gF+H>MyZPyJm!R$JUT5j&)n)<350T{iFyZDOg5P_K!p6rJ1H8KLsO#}x zX!;;nsH`#k9_s$((q{mqB%_U$+bXts1jbJJzehY|YYs`Cl|d{;5Af5=)J3<@4mO2; zZ?JH&w9A$|uYgkUar^SN{1l#jnnc@WeJXmAh9ksh6{LrKsN9_m=88q*2maEo%fP;M zPJ4+;yya=DcL7KgG~wn|!t`)|Eb`#S>jT7hZbk*Zs;z!nI9kh;VngKCV#C?k!W$Q)Cl?6&ME_4E&p))R z=H7VuN*4A_8bH3`B4HwkUrVX9sKa~66H!BD8wQRIs5#B@zC zsn9oE>jgez_q_{%sLN(s2HA)aU4q0#jVbf%;N$Hq)}zFK^;yN- zSK86-<)d;~ls;D0;T-ZY+PL)}pDNO-MP;=*q?lV5hizE(-OcChxvb2Dn7-01(8R2? z-|wRy#a+lmx5vnNuKdn)pP4RB?TdGP>z`{2Y*bwOK!@yor9jbw*1+=R^8@}nwgb^B z{uKSx-y1{lk@Gq{j8gz;d2L>JUteVV))(Dy^@F%f%q>x%)0o8_qyTs&>@`{I+OK#n z21J|r_ylH@dWTX1DD4WTPB0IBkK8%@8IreCQfR5>_ki_BNyuP-J;@mVRh+%&DJ|6@4 zG8PR9O4{nZ2=5`N^JG8Lqxvh3U_(yOS%GBDVfn)MCCji5iiTVxtHVNv>icg4DD6a6 zCtskqu>(aP^nmkjgyI{WN|8N|v70U2UvJx9}$bY|L^w4{|t;=8a_Hpb z4(Za7s%*?)7GjpF$Jzc(cf#D-%cc*Yi_()09uU{YW^wGIin251ux8!{bwTjaOITIw ztJYNqlzkTx2o+g?_2>%tfIP?|`2H?!C>_?Pf8fgb%(TE@aUA;8Zzfr!VEVgV-!^S` za-Eb0sHfTTQwnI@UvZ$#s97NfOlqGe$Bji3QuZZ7_SsI3OZA5U{fco8hOZOJc5adF9X5*fK;-1ZAPBj`k-p=TEl4n+6 z;y8C=3BM0kfiVQpQz8YtH+n)fQEqX%P@sGBLKz6DIfwVIu}JqGom~W2W%Pk{j6e)u z=D!B4ndypV%ueP2=h|X-omS88e2A1_S=n4yQnpz1Z?wng`8nXh;H&E=RQftB5Ezhtz> od;ZHW<^Rw3NgR?U{=3mHe*9pwt`v9)yi5a`U$Qo-GV*-*KRlmPAOHXW literal 0 HcmV?d00001 diff --git a/static/js/script.js b/static/js/script.js new file mode 100644 index 0000000..f5b0daa --- /dev/null +++ b/static/js/script.js @@ -0,0 +1,37 @@ +document.addEventListener('DOMContentLoaded', function() { + // Кнопка нового партнера + const newPartnerBtn = document.querySelector('.btn-new-partner'); + if (newPartnerBtn) { + newPartnerBtn.addEventListener('click', function() { + // Переход на страницу добавления партнера + window.location.href = '/add_partner'; + }); + } + + // Кнопка "Редактирование" + document.querySelectorAll('.btn-edit').forEach(btn => { + btn.addEventListener('click', function() { + const partnerId = this.getAttribute('data-partner-id'); + // Переход на страницу редактирования + window.location.href = `/edit_partner/${partnerId}`; + }); + }); + + // Кнопка "Добавление продажи" + document.querySelectorAll('.btn-add').forEach(btn => { + btn.addEventListener('click', function() { + const partnerId = this.getAttribute('data-partner-id'); + // Переход на страницу добавления продажи + window.location.href = `/add_sale/${partnerId}`; + }); + }); + + // Кнопка "История реализации" + document.querySelectorAll('.btn-history').forEach(btn => { + btn.addEventListener('click', function() { + const partnerId = this.getAttribute('data-partner-id'); + // Переход на страницу истории реализации + window.location.href = `/sales_history/${partnerId}`; + }); + }); +}); \ No newline at end of file diff --git a/templates/about.html b/templates/about.html new file mode 100644 index 0000000..77fdb9f --- /dev/null +++ b/templates/about.html @@ -0,0 +1,18 @@ + + + + + About Flask + + + {% extends "template.html" %} + {% block content %} + +

About Flask

+

Flask is a micro web framework written in Python.

+

Applications that use the Flask framework include Pinterest, + LinkedIn, and the community web page for Flask itself.

+ + {% endblock %} + + \ No newline at end of file diff --git a/templates/add_client.html b/templates/add_client.html new file mode 100644 index 0000000..5a05fcb --- /dev/null +++ b/templates/add_client.html @@ -0,0 +1,521 @@ +{% extends "base.html" %} + +{% block title %}Добавление поставщика{% endblock %} + +{% block content %} +
+
+
+ + + +
+
+

+ Добавление нового поставщика +

+
+ +
+ {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
+ + {{ message }} + +
+ {% endfor %} + {% endif %} + {% endwith %} + +
+
+ +
+
+ Основная информация +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
От 0 до 5 (чем выше, тем надежнее)
+
+
+ + +
+
+ Контактные данные +
+ +
+ + +
+ +
+ + +
+ +
+ + +
10 или 12 цифр
+
+
+ + +
+
+ + +
+
+
+ + +
+ + Отмена + + +
+
+
+
+
+
+
+ + + +{% block scripts %} + +{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/add_order.html b/templates/add_order.html new file mode 100644 index 0000000..399501d --- /dev/null +++ b/templates/add_order.html @@ -0,0 +1,737 @@ +{% extends "base.html" %} + +{% block title %}Добавление заказа{% endblock %} + +{% block content %} +
+
+
+ + + +
+
+

+ Добавление заказа +

+
+ +
+ +
+
+ Информация о поставщике +
+
+
+
+
+ Поставщик: + {{ client.name }} +
+
+ Тип: + {{ client.contractor_type_name }} +
+
+
+
+ Email: + {{ client.email }} +
+
+ Телефон: + {{ client.phone or 'Не указан' }} +
+
+
+
+
+ +
+
+
+
+ +
+ + +
+
+ +
+ + +
+ + Максимально доступно: 0 ед. +
+
+
+ +
+
+ + +
+ + + +
+
+ + +
+
+
+ + Материал: + Не выбран +
+
+ + На складе: + 0 ед. +
+
+
+ + +
+
+ Расчет стоимости +
+
+
+ Количество: + 1 ед. +
+
+ Цена за единицу: + 0 руб. +
+
+ Базовая сумма: + 0 руб. +
+
+ Транспортные расходы (10%): + 0 руб. +
+
+ + + Итоговая сумма : + + + 0.00 руб. + +
+
+
+ + +
+ + Отмена + + +
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/add_product.html b/templates/add_product.html new file mode 100644 index 0000000..cc88928 --- /dev/null +++ b/templates/add_product.html @@ -0,0 +1,458 @@ +{% extends "base.html" %} + +{% block title %}Добавление материала{% endblock %} + +{% block content %} +
+
+
+ + + +
+
+

+ Добавление нового материала +

+
+ +
+ {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
+ + {{ message }} + +
+ {% endfor %} + {% endif %} + {% endwith %} + +
+
+ +
+
+ Основная информация +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+
+ + +
+
+ Характеристики +
+ +
+ + +
+ +
+ +
+ + +
+
+ +
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+ + Отмена + + +
+
+
+
+
+
+
+ + + +{% block scripts %} + +{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..44a2977 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,686 @@ + + + + + + {% block title %}Строительные материалы{% endblock %} + + + + + + + + + + + + + + + + +
+ +
+
+
+ +

Стройматериалы

+
+ + + {% if request.endpoint in ['index', 'orders_list', 'catalog'] %} + + {% endif %} +
+
+ + +
+ + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} +
+ {% for category, message in messages %} +
+ {{ message }} + +
+ {% endfor %} +
+ {% endif %} + {% endwith %} + + {% block content %} + {% endblock %} +
+
+ + + + + + + + + + {% block scripts %} + {% endblock %} + + \ No newline at end of file diff --git a/templates/cart_new.html b/templates/cart_new.html new file mode 100644 index 0000000..659d6a5 --- /dev/null +++ b/templates/cart_new.html @@ -0,0 +1,731 @@ +{% extends "base.html" %} + +{% block title %}Моя корзина{% endblock %} + +{% block content %} +
+ + + +
+

+ Моя корзина +

+ + Продолжить покупки + +
+ + {% if cart_items %} + +
+
+ Транспортные расходы +
+
+

Транспортные расходы составляют 10% от стоимости материалов

+
+
+ + +
+ + + + + + + + + + + + + + + {% for item in cart_items %} + + + + + + + + + + + {% endfor %} + + + + + + + + + + + + + + + + + + +
МатериалПоставщикАртикулКатегорияЦенаКоличествоСуммаДействия
{{ item.product_name }}{{ item.supplier_name }}{{ item.article }}{{ item.category_name }}{{ item.price|int }} ₽ +
+ +
+
{{ (item.price * item.quantity)|int }} ₽ + +
Базовая сумма:{{ total_amount|int }} ₽
Транспортные расходы (10%):{{ (total_amount * 0.1)|int }} ₽
ИТОГО к оплате:{{ (total_amount * 1.1)|int }} ₽
+
+ + + {% if cart_items|groupby('supplier_id') %} +
+

Заказы по поставщикам

+
+ {% for supplier_id, items in cart_items|groupby('supplier_id') %} + {% set supplier_total = 0 %} + {% for item in items %} + {% set supplier_total = supplier_total + (item.price * item.quantity) %} + {% endfor %} + {% set supplier_total_with_transport = supplier_total * 1.1 %} + +
+
+ Поставщик: {{ items[0].supplier_name }} + {{ supplier_total_with_transport|int }} ₽ (с транспортными расходами) +
+
+ {% endfor %} +
+
+ {% endif %} + + +
+
+ +
+
+ + {% else %} + +
+
+ +
+

Корзина пуста

+

Добавьте материалы в корзину, чтобы оформить заказ

+ + Перейти в каталог + +
+ {% endif %} +
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/catalog.html b/templates/catalog.html new file mode 100644 index 0000000..8c47253 --- /dev/null +++ b/templates/catalog.html @@ -0,0 +1,868 @@ +{% extends "base.html" %} + +{% block title %}Каталог материалов{% endblock %} + +{% block content %} + + + + +
+
+

+ Фильтры и поиск +

+ + Сбросить все + +
+ +
+ +
+
+ + + {% if request.args.get('search') %} + + + + {% endif %} +
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+
+ + + {% if request.args.get('search') or (request.args.get('category') and request.args.get('category') != 'all') or (request.args.get('supplier') and request.args.get('supplier') != 'all') %} +
+ Активные фильтры: +
+ {% if request.args.get('search') %} + + Поиск: "{{ request.args.get('search') }}" + + + + + {% endif %} + {% if request.args.get('category') and request.args.get('category') != 'all' %} + + {% for category in categories %} + {% if category.id == request.args.get('category')|int %} + Категория: {{ category.category_name }} + {% endif %} + {% endfor %} + + + + + {% endif %} + {% if request.args.get('supplier') and request.args.get('supplier') != 'all' %} + + {% for supplier in suppliers %} + {% if supplier.id == request.args.get('supplier')|int %} + Поставщик: {{ supplier.name }} + {% endif %} + {% endfor %} + + + + + {% endif %} +
+
+ {% endif %} + + + {% if products %} +
+ {% for product in products %} +
+
+ +
+
+ + {{ product.category_name }} + + | + {{ product.product_name }} +
+
+ + {% if product.quantity_in_stock and product.quantity_in_stock > 0 %} + {{ product.quantity_in_stock }} ед. + {% else %} + Нет в наличии + {% endif %} + +
+
+ + +
+ Артикул: + {{ product.article }} +
+ +
+ Материал: + + {% if product.material_name %} + {{ product.material_name }} + {% else %} + Не указан + {% endif %} + +
+ +
+ Поставщик: + + {% if product.supplier_name %} + {{ product.supplier_name }} + {% else %} + Не указан + {% endif %} + +
+ + {% if product.description %} +
+ Описание: + {{ product.description }} +
+ {% endif %} + +
+ Цена: + {{ product.min_price|int }} руб. +
+ + +
+ + Редактирование + + + +
+
+ + + +
+
+
+
+
+ {% endfor %} +
+ + +
+
+

+ + Найдено материалов: {{ products|length }} + {% if request.args.get('search') %} + по запросу "{{ request.args.get('search') }}" + {% endif %} + {% if request.args.get('category') and request.args.get('category') != 'all' %} + {% for category in categories %} + {% if category.id == request.args.get('category')|int %} + , категория: {{ category.category_name }} + {% endif %} + {% endfor %} + {% endif %} + {% if request.args.get('supplier') and request.args.get('supplier') != 'all' %} + {% for supplier in suppliers %} + {% if supplier.id == request.args.get('supplier')|int %} + , поставщик: {{ supplier.name }} + {% endif %} + {% endfor %} + {% endif %} +

+
+
+ + {% else %} +
+ + {% if request.args.get('search') or request.args.get('category') != 'all' or request.args.get('supplier') != 'all' %} + Ничего не найдено по вашему запросу. +
Сбросить все фильтры + {% else %} + В каталоге нет материалов. Добавьте первый материал. + {% endif %} +
+ {% endif %} + + + + + +{% endblock %} \ No newline at end of file diff --git a/templates/components/header.html b/templates/components/header.html new file mode 100644 index 0000000..a80b901 --- /dev/null +++ b/templates/components/header.html @@ -0,0 +1,8 @@ +
+
+
+ +

Строительные материалы

+
+
+
\ No newline at end of file diff --git a/templates/components/partner_card.html b/templates/components/partner_card.html new file mode 100644 index 0000000..5eeccc1 --- /dev/null +++ b/templates/components/partner_card.html @@ -0,0 +1,249 @@ +
+
+ +
+
+ {% if partner.contractor_type_name %} + {{ partner.contractor_type_name }} + {% else %} + Тип не указан + {% endif %} +
+
{{ partner.name }}
+ +
+ + +
+
+
+ Директор: + {{ partner.director or 'Не указан' }} +
+
+ Телефон: + {{ partner.phone or 'Не указан' }} +
+
+
+
+ Рейтинг: + + + {{ partner.rating }} + + +
+
+ Сумма заказов: + {{ "%.2f"|format(partner.total_sales) }} руб. +
+
+
+ + + +
+
+ + \ No newline at end of file diff --git a/templates/edit_client.html b/templates/edit_client.html new file mode 100644 index 0000000..ae18c30 --- /dev/null +++ b/templates/edit_client.html @@ -0,0 +1,815 @@ +{% extends "base.html" %} + +{% block title %}Редактирование поставщика{% endblock %} + +{% block content %} +
+
+
+ + + +
+
+

+ Редактирование поставщика +

+
+ +
+ + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
+ + {{ message }} + +
+ {% endfor %} + {% endif %} + {% endwith %} + +
+
+ +
+
+ Основная информация +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+ +
+ + +
От 0.0 до 5.0 (чем выше, тем надежнее)
+
+
+ + +
+
+ Контактные данные +
+ +
+ + +
+ +
+ +
+ + +
+
+ Формат: +7 (XXX) XXX-XX-XX +
+ +
+ +
+ + +
10 или 12 цифр
+
+
+ + +
+
+ + +
+
+
+ + +
+ +
+ + История заказов + + +
+
+
+
+
+
+
+
+ + + +{% block scripts %} + +{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/edit_product.html b/templates/edit_product.html new file mode 100644 index 0000000..abd7f68 --- /dev/null +++ b/templates/edit_product.html @@ -0,0 +1,454 @@ +{% extends "base.html" %} + +{% block title %}Редактирование материала{% endblock %} + +{% block content %} +
+
+
+ + + +
+
+

+ Редактирование материала +

+
+ +
+ + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
+ + {{ message }} + +
+ {% endfor %} + {% endif %} + {% endwith %} + +
+
+ +
+
+ Основная информация +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+
+ + +
+
+ Характеристики +
+ +
+ +
+ + +
+
+ +
+ + +
+ +
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+ + Отмена + + +
+
+
+
+
+
+
+ + + + +{% endblock %} \ No newline at end of file diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..085f57c --- /dev/null +++ b/templates/home.html @@ -0,0 +1,16 @@ + + + + + Flask Tutorial + + + {% extends "template.html" %} + {% block content %} + +

My First Try Using Flask

+

Flask is Fun

+ + {% endblock %} + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..376a9ba --- /dev/null +++ b/templates/index.html @@ -0,0 +1,547 @@ +{% extends "base.html" %} + +{% block title %}Поставщики строительных материалов{% endblock %} + +{% block content %} + +
+

Поставщики материалов

+ + Новый поставщик + +
+ + +
+
+

+ Поиск и сортировка +

+ + Сбросить все + +
+ +
+ +
+
+ + + {% if request.args.get('search') %} + + + + {% endif %} +
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+
+ + + {% if request.args.get('search') or (request.args.get('type') and request.args.get('type') != 'all') or (request.args.get('rating') and request.args.get('rating') != '0') %} +
+ Активные фильтры: +
+ {% if request.args.get('search') %} + + Поиск: "{{ request.args.get('search') }}" + + + + + {% endif %} + {% if request.args.get('type') and request.args.get('type') != 'all' %} + + Тип: {{ request.args.get('type') }} + + + + + {% endif %} + {% if request.args.get('rating') and request.args.get('rating') != '0' %} + + Рейтинг ≥ {{ request.args.get('rating') }} + + + + + {% endif %} +
+
+ {% endif %} + + + {% if partners %} +
+ {% for partner in partners %} + {% include 'components/partner_card.html' %} + {% endfor %} +
+ + +
+
+

+ + Найдено поставщиков: {{ partners|length }} + {% if request.args.get('search') %} + по запросу "{{ request.args.get('search') }}" + {% endif %} + {% if request.args.get('type') and request.args.get('type') != 'all' %} + , тип: {{ request.args.get('type') }} + {% endif %} + {% if request.args.get('rating') and request.args.get('rating') != '0' %} + , рейтинг ≥ {{ request.args.get('rating') }} + {% endif %} +

+
+
+ {% else %} +
+ + {% if request.args.get('search') or request.args.get('type') != 'all' or request.args.get('rating') != '0' %} + Ничего не найдено по вашему запросу. +
Сбросить все фильтры + {% else %} + Нет данных о поставщиках. Добавьте первого поставщика. + {% endif %} +
+ {% endif %} + + + + + +{% endblock %} \ No newline at end of file diff --git a/templates/materials.html b/templates/materials.html new file mode 100644 index 0000000..f959b22 --- /dev/null +++ b/templates/materials.html @@ -0,0 +1,266 @@ +{% extends "base.html" %} + +{% block title %}Материалы{% endblock %} + +{% block content %} + +
+

Материалы

+ + Всего: {{ materials|length }} + +
+ + + {% if materials %} +
+ {% for material in materials %} +
+
+
+
+ {{ material.material_name }} +
+
+
+ {% if material.description %} +

{{ material.description }}

+ {% endif %} + +
+ {% if material.category %} +
+ Категория: + {{ material.category }} +
+ {% endif %} + + {% if material.color %} +
+ Цвет: + {{ material.color }} +
+ {% endif %} + + {% if material.density %} +
+ Плотность: + {{ material.density }} кг/м³ +
+ {% endif %} + + {% if material.thickness %} +
+ Толщина: + {{ material.thickness }} мм +
+ {% endif %} + + {% if material.supplier %} +
+ Поставщик: + {{ material.supplier }} +
+ {% endif %} + + {% if material.country %} +
+ Страна: + {{ material.country }} +
+ {% endif %} + + {% if material.wear_class %} +
+ Класс износа: + {{ material.wear_class }} +
+ {% endif %} +
+ +
+ {% if material.price_per_unit %} +
+ Цена: + {{ material.price_per_unit|int }} руб./{{ material.unit or 'шт' }} +
+ {% endif %} + +
+ В наличии: + + {{ material.in_stock or 0 }} {{ material.unit or 'шт' }} + +
+
+ + +
+
+
+ {% endfor %} +
+ {% else %} +
+ +

Нет материалов

+

В базе данных пока нет материалов. Добавьте материалы через импорт данных.

+
+ {% endif %} + + +{% endblock %} \ No newline at end of file diff --git a/templates/order_history.html b/templates/order_history.html new file mode 100644 index 0000000..ef69ff5 --- /dev/null +++ b/templates/order_history.html @@ -0,0 +1,522 @@ +{% extends "base.html" %} + +{% block title %}История заказов - {{ client.name }}{% endblock %} + +{% block content %} +
+ + + + +
+

История заказов - {{ client.name }}

+
+ {% if client.rating %} + Рейтинг: {{ client.rating }} + {% endif %} + {% if total_stats %} + Всего заказов: {{ total_stats.total_orders }} + Выполнено: {{ total_stats.completed_orders }} + Общая сумма: {{ "%.2f"|format(total_stats.total_amount or 0) }} руб. + {% endif %} +
+
+ + + + + +
+ + + + + + + + + + + + + + + + {% for order in orders %} + + + + + + + + + + + + + + + {% else %} + + + + {% endfor %} + +
ID заказаДатаТоварыБазовая стоимостьТранспортные расходы (10%)СкидкаИтоговая стоимостьСтатусДействия
{{ order.id }}{{ order.order_date }} + + {{ "%.2f"|format(order.base_amount) }} руб.{{ "%.2f"|format(order.shipping_cost) }} руб. + {% if order.discount and order.discount > 0 %} + {{ order.discount }}% + {% else %} + - + {% endif %} + {{ "%.2f"|format(order.display_total) }} руб. + + {{ order.status }} + + +
+ +
+
+

У этого клиента пока нет заказов

+ + Создать первый заказ + +
+
+ + +
+ + + + + + + +{% endblock %} \ No newline at end of file diff --git a/templates/orders_list.html b/templates/orders_list.html new file mode 100644 index 0000000..d46360d --- /dev/null +++ b/templates/orders_list.html @@ -0,0 +1,410 @@ +{% extends "base.html" %} + +{% block title %}Список заказов{% endblock %} + +{% block content %} + +
+

Список заказов

+
+ + +
+
+ + +
+
+
+
+
Всего заказов
+

{{ total_stats.total_orders or 0 }}

+
+
+
+
+
+
+
Общая сумма
+

{{ (total_stats.total_amount or 0)|int }} руб.

+
+
+
+
+ + + {% if orders %} +
+ + + + + + + + + + + + + + {% for order in orders %} + + + + + + + + + + {% endfor %} + +
IDДатаПоставщикИННТоварыСуммаСтатус
{{ order.id }}{{ order.order_date }} + + {{ order.client_name }} + + {{ order.client_inn or '-' }} + {% if order.product_name %} + + {{ order.product_name }} + {% elif order.products_list %} + + {{ order.products_list|truncate(50) }} + {% else %} + — + {% endif %} + {{ order.total_amount|int }} руб. + + {{ order.status }} + +
+
+ {% else %} +
+ + Нет данных о заказах. Вернуться к поставщикам. +
+ {% endif %} + + + + + + +{% endblock %} \ No newline at end of file