Файл с партнерами: Partners_import.xlsx
Файл с типами продукции: Product_type_import.xlsx
Файл с продуктами: Products_import.xlsx
Файл с продажами: Partner_products_import.xlsx



def check_database():
    """
    Функция подключается к базе данных и выводит количество записей
    в каждой из основных таблиц для проверки корректности загрузки данных.

    Таблицы для проверки:
        - PartnerType: типы партнеров
        - Partner: информация о партнерах
        - ProductType: типы продуктов
        - Product: информация о продуктах
        - 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()

    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,))

        # 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]

            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['Рейтинг'])
                           )

        # 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['Коэффициент типа продукции'])
                           )

        # 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]

            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()


# Основное меню программы
def display_menu():
    """Главное меню программы."""
    menu_options = [
        'КАРТОЧКИ ПАРТНЕРОВ (сортировка по рейтингу)',
        'КАРТОЧКИ ПАРТНЕРОВ (сортировка по скидкам)',
        'ИСТОРИЯ РЕАЛИЗАЦИИ',
        'ЗАПОЛНЕНИЕ БД из файлов',
        'ВЫХОД'
    ]

    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)

        elif choice == 'КАРТОЧКИ ПАРТНЕРОВ (сортировка по скидкам)':
            print("\n📊 КАРТОЧКИ ПАРТНЕРОВ (сортировка по скидкам)")
            print("═" * 70)
            partners = get_partners(sort_by='discount', ascending=False)
            print_partner_cards(partners)

        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


# Главная точка запуска программы
if __name__ == "__main__":
    display_menu()
