From c89fa73b3f15673cfa750269e5a72ba93fe4ad0e Mon Sep 17 00:00:00 2001 From: user_3d Date: Sat, 8 Nov 2025 09:13:49 +0500 Subject: [PATCH] 6677 --- main.py | 52 ++--- read.txt | 613 ++++++++++++++++++++++--------------------------------- 2 files changed, 260 insertions(+), 405 deletions(-) diff --git a/main.py b/main.py index 7eb8741..2387ce0 100644 --- a/main.py +++ b/main.py @@ -4,14 +4,12 @@ import os import sys import openpyxl - -#РОДИОНОВА +#Родионова def create_tables(db_connection): - # Функция создает структуру таблиц в базе данных + """Создает все необходимые таблицы в базе данных""" cursor = db_connection.cursor() - # Создание таблиц и индексов cursor.executescript(''' CREATE TABLE IF NOT EXISTS PartnerType ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -64,13 +62,13 @@ def create_tables(db_connection): CREATE INDEX IF NOT EXISTS idx_sale_partner ON Sale(partner_id); CREATE INDEX IF NOT EXISTS idx_sale_date ON Sale(sale_date); ''') - # Создание таблиц и индексов + db_connection.commit() print("✅ Таблицы успешно созданы") def calculate_discount(total_quantity): - # Функция рассчитывает скидку на основе объема продаж + """Рассчитывает скидку на основе общего количества проданной продукции""" if total_quantity >= 300000: return 15, '15% (более 300000 ед.)' elif total_quantity >= 50000: @@ -82,10 +80,9 @@ def calculate_discount(total_quantity): def get_partners(db_path='partners.db', sort_by='rating', ascending=False): - # Функция получает данные о партнерах из базы данных + """Получает данные о партнерах с возможностью сортировки""" try: conn = sqlite3.connect(db_path) - # Здесь прописан SQL-запрос для выборки данных о партнерах query = """ SELECT pt.type_name AS "Тип партнера", @@ -104,7 +101,7 @@ def get_partners(db_path='partners.db', sort_by='rating', ascending=False): GROUP BY p.id """ - # Применяем нужную сортировку и лимитируем количество записей + # Добавляем сортировку if sort_by == 'discount': query += " ORDER BY total_quantity" elif sort_by == 'rating': @@ -137,10 +134,9 @@ def get_partners(db_path='partners.db', sort_by='rating', ascending=False): def get_sales_history(db_path='partners.db', limit=50, sort_by='date_desc'): - # Функция получает историю продаж + """Получает историю реализации продукции с разными вариантами сортировки""" try: conn = sqlite3.connect(db_path) - # Здесь прописан SQL-запрос для выборки истории продаж query = """ SELECT s.sale_date AS "Дата продажи", @@ -157,7 +153,7 @@ def get_sales_history(db_path='partners.db', limit=50, sort_by='date_desc'): JOIN ProductType pt ON pr.product_type_id = pt.id """ - # Применяем сортировку и ограничение числа записей + # Добавляем сортировку по дате if sort_by == 'date_desc': query += " ORDER BY s.sale_date DESC, s.created_at DESC" elif sort_by == 'date_asc': @@ -179,11 +175,11 @@ def get_sales_history(db_path='partners.db', limit=50, sort_by='date_desc'): return None def print_partner_cards(partners_df): - # Функция выводит информацию о партнерах в красивой форме + """Выводит карточки партнеров в красивом формате""" if partners_df is None or partners_df.empty: print("📭 Нет данных о партнерах") return - # Красивый вывод карточек партнеров + for index, row in partners_df.iterrows(): print("╔" + "═" * 69 + "╗") print(f"║ {'КАРТОЧКА ПАРТНЕРА':^67} ║") @@ -204,7 +200,6 @@ def print_partner_cards(partners_df): address = address[:57] + "..." address_text = f"Адрес: {address}" - # Информация о партнере print(f"║ {type_text:<67} ║") print(f"║ {name_text:<67} ║") print(f"║ {director_text:<67} ║") @@ -222,11 +217,11 @@ def print_partner_cards(partners_df): def print_sales_cards(sales_df): - # Функция выводит историю продаж в табличном представлении + """Выводит карточки истории реализации в виде таблицы""" if sales_df is None or sales_df.empty: print("📭 Нет данных о продажах") return - # Рамка таблицы + print("╔" + "═" * 147 + "╗") print(f"║ {'ИСТОРИЯ РЕАЛИЗАЦИИ ПРОДУКЦИИ':^145} ║") print("╠" + "═" * 147 + "╣") @@ -238,7 +233,7 @@ def print_sales_cards(sales_df): )) print("╠" + "═" * 147 + "╣") - # Вывод данных о продажах + # Данные таблицы for index, row in sales_df.iterrows(): date = str(row['Дата продажи'])[:10] partner = row['Партнер'] @@ -251,14 +246,13 @@ def print_sales_cards(sales_df): print(f"║ {date} ║ {partner.ljust(16)} ║ {product.ljust(57)} ║ {article.ljust(8)} ║ {quantity.ljust(8)} ║ {price.ljust(10)} ║ {total.ljust(18)} ║") print("╚" + "═" * 147 + "╝") - # Закрывающая рамка таблицы # Итоги total_quantity = sales_df['Количество'].sum() total_amount = sales_df['Общая сумма'].sum() print(f"📊 ИТОГО: {len(sales_df)} продаж, {total_quantity:,} единиц, общая сумма: {total_amount:,.2f} руб.") def simple_choice(options): - # Простая функция выбора пункта меню + """Упрощенная функция выбора""" print("\n" + "=" * 50) print("ВЫБЕРИТЕ ОПЦИЮ:") print("=" * 50) @@ -281,17 +275,7 @@ def simple_choice(options): def check_database(): - """ - Функция подключается к базе данных и выводит количество записей - в каждой из основных таблиц для проверки корректности загрузки данных. - - Таблицы для проверки: - - PartnerType: типы партнеров - - Partner: информация о партнерах - - ProductType: типы продуктов - - Product: информация о продуктах - - Sale: данные о продажах - """ + """Проверяет загруженные данные в базе""" conn = sqlite3.connect('partners.db') try: cursor = conn.cursor() @@ -306,7 +290,7 @@ def check_database(): def load_data_from_files(): - # Загружает данные из Excel-файлов в базу данных + """Загружает данные из Excel файлов в базу данных""" conn = sqlite3.connect('partners.db') cursor = conn.cursor() @@ -411,7 +395,7 @@ def load_data_from_files(): def display_menu(): - # Основное меню программы + """Главное меню программы""" menu_options = [ 'КАРТОЧКИ ПАРТНЕРОВ (сортировка по рейтингу)', 'КАРТОЧКИ ПАРТНЕРОВ (сортировка по скидкам)', @@ -457,6 +441,6 @@ def display_menu(): print("\n👋 До свидания!") break -# Главная точка запуска программы + if __name__ == "__main__": display_menu() diff --git a/read.txt b/read.txt index a38e73b..4f69255 100644 --- a/read.txt +++ b/read.txt @@ -3,7 +3,193 @@ Файл с продуктами: Products_import.xlsx Файл с продажами: Partner_products_import.xlsx +def calculate_discount(total_quantity): + """ + Рассчитывает размер скидки на основе общего объема продаж. + Скидка определяется по следующим пороговым значениям: + - 15% при объеме от 300000 единиц + - 10% при объеме от 50000 до 300000 единиц + - 5% при объеме от 10000 до 50000 единиц + - 0% при объеме менее 10000 единиц + + Args: + total_quantity (int): Общее количество проданных единиц товара + + Returns: + tuple: Кортеж содержащий: + - int: Процент скидки (0-15) + - str: Текстовое описание скидки с диапазоном + """ + +def get_partners(db_path='partners.db', sort_by='rating', ascending=False): + """ + Получает список партнеров из базы данных с возможностью сортировки и расчетом скидок. + + Функция подключается к SQLite базе данных, извлекает информацию о партнерах, + рассчитывает скидки на основе общего объема продаж и предоставляет возможность + сортировки по различным критериям. + + Args: + db_path (str, optional): Путь к файлу базы данных. По умолчанию 'partners.db' + sort_by (str, optional): Поле для сортировки. По умолчанию 'rating'. + Допустимые значения: 'rating', 'name', 'type', 'discount' + ascending (bool, optional): Направление сортировки. По умолчанию False (убывание). + True - возрастание, False - убывание + + Returns: + pandas.DataFrame or None: DataFrame с данными партнеров, включая рассчитанные скидки, + или None в случае ошибки + + Raises: + sqlite3.Error: В случае ошибок при работе с базой данных + Exception: При других непредвиденных ошибках + + Example: + >>> df = get_partners(sort_by='discount', ascending=True) + >>> print(df[['Наименование партнера', 'Рейтинг', 'Скидка']]) + """ + +def get_sales_history(db_path='partners.db', limit=50, sort_by='date_desc'): + """ + Получает историю продаж из базы данных с возможностью сортировки и ограничения количества записей. + + Функция извлекает детальную информацию о продажах, включая даты, партнеров, + продукцию, количества и суммы. Поддерживает различные варианты сортировки + и ограничение количества возвращаемых записей. + + Args: + db_path (str, optional): Путь к файлу базы данных. По умолчанию 'partners.db' + limit (int, optional): Максимальное количество возвращаемых записей. + По умолчанию 50 + sort_by (str, optional): Критерий сортировки результатов. По умолчанию 'date_desc'. + Допустимые значения: + - 'date_desc': по дате продажи (новые сначала) + - 'date_asc': по дате продажи (старые сначала) + - 'quantity_desc': по количеству (по убыванию) + - 'amount_desc': по общей сумме (по убыванию) + + Returns: + pandas.DataFrame or None: DataFrame с историей продаж, содержащий колонки: + - Дата продажи + - Партнер + - Продукция + - Артикул + - Количество + - Цена за единицу + - Общая сумма + - Тип продукции + или None в случае ошибки + + Raises: + sqlite3.Error: В случае ошибок при работе с базой данных + Exception: При других непредвиденных ошибках + + Example: + >>> # Получить последние 100 продаж, отсортированных по сумме + >>> sales_df = get_sales_history(limit=100, sort_by='amount_desc') + >>> print(sales_df[['Партнер', 'Продукция', 'Общая сумма']].head()) + """ + + +def print_partner_cards(partners_df): + """ + Выводит в консоль красиво оформленные карточки партнеров. + + Функция принимает DataFrame с данными партнеров и отображает их в виде + структурированных карточек с рамкой. Каждая карточка содержит основную + информацию о партнере: тип, наименование, директор, рейтинг, объем продаж, + размер скидки, контактные данные и юридическую информацию. + + Args: + partners_df (pandas.DataFrame): DataFrame с данными партнеров, должен содержать колонки: + - 'Тип партнера' + - 'Наименование партнера' + - 'Директор' + - 'Рейтинг' + - 'total_quantity' + - 'Текст_скидки' + - 'Электронная почта' + - 'Телефон' + - 'ИНН' + - 'Юридический адрес' + + Returns: + None: Функция только выводит данные в консоль + + Example: + >>> partners = get_partners() + >>> print_partner_cards(partners) + + Note: + - Если передан пустой DataFrame или None, выводится сообщение об отсутствии данных + - Длинные адреса обрезаются до 60 символов с добавлением многоточия + - Форматирование чисел: разделители тысяч для объема продаж + - Между карточками добавляются пустые строки для лучшей читаемости + """ + + +def print_sales_cards(sales_df): + """ + Выводит в консоль таблицу с историей продаж в структурированном формате. + + Функция принимает DataFrame с данными о продажах и отображает их в виде + таблицы с рамкой. Включает заголовки, детальную информацию по каждой продаже + и итоговую статистику в нижней части. + + Args: + sales_df (pandas.DataFrame): DataFrame с данными о продажах, должен содержать колонки: + - 'Дата продажи' + - 'Партнер' + - 'Продукция' + - 'Артикул' + - 'Количество' + - 'Цена за единицу' + - 'Общая сумма' + + Returns: + None: Функция только выводит данные в консоль + + Example: + >>> sales = get_sales_history(limit=10) + >>> print_sales_cards(sales) + + Note: + - Если передан пустой DataFrame или None, выводится сообщение об отсутствии данных + - Дата обрезается до 10 символов (формат ГГГГ-ММ-ДД) + - Числовые значения форматируются с разделителями тысяч и двумя знаками после запятой + - В конце выводится сводная статистика по всем отображенным продажам + - Ширина таблицы фиксирована для обеспечения читаемости + """ + +def simple_choice(options): + """ + Предоставляет пользователю интерактивный выбор из списка опций. + + Функция отображает пронумерованный список доступных опций и запрашивает + у пользователя ввод номера выбранной опции. Обрабатывает различные + сценарии некорректного ввода и обеспечивает надежный выбор. + + Args: + options (list): Список строк с доступными опциями для выбора + + Returns: + str: Выбранная опция из переданного списка + + Raises: + SystemExit: При прерывании программы пользователем (Ctrl+C) + + Example: + >>> menu_options = ["Показать партнеров", "История продаж", "Выход"] + >>> choice = simple_choice(menu_options) + >>> print(f"Выбрано: {choice}") + + Note: + - Опции нумеруются начиная с 1 + - Функция обрабатывает нечисловой ввод и числа вне диапазона + - Поддерживает обработку прерывания программы (KeyboardInterrupt) + - Цикл продолжается до получения корректного ввода + """ def check_database(): """ @@ -18,389 +204,74 @@ def check_database(): - Sale: данные о продажах """ - - - -# Импортируем библиотеку SQLite3 для взаимодействия с базами данных SQLite -import sqlite3 -# Подключаем библиотеку Pandas для обработки и анализа данных -import pandas as pd -# Подключаем модуль операционной системы Python для работы с файлами и путями -import os -# Подключаем модуль sys для взаимодействия с интерпретатором Python и системой -import sys -# Подключаем библиотеку OpenPyXL для чтения и записи файлов Excel формата .xlsx -import openpyxl - - -import sqlite3 -import pandas as pd -import os -import sys -import openpyxl - -# Функция создает структуру таблиц в базе данных -def create_tables(db_connection): - """Создает все необходимые таблицы в базе данных.""" - cursor = db_connection.cursor() - - # Создание таблиц и индексов - cursor.executescript(''' - ... - ''') # Создание таблиц и индексов - 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_partners(db_path='partners.db', sort_by='rating', ascending=False): - """Получает данные о партнерах с возможностью сортировки.""" - try: - conn = sqlite3.connect(db_path) - query = """ - ... - """ # Здесь прописан SQL-запрос для выборки данных о партнерах - - # Применяем нужную сортировку и лимитируем количество записей - if sort_by == 'discount': - query += " ORDER BY total_quantity" - elif sort_by == 'rating': - query += " ORDER BY p.rating" - elif sort_by == 'name': - query += " ORDER BY p.name" - elif sort_by == 'type': - query += " ORDER BY pt.type_name, p.name" - else: - query += " ORDER BY p.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]) - - return df - - except sqlite3.Error as e: - print(f"❌ Ошибка базы данных: {e}") - return None - except Exception as e: - print(f"❌ Общая ошибка: {e}") - return None - - -# Функция получает историю продаж -def get_sales_history(db_path='partners.db', limit=50, sort_by='date_desc'): - """Получает историю реализации продукции с разными вариантами сортировки.""" - try: - conn = sqlite3.connect(db_path) - query = """ - ... - """ # Здесь прописан SQL-запрос для выборки истории продаж - - # Применяем сортировку и ограничение числа записей - if sort_by == 'date_desc': - query += " ORDER BY s.sale_date DESC, s.created_at DESC" - elif sort_by == 'date_asc': - query += " ORDER BY s.sale_date ASC, s.created_at ASC" - elif sort_by == 'quantity_desc': - query += " ORDER BY s.quantity DESC" - elif sort_by == 'amount_desc': - query += " ORDER BY (s.quantity * s.sale_price) DESC" - else: - query += " ORDER BY s.sale_date DESC, s.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_partner_cards(partners_df): - """Выводит карточки партнеров в красивом формате.""" - if partners_df is None or partners_df.empty: - print("📭 Нет данных о партнерах") - return - - # Красивый вывод карточек партнеров - for index, row in partners_df.iterrows(): - # Оформление рамки вокруг карточки - print("╔" + "═" * 69 + "╗") - print(f"║ {'КАРТОЧКА ПАРТНЕРА':^67} ║") - print("╠" + "═" * 69 + "╣") - - # Информация о партнере - print(f"║ Тип: {row['Тип партнера']}{' ':<63}║") - print(f"║ Наименование: {row['Наименование партнера']}{' ':<50}║") - print(f"║ Директор: {row['Директор']}{' ':<61}║") - print(f"║ Рейтинг: {row['Рейтинг']}{' ':<63}║") - print(f"║ Продано единиц: {row['total_quantity']:,}{' ':<52}║") - print(f"║ Скидка: {row['Текст_скидки']}{' ':<58}║") - print(f"║ {' ':<67}║") - print(f"║ Электронная почта: {row['Электронная почта']}{' ':<45}║") - print(f"║ Телефон: {row['Телефон']}{' ':<61}║") - print(f"║ {' ':<67}║") - print(f"║ ИНН: {row['ИНН']}{' ':<63}║") - print(f"║ Адрес: {row['Юридический адрес']}{' ':<59}║") - print("╚" + "═" * 69 + "╝") - print() - - -# Функция выводит историю продаж в табличном представлении -def print_sales_cards(sales_df): - """Выводит карточки истории реализации в виде таблицы.""" - if sales_df is None or sales_df.empty: - print("📭 Нет данных о продажах") - return - - # Рамка таблицы - print("╔" + "═" * 147 + "╗") - print(f"║ {'ИСТОРИЯ РЕАЛИЗАЦИИ ПРОДУКЦИИ':^145} ║") - print("╠" + "═" * 147 + "╣") - - # Заголовок таблицы - headers = ["Дата", "Партнер", "Продукция", "Артикул", "Кол-во", "Цена", "Сумма"] - print("║ {:<12} {:<18} {:<59} {:<3} {:>9} {:>8} {:>13} ║".format(*headers)) - print("╠" + "═" * 147 + "╣") - - # Вывод данных о продажах - for index, row in sales_df.iterrows(): - date = str(row['Дата продажи'])[:10] - partner = row['Партнер'] - product = row['Продукция'] - article = str(row['Артикул']) - quantity = f"{row['Количество']:,}" - price = f"{row['Цена за единицу']:,.2f}" - total = f"{row['Общая сумма']:,.2f}" - - print(f"║ {date} ║ {partner.ljust(16)} ║ {product.ljust(57)} ║ {article.ljust(8)} ║ {quantity.ljust(8)} ║ {price.ljust(10)} ║ {total.ljust(18)} ║") - - # Закрывающая рамка таблицы - print("╚" + "═" * 147 + "╝") - - # Итоговая статистика - total_quantity = sales_df['Количество'].sum() - total_amount = sales_df['Общая сумма'].sum() - print(f"📊 ИТОГО: {len(sales_df)} продаж, {total_quantity:,} единиц, общая сумма: {total_amount:,.2f} руб.") - - -# Простая функция выбора пункта меню -def simple_choice(options): - """Упрощенная функция выбора.""" - print("\n" + "=" * 50) - print("ВЫБЕРИТЕ ОПЦИЮ:") - print("=" * 50) - 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('partners.db') - try: - cursor = conn.cursor() - print("\n🔍 Проверка загруженных данных:") - tables = ['PartnerType', 'Partner', 'ProductType', 'Product', 'Sale'] - for table in tables: - cursor.execute(f"SELECT COUNT(*) FROM {table}") - count = cursor.fetchone()[0] - print(f" {table}: {count} записей") - finally: - conn.close() - - -# Загружает данные из Excel-файлов в базу данных def load_data_from_files(): - """Загружает данные из Excel файлов в базу данных.""" - conn = sqlite3.connect('partners.db') - cursor = conn.cursor() + """ + Загружает данные из Excel-файлов в базу данных SQLite. - try: - # 1. Загрузка типов партнеров - print("\n1. 📊 Загрузка типов партнеров...") - partners_df = pd.read_excel(input("Файл с партнерами: ")) - partner_types = partners_df['Тип партнера'].unique() - for partner_type in partner_types: - cursor.execute("INSERT OR IGNORE INTO PartnerType (type_name) VALUES (?)", (partner_type,)) + Функция выполняет пошаговую загрузку данных из четырех Excel-файлов: + - Файл с партнерами + - Файл с типами продукции + - Файл с продуктами + - Файл с продажами - # 2. Загрузка партнеров - print("2. 👥 Загрузка партнеров...") - for _, row in partners_df.iterrows(): - cursor.execute("SELECT id FROM PartnerType WHERE type_name = ?", (row['Тип партнера'],)) - partner_type_id = cursor.fetchone()[0] + Процесс загрузки включает: + 1. Загрузку типов партнеров + 2. Загрузку данных партнеров + 3. Загрузку типов продукции с коэффициентами + 4. Загрузку информации о продуктах + 5. Загрузку истории продаж с валидацией связей - cursor.execute(""" - INSERT OR IGNORE INTO Partner - (partner_type_id, name, director, email, phone, legal_address, inn, rating) - VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", - (partner_type_id, row['Наименование партнера'], row['Директор'], - row['Электронная почта партнера'], row['Телефон партнера'], - row['Юридический адрес партнера'], row['ИНН'], row['Рейтинг']) - ) + Returns: + None: Функция выполняет операции с базой данных и выводит результаты в консоль - # 3. Загрузка типов продукции - print("3. 📦 Загрузка типов продукции...") - product_type_df = pd.read_excel(input("Файл с типами продукции: ")) - for _, row in product_type_df.iterrows(): - cursor.execute("INSERT OR IGNORE INTO ProductType (type_name, coefficient) VALUES (?, ?)", - (row['Тип продукции'], row['Коэффициент типа продукции']) - ) + Raises: + Exception: При ошибках чтения файлов или операций с базой данных - # 4. Загрузка продуктов - print("4. 🏷️ Загрузка продуктов...") - products_df = pd.read_excel(input("Файл с продуктами: ")) - for _, row in products_df.iterrows(): - cursor.execute("SELECT id FROM ProductType WHERE type_name = ?", (row['Тип продукции'],)) - product_type_id = cursor.fetchone()[0] + Example: + >>> load_data_from_files() + 📁 Введите имена файлов: + Файл с партнерами: partners.xlsx + Файл с типами продукции: product_types.xlsx + Файл с продуктами: products.xlsx + Файл с продажами: sales.xlsx - cursor.execute(""" - INSERT OR IGNORE INTO Product - (product_type_id, product_name, article, min_partner_price) - VALUES (?, ?, ?, ?)""", - (product_type_id, row['Наименование продукции'], - row['Артикул'], row['Минимальная стоимость для партнера']) - ) - - # 5. Загрузка продаж - print("5. 💰 Загрузка продаж...") - sales_df = pd.read_excel(input("Файл с продажами: ")) - loaded_sales = 0 - - for _, row in sales_df.iterrows(): - # Находим ID продукта - cursor.execute("SELECT id FROM Product WHERE product_name = ?", (row['Продукция'],)) - product_result = cursor.fetchone() - if not product_result: - print(f" ⚠️ Продукт не найден: {row['Продукция']}") - continue - product_id = product_result[0] - - # Находим ID партнера - cursor.execute("SELECT id FROM Partner WHERE name = ?", (row['Наименование партнера'],)) - partner_result = cursor.fetchone() - if not partner_result: - print(f" ⚠️ Партнер не найден: {row['Наименование партнера']}") - continue - partner_id = partner_result[0] - - # Получаем цену продажи - cursor.execute("SELECT min_partner_price FROM Product WHERE id = ?", (product_id,)) - min_price_result = cursor.fetchone() - sale_price = min_price_result[0] if min_price_result else 0 - - # Преобразуем дату - sale_date = pd.to_datetime(row['Дата продажи']).strftime('%Y-%m-%d') - - # Вставляем продажу - cursor.execute(""" - INSERT INTO Sale - (product_id, partner_id, quantity, sale_date, sale_price) - VALUES (?, ?, ?, ?, ?)""", - (product_id, partner_id, row['Количество продукции'], sale_date, sale_price) - ) - loaded_sales += 1 - - conn.commit() - print(f"✅ Данные успешно загружены! Загружено {loaded_sales} продаж") - check_database() -Файл с партнерами: Partners_import.xlsx -Файл с типами продукции: Product_type_import.xlsx -Файл с продуктами: Products_import.xlsx -Файл с продажами: Partner_products_import.xlsx - - except Exception as e: - print(f"❌ Ошибка при загрузке данных: {e}") - conn.rollback() - finally: - conn.close() + Note: + - Использует INSERT OR IGNORE для избежания дубликатов + - Проверяет существование связей перед вставкой продаж + - Выводит прогресс загрузки и информационные сообщения + - В случае ошибки выполняет откат транзакции + - В конце вызывает проверку целостности данных + """ -# Основное меню программы -def display_menu(): - """Главное меню программы.""" - menu_options = [ - 'КАРТОЧКИ ПАРТНЕРОВ (сортировка по рейтингу)', - 'КАРТОЧКИ ПАРТНЕРОВ (сортировка по скидкам)', - 'ИСТОРИЯ РЕАЛИЗАЦИИ', - 'ЗАПОЛНЕНИЕ БД из файлов', - 'ВЫХОД' - ] + def display_menu(): + """ + Главное меню приложения для управления партнерами и продажами. - while True: - choice = simple_choice(menu_options) + Функция предоставляет интерактивный интерфейс для работы с системой: + - Просмотр карточек партнеров с различной сортировкой + - Просмотр истории продаж + - Загрузка данных из файлов + - Выход из приложения - if choice == 'КАРТОЧКИ ПАРТНЕРОВ (сортировка по рейтингу)': - print("\n🎯 КАРТОЧКИ ПАРТНЕРОВ (сортировка по рейтингу)") - print("═" * 70) - partners = get_partners(sort_by='rating', ascending=False) - print_partner_cards(partners) + Returns: + None: Функция управляет основным потоком выполнения приложения - elif choice == 'КАРТОЧКИ ПАРТНЕРОВ (сортировка по скидкам)': - print("\n📊 КАРТОЧКИ ПАРТНЕРОВ (сортировка по скидкам)") - print("═" * 70) - partners = get_partners(sort_by='discount', ascending=False) - print_partner_cards(partners) + Example: + >>> display_menu() + ================================================== + ВЫБЕРИТЕ ОПЦИЮ: + ================================================== + 1. КАРТОЧКИ ПАРТНЕРОВ (сортировка по рейтингу) + 2. КАРТОЧКИ ПАРТНЕРОВ (сортировка по скидкам) + 3. ИСТОРИЯ РЕАЛИЗАЦИИ + 4. ЗАПОЛНЕНИЕ БД из файлов + 5. ВЫХОД - elif choice == 'ИСТОРИЯ РЕАЛИЗАЦИИ': - print("\n📈 ИСТОРИЯ РЕАЛИЗАЦИИ ПРОДУКЦИИ") - print("═" * 70) - sales = get_sales_history(limit=50) - print_sales_cards(sales) - - elif choice == 'ЗАПОЛНЕНИЕ БД из файлов': - if os.path.exists('partners.db'): - os.remove('partners.db') - print("🗑️ База данных partners.db удалена") - else: - print("ℹ️ База данных partners.db не найдена, создаем новую") - - conn = sqlite3.connect('partners.db') - create_tables(conn) - conn.close() - load_data_from_files() - - elif choice == 'ВЫХОД': - print("\n👋 До свидания!") - break + Note: + - При выборе загрузки данных существующая БД удаляется и создается заново + - Использует циклическое меню до выбора опции выхода + - Каждая опция сопровождается визуальным разделителем для лучшей читаемости + """ -# Главная точка запуска программы -if __name__ == "__main__": - display_menu()