Скачиваний:
19
Добавлен:
29.03.2025
Размер:
124 Кб
Скачать
# -*- coding: utf-8 -*-

import sqlite3

path = "C:/Users/admin/source/repos/UNIVERSITY_repos/4 course/7 sem/mispris/2-1/furniture.db"
# path = "/home/user/repos/mispris/3/furniture.db"

conn = sqlite3.connect(path)
cursor = conn.cursor()
print("\n\nDB has been created/connected\n")

conn.execute("PRAGMA foreign_keys = ON")



def create_unit_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS unit (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            unit_name TEXT UNIQUE,
            unit_name_short TEXT UNIQUE
        )
    ''')
    conn.commit()

def create_terminal_classifier_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS terminal_classifier (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            id_parent INTEGER CHECK (id_parent != id),
            terminal_classifier_name TEXT NOT NULL,
            terminal_classifier_short_name TEXT NOT NULL,
            id_unit INTEGER,
            priority INTEGER NOT NULL DEFAULT 0,
            FOREIGN KEY (id_unit) REFERENCES unit(id) ON DELETE CASCADE,
            FOREIGN KEY (id_parent) REFERENCES terminal_classifier(id) ON DELETE CASCADE
        )
    ''')
    conn.commit()

def create_enum_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS enum (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            enum_id INTEGER,
            enum_name TEXT NOT NULL,
            enum_short_name TEXT NOT NULL,
            enum_description TEXT,
            real_value REAL,
            int_value INTEGER,
            pic_value TEXT,
            priority INTEGER NOT NULL DEFAULT 0,
            FOREIGN KEY (enum_id) REFERENCES terminal_classifier(id) ON DELETE CASCADE
        )
    ''')
    conn.commit()

def create_product_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS product (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            id_category INTEGER,
            product_name TEXT NOT NULL,
            quantity INTEGER DEFAULT 0,
            price REAL DEFAULT 0,
            unit_value REAL,
            FOREIGN KEY (id_category) REFERENCES terminal_classifier(id) ON DELETE CASCADE
        )
    ''')
    conn.commit()

def create_param_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS param (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            param_name TEXT NOT NULL,
            param_short_name TEXT NOT NULL,
            unit_id INTEGER,
            min_val REAL,
            max_val REAL,
            FOREIGN KEY (unit_id) REFERENCES unit(id) ON DELETE CASCADE
        )
    ''')
    conn.commit()

def create_class_param_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS class_param (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            param_id INTEGER NOT NULL,
            class_param_id INTEGER,
            param_class_name TEXT NOT NULL,
            param_class_short_name TEXT NOT NULL,
            priority INTEGER NOT NULL,
            FOREIGN KEY (param_id) REFERENCES param(id) ON DELETE CASCADE,
            FOREIGN KEY (class_param_id) REFERENCES terminal_classifier(id) ON DELETE CASCADE
        )
    ''')
    conn.commit()

def create_prod_param_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS prod_param (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            prod_id INTEGER NOT NULL,
            param_id INTEGER NOT NULL,
            int_value INTEGER,
            str_value TEXT,
            real_value REAL,
            enum_id INTEGER,
            UNIQUE(prod_id, param_id),
            FOREIGN KEY (enum_id) REFERENCES enum(id),
            FOREIGN KEY (prod_id) REFERENCES product(id) ON DELETE CASCADE,
            FOREIGN KEY (param_id) REFERENCES param(id) ON DELETE CASCADE
        )
    ''')
    conn.commit()

##################################### 2-1 lab #####################################

def create_acceptable_components_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS acceptable_components (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            class_id INTEGER NOT NULL,
            component_id INTEGER NOT NULL,
            UNIQUE(class_id, component_id),
            FOREIGN KEY (class_id) REFERENCES terminal_classifier(id) ON DELETE CASCADE,
            FOREIGN KEY (component_id) REFERENCES terminal_classifier(id) ON DELETE CASCADE
        )
    ''')
    conn.commit()

def create_prod_position_union_table():
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS prod_position_union (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            prod_id INTEGER NOT NULL,
            comp_id INTEGER NOT NULL,
            quantity INTEGER NOT NULL CHECK (quantity > 0),
            UNIQUE(prod_id, comp_id),
            FOREIGN KEY (prod_id) REFERENCES product(id) ON DELETE CASCADE,
            FOREIGN KEY (comp_id) REFERENCES product(id) ON DELETE CASCADE
        )
    ''')
    conn.commit()

##################################### 2-1 lab #####################################



# def create_agr_class_table():
#     cursor.execute('''
#         CREATE TABLE IF NOT EXISTS agr_class (
#             id INTEGER PRIMARY KEY AUTOINCREMENT,
#             agr_class_name TEXT NOT NULL
#         )
#     ''')
#     conn.commit()

# def create_agr_pos_table():
#     cursor.execute('''
#         CREATE TABLE IF NOT EXISTS agr_pos (
#             id INTEGER PRIMARY KEY AUTOINCREMENT,
#             agr_pos_name TEXT NOT NULL,
#             id_agr_class INTEGER NOT NULL,
#             id_prod INTEGER NOT NULL,
#             FOREIGN KEY (id_agr_class) REFERENCES agr_class(id),
#             FOREIGN KEY (id_prod) REFERENCES product(id)
#         )
#     ''')
#     conn.commit()

# def create_agr_pos_list_table():
#     cursor.execute('''
#         CREATE TABLE IF NOT EXISTS agr_pos_list (
#             id INTEGER PRIMARY KEY AUTOINCREMENT,
#             id_prod_param INTEGER NOT NULL,
#             id_agr_class INTEGER NOT NULL,
#             FOREIGN KEY (id_agr_class) REFERENCES agr_class(id),
#             FOREIGN KEY (id_prod_param) REFERENCES prod_param(prod_id)
#         )
#     ''')
#     conn.commit()

def creating_tables():
    create_unit_table()
    create_terminal_classifier_table()
    create_enum_table()
    create_product_table()

    create_param_table()
    create_class_param_table()
    create_prod_param_table()

    #2-1 lab#
    create_acceptable_components_table()
    create_prod_position_union_table()
    #2-1 lab#

    # create_agr_class_table()
    # create_agr_pos_table()
    # create_agr_pos_list_table()

creating_tables()



def delete_data(tables_order):
    try:
        cursor.execute("PRAGMA foreign_keys = OFF;")  # Disable foreign key checks
        for table_name in tables_order:
            cursor.execute(f"DELETE FROM {table_name};")
        conn.commit()
        cursor.execute("PRAGMA foreign_keys = ON;")  # Re-enable foreign key checks
    except sqlite3.Error as ex:
        print(f"Произошла ошибка при удалении данных: {ex}")
        conn.rollback()


def dropAllTables():
    try:
        cursor.execute("PRAGMA foreign_keys = OFF;")  # Disable foreign key checks

        # Define the correct order for deleting data and dropping tables
        tables_order = [
            'prod_param',          # Child of 'product', 'param', 'enum'
            'class_param',         # Child of 'param', 'terminal_classifier'
            'acceptable_components',  # Child of 'terminal_classifier'
            'prod_position_union', # Child of 'product'
            'product',             # Child of 'terminal_classifier'
            'enum',                # Child of 'terminal_classifier'
            'param',               # Child of 'unit'
            'terminal_classifier', # Child of 'unit'
            'unit'                 # No dependencies
        ]

        # Delete data from all tables
        delete_data(tables_order)

        # Drop all tables in the correct order
        for table_name in tables_order:
            cursor.execute(f"DROP TABLE IF EXISTS {table_name};")

        conn.commit()
        cursor.execute("PRAGMA foreign_keys = ON;")  # Re-enable foreign key checks
        print("Данные успешно удалены")
        print("Таблицы успешно удалены")
    except sqlite3.Error as ex:
        print(f"Произошла ошибка при удалении таблиц: {ex}")
        conn.rollback()




def is_category_exists(terminal_classifier_name):
    cursor.execute("SELECT COUNT(*) FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
    count = cursor.fetchone()[0]
    res = count > 0

    return res

def is_category_id_exists(cl_id):
    cursor.execute("SELECT COUNT(*) FROM terminal_classifier WHERE id = ?", (cl_id,))
    count = cursor.fetchone()[0]
    res = count > 0

    return res

def is_product_exist(product_name):
    cursor.execute("SELECT COUNT(*) FROM product WHERE product_name = ?", (product_name,))
    count = cursor.fetchone()[0]
    res = count > 0

    return res

def is_unit_exist(unit_name_short):
    cursor.execute("SELECT COUNT(*) FROM unit WHERE unit_name_short = ?", (unit_name_short,))
    count = cursor.fetchone()[0]
    res = count > 0

    return res


def add_unit(unit_name, unit_name_short):
    try:
        if not is_unit_exist(unit_name_short):
            cursor.execute('''
              INSERT INTO unit (unit_name, unit_name_short)
              VALUES (?, ?)
            ''', (unit_name, unit_name_short))
            conn.commit()

            print('Единица измерения успешно добавлена.')
        else:
            print('Единица измерения с таким названием уже существует.')

    except Exception as _ex:
        print(f'Error {_ex} - произошла ошибка при добавлении единицы измерения')


def add_category(terminal_classifier_name, terminal_classifier_short_name, id_parent=None, id_unit=None):
    # try:
        if is_category_exists(terminal_classifier_name):
            print(f'Категория с названием {terminal_classifier_name} уже существует.')
            return
        if id_unit:
            cursor.execute("SELECT COUNT(*) FROM unit WHERE id = ?", (id_unit,))
            unit_check_exist = cursor.fetchone()[0]
            if not unit_check_exist:
                print(f'Указанного id единицы измерения не существует!')
                return

        cursor.execute('''
            INSERT INTO terminal_classifier (terminal_classifier_name, terminal_classifier_short_name, id_parent, id_unit)
            VALUES (?, ?, ?, ?)
        ''', (terminal_classifier_name, terminal_classifier_short_name, id_parent, id_unit))

        conn.commit()
        print('Категория успешно добавлена.')
    # except Exception as _ex:
    #     print(f'Error {_ex} - ошибка при добавлении категории.')


def add_subcategory(terminal_classifier_name, subterminal_classifier_name, subterminal_classifier_short_name, id_unit=None):
    try:

        if is_category_exists(terminal_classifier_name):
            # Получаем Id категории
            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
            id_parent_to_set = cursor.fetchone()[0]

            add_category(subterminal_classifier_name, subterminal_classifier_short_name, id_parent_to_set, id_unit)
            conn.commit()
            print("Подкатегория успешно добавлена.")

        else:
            print("Указанная категория/подкатегория не существует.")
    except Exception as _ex:
        print(f"Произошла ошибка при добавлении подкатегории: {_ex}")


def edit_category(id, terminal_classifier_name_new, terminal_classifier_short_name_new, id_unit=None):
    try:
        cursor.execute('SELECT COUNT(*) FROM terminal_classifier WHERE id = ?', (id,))
        if cursor.fetchone()[0] == 0:
            raise ValueError(f"Запись с id={id} не найдена в таблице terminal_classifier.")

        if id_unit is not None:
            cursor.execute('SELECT COUNT(*) FROM unit WHERE id = ?', (id_unit,))
            if cursor.fetchone()[0] == 0:
                raise ValueError(f"Запись с id_unit={id_unit} не найдена в таблице unit.")

        cursor.execute('SELECT COUNT(*) FROM terminal_classifier WHERE terminal_classifier_name = ? AND id != ?', (terminal_classifier_name_new, id))
        if cursor.fetchone()[0] > 0:
            raise ValueError(f"Новое полное имя '{terminal_classifier_name_new}' уже занято.")

        cursor.execute('SELECT COUNT(*) FROM terminal_classifier WHERE terminal_classifier_short_name = ? AND id != ?', (terminal_classifier_short_name_new, id))
        if cursor.fetchone()[0] > 0:
            raise ValueError(f"Новое короткое имя '{terminal_classifier_short_name_new}' уже занято.")

        cursor.execute('''
            UPDATE terminal_classifier
            SET terminal_classifier_name = ?,
                terminal_classifier_short_name = ?,
                id_unit = ?
            WHERE id = ?
        ''', (terminal_classifier_name_new, terminal_classifier_short_name_new, id_unit, id))

        # Подтверждаем изменения
        conn.commit()

    except Exception as _ex:
        print(f"Произошла ошибка при изменении категории: {_ex}")


def add_product(product_name, terminal_classifier_name, quantity, price, unit_value ):
    try:
        if is_category_exists(terminal_classifier_name):

            # Получаем id подкатегории по ее названию
            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
            category_id = cursor.fetchone()[0]

            # Добавляем новое изделие в таблицу Изделие
            cursor.execute("INSERT INTO product (id_category, product_name, quantity, price, unit_value) VALUES (?, ?, ?, ?, ?)",
                        (category_id, product_name, quantity, price, unit_value))
            conn.commit()
            print("Изделие успешно добавлено.")

        else:
            print("Указанная подкатегория не существует.")

    except Exception as _ex:
        print(f"Произошла ошибка при добавлении изделия: {_ex}")


def get_all_categories():
    try:
        cursor.execute("SELECT * FROM terminal_classifier")
        categories_names = cursor.fetchall()

        return categories_names

    except Exception as _ex:
        print(f"Произошла ошибка при получении категорий: {_ex}")
        return None


def get_all_products():
    try:
        cursor.execute("SELECT * FROM product")
        products_names = cursor.fetchall()

        return products_names

    except Exception as _ex:
        print(f"Произошла ошибка при получении товаров: {_ex}")
        return None


def product_update_price(product_name, new_price):
    try:

        if is_product_exist(product_name):
            cursor.execute("UPDATE product SET price = ? WHERE product_name = ?", (new_price, product_name))
            conn.commit()
            print('Цена изделия успешно обновлена.')
        else:
            print('Указанное изделие не существует.')

    except Exception as _ex:
        print(f"Произошла ошибка при обновлении цены изделия: {_ex}")


def product_update_quantity(product_name, new_quantity):
    try:

        if is_product_exist(product_name):
            cursor.execute("UPDATE product SET quantity = ? WHERE product_name = ?", (new_quantity, product_name))
            conn.commit()
            print('Количество изделия успешно обновлено.')
        else:
            print('Указанное изделие не существует.')

    except Exception as _ex:
        print(f"Произошла ошибка при обновлении цены изделия: {_ex}")


def change_product_category(product_name, new_category):
    try:

        if is_category_exists(new_category):
            # Получаем идентификатор новой категории
            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (new_category,))
            new_category_id = cursor.fetchone()[0]

            # Обновляем категорию у изделия
            cursor.execute("UPDATE product SET id_category = ? WHERE product_name = ?", (new_category_id, product_name))
            conn.commit()
            print('Категория изделия успешно изменена.')
        else:
            print('Указанная новая подкатегория не существует.')

    except Exception as _ex:
        print(f"Произошла ошибка при изменении подкатегории изделия: {_ex}")





def change_product_unit_value(product_name, unit_value):
    try:
        if is_product_exist(product_name):
            cursor.execute("UPDATE product SET unit_value = ? WHERE product_name = ?", (unit_value, product_name))
            conn.commit()
            print('Значение единицы измерения изделия успешно изменено.')

        else:
            print('Указанное изделие не существует.')

    except Exception as _ex:
        print(f"Произошла ошибка при изменении значения единицы измерения изделия: {_ex}")


def delete_product_unit_value(product_name):
    try:
        if is_product_exist(product_name):
            # cursor.execute("SELECT id_unit FROM product WHERE product_name = ?", (product_name,))
            # delete_unit_id = cursor.fetchone()[0]

            cursor.execute("UPDATE product SET unit_value = ? WHERE product_name = ?", (None, product_name))
            conn.commit()
            print('Значение единицы измерения изделия успешно удалено.')

        else:
            print('Указанное изделие не существует.')

    except Exception as _ex:
        print(f"Произошла ошибка при удалении значения единицы измерения изделия: {_ex}")



def is_enum_exist(terminal_classifier_name):
    try:
        cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
        check_if_exist = cursor.fetchone()

        return check_if_exist

    except Exception as _ex:
        print(f"Произошла ошибка при проверке перечисления на существование: {_ex}")


def is_enum_pos_exist(enum_name):
    try:
        cursor.execute("SELECT id FROM enum WHERE enum_name = ?", (enum_name,))
        check_if_exist = cursor.fetchone()

        if check_if_exist:
            return True
        else:
            return False

    except Exception as _ex:
        print(f"Произошла ошибка при проверке перечисления на существование: {_ex}")



def add_enum_pos(enum_id, enum_name, enum_short_name, enum_description=None, real_value=None, int_value=None, pic_value=None, priority=None):

    try:
        # Check if enum already exists in terminal_classifier
        if is_enum_pos_exist(enum_name):
            print("Указанное перечисление уже существует.")
            return

        # Get next priority if not provided
        if priority is None:
            cursor.execute("SELECT COALESCE(MAX(priority), 0) + 1 FROM enum", ())
            priority = cursor.fetchone()[0]

        # UPDATE via id
        cursor.execute("INSERT INTO enum (enum_id, enum_name, enum_short_name, enum_description, real_value, int_value, pic_value, priority) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
                                (enum_id, enum_name, enum_short_name, enum_description, real_value, int_value, pic_value,  priority))

        conn.commit()

        print('Перечисление успешно добавлено.')

    except Exception as _ex:
        print(f"Произошла ошибка при добавлении перечисления: {_ex}")


def delete_enum_classification(terminal_classifier_name):
    try:

        if is_enum_exist(terminal_classifier_name):
            # Получаем идентификатор удаляемого класса перечислений
            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
            delete_id = cursor.fetchone()[0]

            # Перемещаем все классы перечисления удаляемого класса перечисления в класс-перечисление "неопределенные"
            cursor.execute("UPDATE terminal_classifier SET id_parent = (SELECT id FROM terminal_classifier WHERE terminal_classifier_name = 'неопределенные') WHERE id_parent = ?", (delete_id,))

            # Перемещаем все перечисления удаляемой категории в категорию "неопределенные"
            cursor.execute("UPDATE enum SET enum_id = (SELECT id FROM terminal_classifier WHERE terminal_classifier_name = 'неопределенные') WHERE enum_id = ?", (delete_id,))

            # Удаляем класс-перечисление
            cursor.execute("DELETE FROM terminal_classifier WHERE id = ?", (delete_id,))
            conn.commit()

            print('Класс перечисления успешно удален.')
        else:
            print('Указанный класс перечисления не существует.')

    except Exception as _ex:
        print(f"Произошла ошибка при удалении класса перечисления: {_ex}")


def delete_enum_pos(enum_name):
    try:

        # Удаление перечисления
        cursor.execute("DELETE FROM enum WHERE enum_name = ?", (enum_name,))
        rows_deleted = cursor.rowcount

        if rows_deleted > 0:
            print('Перечисление успешно удалено.')
        else:
            print('Перечисление с указанным названием не найдено.')

        conn.commit()

    except Exception as _ex:
        print(f"Произошла ошибка при удалении перечисления: {_ex}")



def change_enum_pos(id, new_enum_name, new_enum_short_name, new_enum_description=None, new_real_value=None, new_int_value=None, new_pic_value=None):

    try:

        cursor.execute("SELECT enum_name FROM enum WHERE id = ?", (id,))
        old_name_to_check = cursor.fetchone()[0]

        if is_enum_pos_exist(old_name_to_check):

            cursor.execute("UPDATE enum SET enum_name = ?, enum_short_name = ?, enum_description = ?, real_value = ?, int_value = ?, pic_value = ? WHERE id = ?",
                                (new_enum_name, new_enum_short_name, new_enum_description, new_real_value, new_int_value, new_pic_value, id))
            conn.commit()

            print('Перечисление изменено.')

        else:
            print('Указаное перечисление не найдено.')
            return

    except Exception as _ex:
        print(f"Произошла ошибка при изменении перечисления: {_ex}")


def edit_enum_pos_priority(enum_pos_id, new_priority):
    try:
        # Получаем enum_id для указанного enum_pos_id
        cursor.execute("SELECT enum_id FROM enum WHERE id = ?", (enum_pos_id,))
        result = cursor.fetchone()
        if result is None:
            print('Указанное enum_pos_id не найдено.')
            return None
        enum_id = result[0]

        # Проверяем, существует ли уже запись с таким priority для данного enum_id
        cursor.execute("""
            SELECT count(*)
            FROM enum
            WHERE priority = ?
            AND enum_id = ?
        """, (new_priority, enum_id))
        count = cursor.fetchone()[0]

        if count == 0:
            # Обновляем priority
            cursor.execute("""
                UPDATE enum
                SET priority = ?
                WHERE id = ?
            """, (new_priority, enum_pos_id))
        else:
            # Смещаем приоритеты и обновляем нужную запись
            cursor.execute("""
                UPDATE enum
                SET priority = priority + 1
                WHERE priority >= ?
                AND enum_id = ?
            """, (new_priority, enum_id))

            cursor.execute("""
                UPDATE enum
                SET priority = ?
                WHERE id = ?
            """, (new_priority, enum_pos_id))

        conn.commit()

        print("Приоритет перечисления изменен")
        return new_priority



    except Exception as _ex:
        print(f"Произошла ошибка при изменении приоритета перечисления: {_ex}")


def find_enums(enum_class_id):
    try:

        cursor.execute("""
            SELECT ep.id, ep.enum_name, ep.enum_short_name, ep.enum_id, ep.priority, ep.real_value, ep.int_value, ep.pic_value
            FROM enum ep
            WHERE ep.enum_id = ?
            ORDER BY ep.priority ASC
        """, (enum_class_id,))

        results = cursor.fetchall()

        for row in results:
            print(row)

        return results

    except Exception as _ex:
        print(f"Произошла ошибка при получении списка перечислений заданного класса: {_ex}")


def add_enum_in_classifier(terminal_classifier_name, terminal_classifier_short_name, enum_parent_name, id_unit=None):
    # try:
        cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (enum_parent_name,))
        id_parent_check = cursor.fetchone()
        if id_parent_check is not None:
            id_parent = id_parent_check[0]
        else:
            id_parent = None
        if id_unit:
            cursor.execute("SELECT COUNT(*) FROM unit WHERE id = ?", (id_unit,))
            count = cursor.fetchone()[0]
            if (not count):
                print(f'Произошла ошибка при добавлении записи в enum_classifier! Указанного id_unit не существует.')
        cursor.execute('''
            INSERT INTO terminal_classifier (terminal_classifier_name, terminal_classifier_short_name, id_parent, id_unit)
            VALUES (?, ?, ?, ?)
        ''', (terminal_classifier_name, terminal_classifier_short_name, id_parent, id_unit))
        conn.commit()

        print('Класс перечисления успешно добавлен в основную базу.')


    # except Exception as _ex:
    #     print(f'Error {_ex} - ошибка при добавлении enum_in_classifier.')


def change_enum_priority(enum_name, priority):
    try:
        if (priority >= 0):
            cursor.execute("UPDATE enum SET priority = ? WHERE enum_name = ?", (priority, enum_name))
            conn.commit()
        else:
            print('Приоритет должен быть неотрицательным целым числом.')
            return

    except Exception as _ex:
        print(f'Error {_ex} - ошибка при изменении приоритета конкретного перечисления.')


def check_cyclic_dependency_terminal_classifier(new_parent_terminal_classifier_id, product_name_in_func):
    try:
        def fetch_parent_terminal_classifier(id):
            cursor.execute("SELECT id_parent FROM terminal_classifier WHERE id = ?", (id,))
            return cursor.fetchone()[0]

        current_id = new_parent_terminal_classifier_id
        while current_id is not None:
            if current_id == product_name_in_func:
                return True
            current_id = fetch_parent_terminal_classifier(current_id)
        return False
    except Exception as _ex:
        print(f'Error {_ex} - ошибка при проверке классов на цикл.')


def change_parent_of_terminal_classifier(terminal_classifier_name, new_parent_terminal_classifier=None):
    try:
        print(f'введенные категории - для {terminal_classifier_name} назначить родителем {new_parent_terminal_classifier}')

        if (is_enum_exist(terminal_classifier_name)):
            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
            id_enum = cursor.fetchone()[0]

            if (new_parent_terminal_classifier is not None):
                if (is_enum_exist(new_parent_terminal_classifier)):

                    if (terminal_classifier_name == new_parent_terminal_classifier):
                        print('Нельзя назначить классу самого себя в родители.')
                        return 0

                    cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (new_parent_terminal_classifier,))
                    id_new_parent_terminal_classifier = cursor.fetchone()[0]

                    cursor.execute("SELECT id_parent FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
                    id_parent_class_of_class = cursor.fetchone()[0]

                    # Check for cyclic dependency using the recursive function
                    if check_cyclic_dependency_terminal_classifier(id_new_parent_terminal_classifier, id_enum):

                        if (id_parent_class_of_class):
                            # if parent class has had their own parent then would set it

                            cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE id = ?", (id_new_parent_terminal_classifier, id_enum))

                            conn.commit()

                            cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE id = ?", (id_parent_class_of_class, id_new_parent_terminal_classifier ))

                            conn.commit()

                            print('Родитель у подкласса был успешно изменен.')
                            return 1

                        else:
                            # if not then class becomes root
                            cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE terminal_classifier_name = ?", (None, new_parent_terminal_classifier))

                            conn.commit()
                            print(f'Подкласс c terminal_classifier_name - {new_parent_terminal_classifier} стала родительской.')
                            return 1

                    # Update the parent class
                    cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE id = ?", (id_new_parent_terminal_classifier, id_enum ))

                    conn.commit()
                    return 1

                else:
                    print('Новая родительский класс не существует.')
                    return 0

            else:
                # code for new_parent_class=None
                cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE id = ?", (None, id_enum))
                conn.commit()

                print('Класс стал корневым / одним из корневых')
                return 1

        else:
            print('Указанного класса не существует.')
            return 0

    except Exception as _ex:
        conn.rollback()
        print(f"Ошибка в изменении родителя класса (terminal_classifier): {_ex}")










def delete_product(product_name):
    try:

        # Удаление изделия
        cursor.execute("DELETE FROM product WHERE product_name = ?", (product_name,))
        rows_deleted = cursor.rowcount

        if rows_deleted > 0:
            print('Изделие успешно удалено.')
        else:
            print('Изделие с указанным названием не найдено.')

        conn.commit()

    except Exception as _ex:
        print(f"Произошла ошибка при удалении изделия: {_ex}")


def delete_category(terminal_classifier_name):
    try:

        if is_category_exists(terminal_classifier_name):
            # Получаем идентификатор удаляемой категории
            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?;", (terminal_classifier_name,))
            delete_id = cursor.fetchone()[0]

            # Перемещаем все подкатегории удаляемой категории в категорию "неопределенные"
            cursor.execute("UPDATE terminal_classifier SET id_parent = (SELECT id FROM terminal_classifier WHERE terminal_classifier_name = 'неопределенные') WHERE id_parent = ?", (delete_id,))

            # Перемещаем все изделия удаляемой категории в категорию "неопределенные"
            cursor.execute("UPDATE product SET id_category = (SELECT id FROM terminal_classifier WHERE terminal_classifier_name = 'неопределенные') WHERE id_category = ?", (delete_id,))

            # Удаляем категорию
            cursor.execute("DELETE FROM terminal_classifier WHERE id = ?", (delete_id,))
            conn.commit()

            print('Категория успешно удалена.')
        else:
            print('Указанная категория не существует.')

    except Exception as _ex:
        print(f"Произошла ошибка при удалении категории: {_ex}")



# here coursework-1 ends



def delete_subcategory(subterminal_classifier_name):
    try:

        if is_category_exists(subterminal_classifier_name):
            # Получаем идентификатор удаляемой подкатегории
            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (subterminal_classifier_name,))
            subcategory_id = cursor.fetchone()[0]

            # Перемещаем связанные изделия в категорию "неопределенные"
            cursor.execute("UPDATE product SET id_category = (SELECT id FROM terminal_classifier WHERE terminal_classifier_name = 'неопределенные') WHERE id_category = ?", (subcategory_id,))

            # Перемещаем связанные подкатегории в категорию "неопределенные"
            cursor.execute("UPDATE category SET id_parent = (SELECT id FROM terminal_classifier WHERE terminal_classifier_name = 'неопределенные') WHERE id_parent = ?", (subcategory_id,))

            # Удаляем подкатегорию
            cursor.execute("DELETE FROM terminal_classifier WHERE id = ?", (subcategory_id,))
            conn.commit()

            print('Подкатегория успешно удалена.')
        else:
            print('Указанная подкатегория не существует.')

    except Exception as _ex:
        print(f"Произошла ошибка при удалении подкатегории: {_ex}")


def get_subcategory_parent(subterminal_classifier_name):
    try:

        if is_category_exists(subterminal_classifier_name):
            cursor.execute("SELECT id_parent FROM terminal_classifier WHERE terminal_classifier_name = ?", (subterminal_classifier_name,))
            id_parent_category_of_subcategory = cursor.fetchone()[0]

            cursor.execute("SELECT terminal_classifier_name FROM terminal_classifier WHERE id = ?", (id_parent_category_of_subcategory,))
            parent_terminal_classifier_name = cursor.fetchone()[0]

            return parent_terminal_classifier_name
        else:
            print('Указанной подкатегории не существует!')

    except Exception as _ex:
        print(f"Произошла ошибка при получении родительской категории подкатегории: {_ex}")


# cycle checking

def check_cyclic_dependency(new_parent_id, category_id):
    def fetch_parent_category(cat_id):
        cursor.execute("SELECT id_parent FROM terminal_classifier WHERE id = ?", (cat_id,))
        return cursor.fetchone()[0]

    current_id = new_parent_id
    while current_id is not None:
        if current_id == category_id:
            return True
        current_id = fetch_parent_category(current_id)
    return False


def change_parent_of_category(terminal_classifier_name, new_parent_category=None):
    try:
        print(f'введенные категории - для {terminal_classifier_name} назначить родителем {new_parent_category}')

        if (is_category_exists(terminal_classifier_name)):
            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
            id_category = cursor.fetchone()[0]

            if (new_parent_category is not None):
                if (is_category_exists(new_parent_category)):

                    if (terminal_classifier_name == new_parent_category):
                        print('Нельзя назначить категории саму себя в родители.')
                        return

                    cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (new_parent_category,))
                    id_new_parent_category = cursor.fetchone()[0]

                    cursor.execute("SELECT id_parent FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
                    id_parent_category_of_category = cursor.fetchone()[0]

                    # Check for cyclic dependency using the recursive function
                    if check_cyclic_dependency(id_new_parent_category, id_category):

                        if (id_parent_category_of_category):
                            # if parent category has had their own parent then would set it

                            cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE id = ?", (id_new_parent_category, id_category))

                            conn.commit()

                            cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE id = ?", (id_parent_category_of_category, id_new_parent_category ))

                            conn.commit()

                            print('Родитель у подкатегории был успешно изменен.')

                        else:
                            # if not then category becomes root
                            cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE terminal_classifier_name = ?", (None, new_parent_category))

                            conn.commit()
                            print(f'Подкатегория c terminal_classifier_name {new_parent_category} стала родительской.')

                    # Update the parent category
                    cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE id = ?", (id_new_parent_category, id_category ))

                    conn.commit()

                else:
                    print('Новая родительская категория не существует.')

            else:
                # code for new_parent_category=None
                cursor.execute("UPDATE terminal_classifier SET id_parent = ? WHERE id = ?", (None, id_category))
                conn.commit()

                print('Категория стала корневой / одной из корневых')

        else:
            print('Указанной категории не существует.')

    except Exception as _ex:
        conn.rollback()
        print(f"Ошибка в изменении родителя категории: {_ex}")


def change_terminal_classifier_name(old_name, new_name):
    try:

        if is_category_exists(old_name):
            if not is_category_exists(new_name):
                cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (old_name,))
                terminal_classifier_name_id = cursor.fetchone()[0]

                cursor.execute("UPDATE category SET terminal_classifier_name = ? WHERE id = ?", (new_name, terminal_classifier_name_id))
                print('Имя категории успешно изменено.')
            else:
                print('Указанное новое имя категории уже существует!')

        else:
            print('Указанная категория не существует.')

        conn.commit()

    except Exception as _ex:
        print(f"Произошла ошибка при изменении имени категории: {_ex}")


def change_product_name(old_name, new_name):
    try:

        if is_product_exist(old_name):
            if not is_product_exist(new_name):
                cursor.execute("SELECT id FROM product WHERE product_name = ?", (old_name,))
                product_name_id = cursor.fetchone()[0]

                cursor.execute("UPDATE product SET product_name = ? WHERE id = ?", (new_name, product_name_id))
                print('Имя изделия успешно изменено.')
            else:
                print('Указанное новое имя изделия уже существует!')

        else:
            print('Указанное изделие не существует.')

        conn.commit()

    except Exception as _ex:
        print(f"Произошла ошибка при изменении имени изделия: {_ex}")


def get_category_parents(terminal_classifier_name):

    if is_category_exists(terminal_classifier_name):
        terminal_classifier_name_copy = terminal_classifier_name
        try:

            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
            category_id = cursor.fetchone()[0]

            # function for recursive search parents
            def find_parents(category_id, parents_list):
                id_parent = 0

                cursor.execute("SELECT EXISTS(SELECT 1 FROM terminal_classifier WHERE id = ?)", (category_id,))
                record_exists = cursor.fetchone()[0]

                if record_exists:
                    cursor.execute("SELECT id_parent FROM terminal_classifier WHERE id = ?", (category_id,))
                    id_parent = cursor.fetchone()[0]

                if id_parent == 0:
                    return

                if category_id != 0 and id_parent != 0:
                    if id_parent != 0:
                        cursor.execute("SELECT terminal_classifier_name FROM terminal_classifier WHERE id = ?", (id_parent,))
                        parent_name = cursor.fetchone()
                        parents_list.append(parent_name)
                        find_parents(id_parent, parents_list)

            parents_list = []
            parents_list_res = []

            # begin recursive search for parents
            find_parents(category_id, parents_list)

            for elem in parents_list:
                if elem:
                    parents_list_res.append(elem[0])

            if parents_list_res:
                print(f'родительские элементы для категории "{terminal_classifier_name_copy}": \n {parents_list_res}')
            else:
                print(f'У категории "{terminal_classifier_name_copy}" нет родительских элементов')

        except Exception as _ex:
            print(f"Произошла ошибка при получении списка родителей категории: {_ex}")

    else:
        print('Категории не существует.')


def print_category_children(terminal_classifier_name, order):

    if not is_category_exists(terminal_classifier_name):
        print("Такой категории нет.")
        return

    children_list_res = get_category_children(terminal_classifier_name)
    if children_list_res:
        if order == 'прямой':
            print(f'дочерние элементы для категории "{terminal_classifier_name}": \n {children_list_res}')
        elif order == 'обратный':
            print(f'дочерние элементы для категории "{terminal_classifier_name}": \n {children_list_res[::-1]}')
        else:
            print('Такого порядка вывода нет!')
    else:
        print(f'У категории "{terminal_classifier_name}" нет дочерних элементов')


def get_category_children(terminal_classifier_name):

    if is_category_exists(terminal_classifier_name):
        try:

            cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
            category_id = cursor.fetchone()[0]

            # function for recursive search subcategories
            def find_children(category_id, children_list):
                childrens_id = 0
                childrens_id = []

                cursor.execute("SELECT COUNT(*) FROM terminal_classifier WHERE id_parent = ?", (category_id,))
                record_exists = cursor.fetchall()

                if record_exists:
                    cursor.execute("SELECT id FROM terminal_classifier WHERE id_parent = ?", (category_id,))
                    childrens_id = cursor.fetchall()

                    if childrens_id == 0:
                        return

                    if category_id != 0 and childrens_id != 0:
                        for elem in childrens_id:
                            elem_id = elem[0]

                            cursor.execute("SELECT terminal_classifier_name FROM terminal_classifier WHERE id = ?", (elem_id,))
                            child_name = cursor.fetchone()
                            children_list.append(child_name)

                            find_children(elem_id, children_list)

            children_list = []
            children_list_res = []

            # begin search subcategories
            find_children(category_id, children_list)

            for elem in children_list:
                if elem:
                    children_list_res.append(elem[0])

            return children_list_res

        except Exception as _ex:
            print(f"Произошла ошибка при получении списка дочерних категорий: {_ex}")

    else:
        print('Категории не существует.')



############### added after first review ###############

def print_products_of_category(terminal_classifier_name, order):
    products = get_products_of_category(terminal_classifier_name)
    if products:
        print(f'Изделия для категории "{terminal_classifier_name}":')
        print_str = ''

        if order == 'прямой':
            for prod in products:
                print_str += '"' + prod + '"' + ' '
            print(print_str)

        elif order == 'обратный':
            products = products[::-1]
            for prod in products:
                print_str += '"' + prod + '"' + ' '
            print(print_str)
        else:
            print('Такого порядка вывода нет!')

    else:
        print(f'У категории "{terminal_classifier_name}" нет изделий')


def get_products_of_category(terminal_classifier_name):
    if is_category_exists(terminal_classifier_name):
        try:
            categories_to_check = get_category_children(terminal_classifier_name)
            products = []

            if categories_to_check:
                for category in categories_to_check:
                    cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (category,))
                    id_of_searched_category = cursor.fetchone()[0]

                    cursor.execute("SELECT id FROM product WHERE id_category = ?", (id_of_searched_category,))
                    products_id = cursor.fetchall()


                    for id in products_id:
                        cursor.execute("SELECT product_name FROM product WHERE id = ?", (id[0],))
                        product_to_add = cursor.fetchone()[0]
                        products.append(product_to_add)


            else:
                cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (terminal_classifier_name,))
                id_of_searched_category = cursor.fetchone()[0]

                cursor.execute("SELECT id FROM product WHERE id_category = ?", (id_of_searched_category,))
                products_id = cursor.fetchall()

                for id in products_id:
                    cursor.execute("SELECT product_name FROM product WHERE id = ?", (id[0],))
                    product_to_add = cursor.fetchone()[0]
                    products.append(product_to_add)

            return products

        except Exception as _ex:
            print(f"Произошла ошибка при поиске изделия заданной категории: {_ex}")
    else:
        print('Категории не существует.')














##################################### third lab #####################################


def create_param(new_name, new_short_name, new_unit_id, new_min_val, new_max_val):

    try:
        # Вставка новой записи в таблицу param
        cursor.execute('''SELECT unit_name FROM unit WHERE id = ?''', (new_unit_id,))
        is_unit_exist = cursor.fetchone()

        if not is_unit_exist:
            print(f'Ошибка в create_param: Единицы измерения не сушествует.')

        cursor.execute('''
            INSERT INTO param(param_name, param_short_name, unit_id, min_val, max_val)
            VALUES (?, ?, ?, ?, ?)
        ''', (new_name, new_short_name, new_unit_id, new_min_val, new_max_val))

        # Проверка количества вставленных строк
        if cursor.rowcount == 1:
            conn.commit()
            print(f'параметр с именем {new_name} успешно добавлен.')
            return 1
        else:
            conn.rollback()
            return 0
    except sqlite3.Error as e:
        # В случае ошибки откатываем транзакцию
        print(f"An error occurred in create_param: {e}")
        conn.rollback()
        return 0


def edit_param(param_id, new_name, new_short_name, new_unit_id, new_min_val, new_max_val):
    try:
        # Начало транзакции
        conn.execute('BEGIN TRANSACTION')

        cursor.execute('''SELECT param_name FROM param WHERE id = ? ''', (param_id,))
        is_param_exist = cursor.fetchone()

        if not is_param_exist:
            print(f'Ошибка в edit_param: Параметра с id = {param_id} не существует.')
            return 0


        cursor.execute('''SELECT unit_name FROM unit WHERE id = ? ''', (new_unit_id,))
        is_unit_exist = cursor.fetchone()

        if not is_unit_exist:
            print(f'Ошибка в edit_param: Единицы измерения с id = {new_unit_id} не существует.')
            return 0


        # Выполнение запроса на обновление
        cursor.execute('''
            UPDATE param
            SET param_name = ?, param_short_name = ?, unit_id = ?, min_val = ?, max_val = ?
            WHERE id = ?
        ''', (new_name, new_short_name, new_unit_id, new_min_val, new_max_val, param_id))

        conn.commit()

        # Получение количества обновленных строк
        res = cursor.rowcount

        # Фиксация изменений
        conn.commit()

        # Возвращение результата
        if res == 1:
            print(f'Параметр с id = {param_id} успешно обновлен.')
            return 1
        else:
            return 0

    except sqlite3.Error as e:
        print(f"Ошибка в edit_param: {e}")
        conn.rollback()
        return 0


def delete_param(param_to_delete):
    cursor.execute('''SELECT id FROM param WHERE param_name = ? ''', (param_to_delete,))
    param_id = cursor.fetchone()

    if not param_id:
        print(f'Ошибка. Параметра с таким названием не существует')
        return 0
    else:
        param_id = param_id[0]
        print(f'param_id - {param_id}')

    def del_param_from__class_param():
        cursor.execute('''SELECT id FROM class_param WHERE param_id = ? ''', (param_id,))
        classes_id_to_del = cursor.fetchall()
        print(f'classes_id_to_del - {classes_id_to_del}')

        for elem_id in classes_id_to_del:
            print(f'elem_id - {elem_id[0]}')

            cursor.execute("DELETE FROM class_param WHERE id = ?", (elem_id[0],))
            conn.commit()

        print(f'Классы параметров (если были) удаляемого параметра были обновлены')


    del_param_from__class_param()

    cursor.execute("DELETE FROM param WHERE param_name = ?", (param_to_delete,))

    res = cursor.rowcount

    conn.commit()

    # Возвращение результата в зависимости от количества удаленных строк
    if res == 1:
        print(f'Параметр успешно удален.')
        return 1
    else:
        print(f'При удалении параметра что-то пошло не так.')
        return 0




def create_class_param(terminal_classifier_name_class, terminal_classifier_name_short_class, param_name, parent_class_param_name):


    try:
        cursor.execute("SELECT id FROM param WHERE param_name = ?", (param_name,))

        param_id = cursor.fetchone()
        if not param_id:
            print(f'Ошибка в create_class_param: параметра с именем {param_name} не существует в таблице param')
            return 0
        else:
            param_id = param_id[0]

        cursor.execute("SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ?", (parent_class_param_name,))

        parent_class_id = cursor.fetchone()
        if not parent_class_id:
            print(f'В create_class_param: класса параметра (родителя) с именем {parent_class_param_name} не существует в таблице terminal_classifier, будет вставлено значение None')
            parent_class_id = None
        else:
            parent_class_id = parent_class_id[0]


        # Получаем максимальное значение priority для данного class_id

        cursor.execute(''' SELECT COUNT(*) FROM class_param WHERE param_class_name = ? ''', (terminal_classifier_name_class,))
        res = cursor.fetchone()[0]

        if res is None:
            res = 0
        else:
            cursor.execute(''' SELECT MAX(priority) + 1 FROM class_param WHERE param_class_name = ? ''', (terminal_classifier_name_class,))
            res = cursor.fetchone()[0]

        if res is None:
            res = 0

        cursor.execute('''SELECT unit_id FROM param WHERE param_name = ? ''', (param_name,))
        unit_id = cursor.fetchone()
        if not unit_id:
            print(f'Единицы измерения с заданным {unit_id} не найдено. Будет вставлено NULL')
        else:
            unit_id = unit_id[0]

        cursor.execute('''
            INSERT INTO terminal_classifier(id_parent, terminal_classifier_name, terminal_classifier_short_name, id_unit, priority)
            VALUES (?, ?, ?, ?, ?)
        ''', (parent_class_id, terminal_classifier_name_class, terminal_classifier_name_short_class, unit_id, res))

        cursor.execute('''
            INSERT INTO class_param(param_class_name, param_class_short_name, class_param_id, param_id, priority)
            VALUES (?, ?, ?, ?, ?)
        ''', (terminal_classifier_name_class, terminal_classifier_name_short_class, parent_class_id, param_id, res))

        conn.commit()

    except sqlite3.Error as e:
        # В случае ошибки откатываем транзакцию
        print(f"An error occurred: {e}")
        conn.rollback()
        return 0





def edit_class_param(id, new_param_class_name, new_param_class_short_name, new_param_id=None, class_param_id=None):
    try:
        # Начало транзакции
        conn.execute('BEGIN TRANSACTION')

        cursor.execute('''SELECT param_class_name FROM class_param WHERE id = ? ''', (id,))
        is_class_param_exist = cursor.fetchone()

        if not is_class_param_exist:
            print(f'Ошибка в edit_class_param: Параметра класса с id = {id} не существует.')
            return 0
        else:
            param_class_name_old = is_class_param_exist[0]

            cursor.execute('''SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ? ''', (param_class_name_old,))
            id_class_param_in_tc = cursor.fetchone()[0]

        if new_param_id:
            cursor.execute('''SELECT param_name FROM param WHERE id = ? ''', (new_param_id,))
            is_param_exist = cursor.fetchone()

            if not is_param_exist:
                print(f'Ошибка в edit_class_param: Параметра с id = {new_param_id} не существует.')
                return 0
        else:
            cursor.execute('''SELECT id FROM param WHERE param_name = ? ''', ('неопределенный параметр',))
            new_param_id = cursor.fetchone()[0]



        if class_param_id:
            cursor.execute('''SELECT terminal_classifier_name FROM terminal_classifier WHERE id = ? ''', (class_param_id,))
            is_terminal_class_name_exist = cursor.fetchone()

            if check_cyclic_dependency_terminal_classifier(class_param_id, param_class_name_old):
                print("Ошибка в edit_class_param: родитель и потомок образуют цикл. ")
                return 0

            if (is_terminal_class_name_exist[0] == param_class_name_old):
                print(f'_terminal_class_name_ = {is_terminal_class_name_exist[0]}, param_class_name_old = {param_class_name_old} =>', sep='')
                print(f'Нельзя назначить классу в родителя самого себя')
                return 0

            if not is_terminal_class_name_exist:
                    print(f'Ошибка в edit_class_param: Параметра класса с id = {id} не существует.')
                    return 0

            if change_parent_of_category(param_class_name_old, is_terminal_class_name_exist[0]):


                cursor.execute('''SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ? ''', ('неопределенный параметр класса',))
                class_param_id = cursor.fetchone()[0]

                cursor.execute("UPDATE class_param SET param_class_name = ?, param_class_short_name = ?, param_id = ?, class_param_id = ? WHERE id = ?", (new_param_class_name, new_param_class_short_name, new_param_id, class_param_id, id))


                cursor.execute("UPDATE terminal_classifier SET terminal_classifier_name = ?, terminal_classifier_short_name = ?,  id_parent = ? WHERE id = ?", (new_param_class_name, new_param_class_short_name, class_param_id, id_class_param_in_tc))



                res = cursor.rowcount

                # Фиксация изменений
                conn.commit()

                # Возвращение результата
                if res == 1:
                    print(f'Параметр с id = {id} успешно обновлен.')
                    return 1
                else:
                    return 0

        else:
            cursor.execute('''SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ? ''', ('неопределенный параметр класса',))
            class_param_id = cursor.fetchone()[0]

            cursor.execute("UPDATE class_param SET param_class_name = ?, param_class_short_name = ?, param_id = ?, class_param_id = ? WHERE id = ?", (new_param_class_name, new_param_class_short_name, new_param_id, class_param_id, id))


            cursor.execute("UPDATE terminal_classifier SET terminal_classifier_name = ?, terminal_classifier_short_name = ?,  id_parent = ? WHERE id = ?", (new_param_class_name, new_param_class_short_name, class_param_id, id_class_param_in_tc))

            res = cursor.rowcount

            # Фиксация изменений
            conn.commit()

            # Возвращение результата
            if res == 1:
                print(f'Параметр класса с id = {id} успешно обновлен.')
                return 1
            else:
                return 0


    except sqlite3.Error as e:
        print(f"Ошибка в edit_class_param: {e}")
        conn.rollback()
        return 0



def delete_class_param(class_to_delete):
    try:
        cursor.execute('''SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ? ''', (class_to_delete,))
        exists = cursor.fetchone()

        if not exists:
            print(f'Ошибка в delete_class_param: Класса параметра с таким названием не существует')
            return 0

        if (class_to_delete == 'неопределенный параметр класса' or class_to_delete == 'параметр класса'):
            print(f"Нельзя удалить параметр класса \'неопределенный параметр класса\' или \'параметр класса\'")
            return 0

        # Проверка на наличие дочерних элементов
        is_children_exist = get_category_children(class_to_delete)

        print(f'is_children_exist - {is_children_exist}')

        if not is_children_exist:
            cursor.execute("DELETE FROM class_param WHERE param_class_name = ?", (class_to_delete,))
            conn.commit()

            cursor.execute("DELETE FROM terminal_classifier WHERE terminal_classifier_name = ?", (class_to_delete,))
            conn.commit()
        else:
            cursor.execute('''SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ? ''', (class_to_delete,))
            id_class_to_delete = cursor.fetchone()[0]

            print(f'class_to_delete - {class_to_delete}')
            print(f'id_class_to_delete - {id_class_to_delete}')

            cursor.execute("SELECT id FROM class_param WHERE class_param_id = ? ", (id_class_to_delete,))
            children = cursor.fetchall()

            print(f'children (id) - {children}')

            cursor.execute('''SELECT id FROM terminal_classifier WHERE terminal_classifier_name = ? ''', ('неопределенный параметр класса',))
            undef_class_id = cursor.fetchone()[0]

            children_info_rows = []


            for child in children:
                print(f'child - {child}')

                cursor.execute('''SELECT param_class_name FROM class_param WHERE id = ? ''', (child[0],))
                child_name = cursor.fetchone()[0]
                print(f'child_name - {child_name}')

                cursor.execute('''SELECT * FROM class_param WHERE id = ?''', (child[0],))
                child_row = cursor.fetchone()[0]

                children_info_rows.append(child_row)



                cursor.execute("UPDATE class_param SET class_param_id = ? WHERE id = ?", (undef_class_id, child[0]))

                change_parent_of_terminal_classifier(child_name, 'неопределенный параметр класса')
                conn.commit()



                cursor.execute("DELETE FROM class_param WHERE param_class_name = ?", (class_to_delete,))
                conn.commit()

                cursor.execute("DELETE FROM terminal_classifier WHERE terminal_classifier_name = ?", (class_to_delete,))
                conn.commit()

            print(f'children_info_rows - {children_info_rows}')

        conn.commit()
        print("Удаление завершено успешно")
        return 1

    except sqlite3.IntegrityError as e:
        print(f"Ошибка в delete_class_param: {e}")
        conn.rollback()
        return 0



def inherit_class_parameters(new_class_to_inherit__name, new_class_to_inherit__short_name, parent_class__name):
    try:
        # Получаем parent_id
        cursor.execute('''
            SELECT id FROM class_param WHERE param_class_name = ?
        ''', (parent_class__name,))
        parent_id_row = cursor.fetchone()

        if parent_id_row is None:
            print(f'Ошибка в inherit_class_parameters: класса параметра с именем для наследования не найдено')
            return 0  # Если id родителя в таблице class_param не найдено


        # Получаем параметры из CLASS_PARAM для parent_id
        cursor.execute('''
            SELECT class_param_id, param_id FROM class_param WHERE param_class_name = ? ORDER BY priority
        ''', (parent_class__name,))

        param_rows = cursor.fetchall()

        print(f'param_rows - {param_rows}')

        for param_row in param_rows:
            class_param_id, param_id = param_row

            # Проверяем, существует ли уже параметр для данного cl_id
            cursor.execute('''
                SELECT 1 FROM class_param WHERE param_class_name = ? AND param_id = ?
            ''', (new_class_to_inherit__name, param_id))

            exists = cursor.fetchone()

            cursor.execute('''
                SELECT param_name FROM param WHERE id = ?''', (param_id,))
            param_name = cursor.fetchone()[0]

            print(f'exists ? - {exists}')

            if exists:
                print(f'Класс параметра с именем {new_class_to_inherit__name} уже существует.')

            if not exists:

                create_class_param(new_class_to_inherit__name, new_class_to_inherit__short_name, param_name, parent_class__name)


        conn.commit()


    except sqlite3.Error as e:
        print(f"An error occurred in inherit_class_parameters: {e}")
        conn.rollback()
        return 0




def edit_class_param_output_priority(class_id, id, priority):
    try:
        # Выполнение запроса для получения количества записей с указанным priority и id класса
        cursor.execute("""
            SELECT count(*)
            FROM class_param
            WHERE priority = ? AND class_param_id = ?
        """, (priority, class_id))

        # Получение результата запроса
        cnt = cursor.fetchone()[0]

        if cnt == 0:
            # Если таких записей нет, обновляем priority для указанной записи
            cursor.execute("""
                UPDATE class_param
                SET priority = ?
                WHERE class_param_id = ? AND id = ?
            """, (priority, class_id, id))
        else:
            # Если такие записи есть, увеличиваем output_priority для всех записей с priority >= переданного в функцию priority
            cursor.execute("""
                UPDATE class_param
                SET priority = priority + 1
                WHERE priority >= ? AND class_param_id = ?
            """, (priority, class_id))

            # Затем обновляем priority для указанной записи
            cursor.execute("""
                UPDATE class_param
                SET priority = ?
                WHERE class_param_id = ? AND id = ?
            """, (priority, class_id, id))

        conn.commit()
        print(f'Приоритет изменен.')
        return priority

    except sqlite3.Error as e:
        print(f"An error occurred in edit_class_param_output_priority: {e}")
        conn.rollback()
        return 0





def create_prod_param(new_prod_id, new_param_id, new_int_val, new_str_val, new_real_val, new_enum_id):
    try:
        # проверка на существование new_prod_id
        cursor.execute("SELECT product_name FROM product WHERE id = ?", (new_prod_id,))
        is_new_product_name_exist = cursor.fetchone()

        print(f'new_prod_id - {new_prod_id}')
        print(f'is_new_product_name_exist - {is_new_product_name_exist}')

        if is_new_product_name_exist is None:
            print(f'Ошибка в create_prod_param: изделия с id {new_prod_id} не найдено')
            return 0


        # проверка на существование new_param_id
        cursor.execute('''
            SELECT param_name FROM param WHERE id = ?
        ''', (new_param_id,))
        is_new_param_name_exist = cursor.fetchone()

        if is_new_param_name_exist is None:
            print(f'Ошибка в create_prod_param: параметра с id {new_param_id} не найдено')
            return 0


        # проверка на существование new_enum_val
        cursor.execute('''
            SELECT enum_name FROM enum WHERE id = ?
        ''', (new_enum_id,))
        is_new_enum_id_exist = cursor.fetchone()

        if is_new_enum_id_exist is None:
            print(f'Ошибка в create_prod_param: перечисления с id {new_enum_id} не найдено')
            return 0

        if new_int_val:
            cursor.execute('''SELECT min_val, max_val FROM param WHERE id = ?''', (new_param_id,))
            limits = cursor.fetchall()[0]

            print(f'у new_int_val limits = {limits}')

            if not limits:
                min_val, max_val = None
            else:
                min_val, max_val = limits
                if not ((min_val <= new_int_val) and (new_int_val <= max_val)):
                    print(f'значение {new_int_val} не попадает в промежуток границ параметра [{min_val} ; {max_val}]')

        if new_real_val:
            cursor.execute('''SELECT min_val, max_val FROM param WHERE id = ?''', (new_param_id,))
            print(f'new_param_id = {new_param_id}')
            limits = cursor.fetchall()[0]

            print(f'у new_real_val limits = {limits}')

            if not limits:
                min_val, max_val = None
            else:
                min_val, max_val = limits
                print(f'min_val - {min_val} \n max_val - {max_val}')
                if not ((min_val <= new_real_val ) and (max_val >= new_real_val)):
                    print(f'значение {new_real_val} не попадает в промежуток границ параметра [{min_val} ; {max_val}]')

        # Выполнение запроса на вставку данных
        cursor.execute('''
            INSERT INTO prod_param (prod_id, param_id, int_value, str_value, real_value, enum_id)
            VALUES (?, ?, ?, ?, ?, ?)
        ''', (new_prod_id, new_param_id, new_int_val, new_str_val, new_real_val, new_enum_id,))

        # Получение количества вставленных строк
        res = cursor.rowcount

        # Фиксация изменений
        conn.commit()

        # Возвращение результата
        if res == 1:
            print(f'Добавлена запись в таблицу prod_param')
            return 1
        else:
            return 0

    except sqlite3.Error as e:
        print(f"Ошибка в create_prod_param: {e}")
        conn.rollback()
        return 0





def edit_prod_param(id, new_int_val, new_str_val, new_real_val, new_enum_val):
    try:
        # Начало транзакции
        conn.execute('BEGIN TRANSACTION')

        new_enum_val
        # проверка на существование new_enum_val
        cursor.execute('''
            SELECT id FROM enum WHERE enum_name = ?
        ''', (new_enum_val,))
        is_enum_exist = cursor.fetchall()

        print(f'is_enum_exist - {is_enum_exist}')

        if is_enum_exist is None:
            print(f'Ошибка в edit_prod_param: записи с new_enum_val {new_enum_val} в enum не найдено')
            return 0
        else:
            new_enum_id = is_enum_exist[0]


        # проверка на существование id
        cursor.execute('''
            SELECT prod_id, param_id FROM prod_param WHERE id = ?
        ''', (id,))
        is_id_exist = cursor.fetchall()

        print(f'is_id_exist - {is_id_exist}')

        if is_id_exist is None:
            print(f'Ошибка в edit_prod_param: записи с id {id} в prod_param не найдено')
            return 0



        print(f'enum_id - {new_enum_id[0]}')
        # Выполнение запроса на обновление данных
        cursor.execute('''
            UPDATE prod_param
            SET int_value = ?, str_value = ?, enum_id = ?, real_value = ?
            WHERE id = ?
        ''', (new_int_val, new_str_val, new_enum_id[0], new_real_val, id))

        # Получение количества обновленных строк
        res = cursor.rowcount

        # Фиксация изменений
        conn.commit()

        # Возвращение результата
        if res == 1:
            return 1
        else:
            return 0

    except sqlite3.Error as e:
        print(f"Ошибка в edit_prod_param: {e}")
        conn.rollback()
        return 0




def find_param_id_from_prod(prod_id):
    try:

        cursor.execute('SELECT product_name FROM product WHERE id = ?', (prod_id,))
        product_name = cursor.fetchone()
        if product_name:
            product_name = product_name[0]
        else:
            print(f'изделия с id - {prod_id} не существует.')
            return 0

        # Начало транзакции
        conn.execute('BEGIN TRANSACTION')

        # Получение class_id из таблицы obj
        cursor.execute('SELECT id_category FROM product WHERE id = ?', (prod_id,))
        id_parent = cursor.fetchone()
        print(f'id_parent = {id_parent}')

        if id_parent is None:
            print(f'Ошибка: объект с id {prod_id} не найден')
            return []

        id_parent = id_parent[0]

        # Получение param_id из таблицы class_param, упорядоченных по output_priority
        cursor.execute('''
            SELECT param_id FROM class_param
            WHERE class_param_id = ?
            ORDER BY priority
        ''', (id_parent,))

        param_ids = cursor.fetchall()

        # Фиксация изменений
        conn.commit()

        # Возвращение результата в виде списка
        return [row[0] for row in param_ids]

    except sqlite3.Error as e:
        print(f"Ошибка в find_param_id_from_prod: {e}")
        conn.rollback()
        return []


def find_products_of_class_param(id_of_class_param_el):

    cursor.execute('SELECT param_class_name FROM class_param WHERE id = ?', (id_of_class_param_el,))
    name_of_class_param_el = cursor.fetchone()

    print(f'id_of_class_param_el - {name_of_class_param_el}')

    if name_of_class_param_el:
        name_of_class_param_el = name_of_class_param_el[0]
    else:
        print(f'класса параметра с названием - {name_of_class_param_el} не существует.')
        return 0

    cursor.execute('SELECT class_param_id FROM class_param WHERE id = ?', (id_of_class_param_el,))
    class_param_id = cursor.fetchone()

    print(f'name_of_class_param_el - {name_of_class_param_el}')

    if class_param_id:
        class_param_id = class_param_id[0]
    else:
        print(f'класс параметра с id категории изделий - {class_param_id} не существует.')
        return 0

    cursor.execute('SELECT * FROM product WHERE id_category = ?', (class_param_id,))
    products = cursor.fetchall()

    if products:
        products = products[0]
    else:
        print(f'изделия с id классом параметра - {class_param_id} не существует.')
        return 0

    return products



def find_products_in_interval_param(param_id, type_value, start_val, end_val):

    if 'int' in type_value.lower():
        cursor.execute('SELECT prod_id FROM prod_param WHERE param_id = ? AND int_value >= ? AND int_value <= ?', (param_id, start_val, end_val))
        prod_ids = cursor.fetchall()

        if prod_ids:
            prod_ids = prod_ids
            return prod_ids
        else:
            print(f'изделий с param_id = {param_id}, type_value = {type_value}, start_val = {start_val}, end_val = {end_val} нет в таблице product')
            return

    if 'real' in type_value.lower():
        cursor.execute('SELECT prod_id FROM prod_param WHERE param_id = ? AND real_value >= ? AND real_value <= ?', (param_id, start_val, end_val))
        prod_ids = cursor.fetchall()

        if prod_ids:
            prod_ids = prod_ids
            return prod_ids
        else:
            print(f'изделий с param_id = {param_id}, type_value = {type_value}, start_val = {start_val}, end_val = {end_val} нет в таблице product')
            return

##################################### third lab #####################################



##################################### 2-1 lab #####################################



def create_acceptable_component(new_class_id, new_component_id):
    # Prevent self-referencing components
    if new_class_id == new_component_id:
        print("Error: нельзя создать цикл с одинаковыми class_id и component_id!")
        return 0  # Failure

    try:
        # Recursive query to check for cycles in acceptable_components
        cursor.execute('''
            WITH RECURSIVE cycle_check(class_id, comp_id) AS (
                SELECT class_id, component_id
                FROM acceptable_components
                WHERE class_id = ?
                UNION ALL
                SELECT ac.class_id, ac.component_id
                FROM acceptable_components ac
                INNER JOIN cycle_check cc ON ac.class_id = cc.comp_id
            )
            SELECT 1 FROM cycle_check WHERE comp_id = ?
        ''', (new_component_id, new_class_id))

        # If a result exists, it means adding the new entry would create a cycle
        if cursor.fetchone():
            print(f"Error: добавление пары ({new_class_id}, {new_component_id}) создаёт цикл!")
            return 0  # Failure

        # Insert the new relationship if no cycle is detected
        cursor.execute('''
            INSERT INTO acceptable_components (class_id, component_id)
            VALUES (?, ?)
        ''', (new_class_id, new_component_id))
        conn.commit()
        print(f"Компонент успешно добавлен: class_id={new_class_id}, component_id={new_component_id}")
        return 1  # Success
    except sqlite3.OperationalError as e:
        print(f"SQL Error: {e}")
        return 0  # Failure
    except sqlite3.IntegrityError:
        print("Error: нарушение ограничений UNIQUE или FOREIGN KEY.")
        return 0  # Failure



# cycle checking

def check_cyclic_dependency_specif(new_class_id, comp_id):
    def fetch_parent_category(cat_id):
        cursor.execute("SELECT prod_id FROM prod_position_union WHERE comp_id = ?", (cat_id,))
        return cursor.fetchone()[0]

    current_id = new_class_id
    while current_id is not None:
        if current_id == comp_id:
            return True
        current_id = fetch_parent_category(current_id)
    return False


# ???
def create_prod_position_union(new_object_id, new_component_id, new_quantity):
    try:
        cursor.execute('SELECT id_category FROM product WHERE id = ?', (new_object_id,))

        obj_class_id = cursor.fetchone()
        if obj_class_id is None:
            raise ValueError("Object ID not found")

        cursor.execute('SELECT id_category FROM product WHERE id = ?', (new_component_id,))
        comp_class_id = cursor.fetchone()
        if comp_class_id is None:
            raise ValueError("Component ID not found")

        cursor.execute('''
            SELECT 1
            FROM acceptable_components
            WHERE class_id = ? AND component_id = ?
        ''', (obj_class_id[0], comp_class_id[0]))
        if cursor.fetchone() is None:

            raise ValueError("Invalid composition for the object!")

        cursor.execute('''
            INSERT INTO prod_position_union (prod_id, comp_id, quantity)
            VALUES (?, ?, ?)
        ''', (new_object_id, new_component_id, new_quantity))
        conn.commit()
        print('таблица prod_position_union успешно обновлена новым значением.')
        return 1  # Success
    except Exception as e:
        print(f"Error: {e}")
        return 0  # Failure




def is_prod_position_union(prod_id, comp_id):
    cursor.execute('SELECT 1 FROM prod_position_union WHERE prod_id = ? AND comp_id =?', (prod_id, comp_id,))
    res = cursor.fetchone()

    if res:
        return True
    else:
        return False


def delete_prod_position_union(prod_id, comp_id):
    cursor.execute('''
        DELETE FROM prod_position_union
        WHERE prod_id = ? AND comp_id = ?
    ''', (prod_id, comp_id))
    deleted_rows = cursor.rowcount
    conn.commit()
    print(f'в таблице prod_position_union успешно удалено значение - {prod_id, comp_id}')

    return 1 if deleted_rows == 1 else 0


# def delete_acceptable_component(cl_id, component_cl_id):
#     deleted_count = 0
#     try:

#         cursor.execute('SELECT id FROM product WHERE id_category = ?', (cl_id,))

#         obj_ids = [row[0] for row in cursor.fetchall()]

#         cursor.execute('SELECT id FROM product WHERE id_category = ?', (component_cl_id,))
#         comp_ids = [row[0] for row in cursor.fetchall()]



#         # Delete all associated position compositions
#         for obj_id in obj_ids:
#             for comp_id in comp_ids:
#                 if (is_prod_position_union(obj_id, comp_id)):
#                     deleted_count += delete_prod_position_union(obj_id, comp_id)

#         # Delete from acceptable_components
#         cursor.execute('''
#             DELETE FROM acceptable_components
#             WHERE class_id = ? AND component_id = ?
#         ''', (cl_id, component_cl_id))
#         conn.commit()
#         print(f'из класса с id - {cl_id} успешно удален компонент с id - {component_cl_id}')
#         return deleted_count
#     except Exception as e:
#         print(f"Error: {e}")
#         return deleted_count


def delete_acceptable_component(cl_id, component_cl_id):
    deleted_count = 0
    try:
        # Fetch all products linked to the class_id and component_id
        cursor.execute('SELECT id FROM product WHERE id_category = ?', (cl_id,))
        obj_ids = [row[0] for row in cursor.fetchall()]

        cursor.execute('SELECT id FROM product WHERE id_category = ?', (component_cl_id,))
        comp_ids = [row[0] for row in cursor.fetchall()]

        # Delete all associated position compositions
        for obj_id in obj_ids:
            for comp_id in comp_ids:
                if is_prod_position_union(obj_id, comp_id):
                    deleted_count += delete_prod_position_union(obj_id, comp_id)

        # Fetch all parents of the component_cl_id (nodes where component_cl_id is a child)
        cursor.execute('''
            SELECT class_id FROM acceptable_components
            WHERE component_id = ?
        ''', (cl_id,))
        parents = [row[0] for row in cursor.fetchall()]

        # Fetch all children of the component_cl_id (nodes where component_cl_id is a parent)
        cursor.execute('''
            SELECT component_id FROM acceptable_components
            WHERE class_id = ?
        ''', (component_cl_id,))
        children = [row[0] for row in cursor.fetchall()]

        # Delete the specified relationship
        cursor.execute('''
            DELETE FROM acceptable_components
            WHERE class_id = ? AND component_id = ?
        ''', (cl_id, component_cl_id))

        # Connect parents of cl_id to children of component_cl_id
        for parent in parents:
            for child in children:
                # Check if the relationship already exists
                cursor.execute('''
                    SELECT 1 FROM acceptable_components
                    WHERE class_id = ? AND component_id = ?
                ''', (parent, child))
                if cursor.fetchone() is None:
                    cursor.execute('''
                        INSERT INTO acceptable_components (class_id, component_id)
                        VALUES (?, ?)
                    ''', (parent, child))

        conn.commit()
        print(f'из класса с id - {cl_id} успешно удален компонент с id - {component_cl_id}, соединены родители и дети.')
        return deleted_count
    except Exception as e:
        print(f"Error: {e}")
        return deleted_count



def edit_prod_position_union_quantity(obj_id, comp_id, new_quantity):
    cursor.execute('''
        UPDATE prod_position_union
        SET quantity = ?
        WHERE prod_id = ? AND comp_id = ?
    ''', (new_quantity, obj_id, comp_id))
    updated_rows = cursor.rowcount
    conn.commit()
    print(f"значение позиции {(obj_id, comp_id)} установлено в {new_quantity}")
    return 1 if updated_rows == 1 else 0


def inherit_acceptable_components(cl_id):
    inserted_count = 0
    try:
        cursor.execute('SELECT id_parent FROM terminal_classifier WHERE id = ?', (cl_id,))
        parent_cl_id = cursor.fetchone()
        if parent_cl_id is None:
            raise ValueError("Parent class ID not found")

        cursor.execute('''
            SELECT component_id FROM acceptable_components
            WHERE class_id = ?
        ''', (parent_cl_id[0],))
        components = cursor.fetchall()

        # Insert acceptable components for the child class
        for (component_id,) in components:
            cursor.execute('''
                INSERT OR IGNORE INTO acceptable_components (class_id, component_id)
                VALUES (?, ?)
            ''', (cl_id, component_id))
            inserted_count += cursor.rowcount
        conn.commit()
        print(f'произведено {inserted_count} наследований')
    except Exception as e:
        print(f"Error: {e}")
    return inserted_count


def find_acceptable_components_by_class(class_id):
    try:
        cursor.execute("SELECT component_id FROM acceptable_components WHERE class_id = ?", (class_id,))
        component_ids = cursor.fetchall()

        if not component_ids:
            return []

        # Prepare the result list with names of components
        result = []
        for component_id in component_ids:
            cursor.execute("SELECT terminal_classifier_name FROM terminal_classifier WHERE id = ?", (component_id[0],))
            name = cursor.fetchone()
            if name:
                result.append((component_id[0], name[0]))

        print(f'для класса с id = {class_id}, составные части: {result}')
        return result

    except Exception as e:
        print(f"Error occurred while finding acceptable components by class: {e}")
        return []


def find_acceptable_components_by_class_recursive(class_id):
    try:
        def find_components(class_id, result):
            cursor.execute("SELECT component_id FROM acceptable_components WHERE class_id = ?", (class_id,))
            components = cursor.fetchall()

            for component in components:
                component_id = component[0]
                result.add(component_id)
                find_components(component_id, result)

        result = set()
        find_components(class_id, result)

        # Fetch component names for the result set
        component_names = []
        for component_id in result:
            cursor.execute("SELECT terminal_classifier_name FROM terminal_classifier WHERE id = ?", (component_id,))
            component_name = cursor.fetchone()
            if component_name:
                component_names.append((component_id, component_name[0]))

        print(f'результат подходящих компонент для id {class_id} - ({component_names})')

        return component_names

    except Exception as e:
        print(f"Error occurred while finding acceptable components: {e}")
        return []


def find_components_by_object(object_id):
    try:
        cursor.execute('''
            SELECT comp_id, quantity FROM prod_position_union WHERE prod_id = ?
        ''', (object_id,))
        components = cursor.fetchall()

        result = []
        for comp_id, quantity in components:
            cursor.execute("SELECT product_name, quantity FROM product WHERE id = ?", (comp_id,))
            name = cursor.fetchone()
            if name:
                result.append((['id', comp_id], ['product_name', name[0]], ['quantity', quantity]))

        print(f'для продукции с id = {object_id} компоненты - ({result})')
        return result

    except Exception as e:
        print(f"Error occurred while finding components by object: {e}")
        return []


def find_components_by_object_recursive(object_id):
    try:
        # Recursive function to find components
        def find_components(obj_id, result):
            cursor.execute("SELECT comp_id, quantity FROM prod_position_union WHERE prod_id = ?", (obj_id,))
            components = cursor.fetchall()

            for comp_id, quantity in components:
                result[comp_id] = result.get(comp_id, 0) + quantity
                find_components(comp_id, result)

        result = {}
        find_components(object_id, result)

        # Fetch component names for the result
        final_result = []
        for comp_id, total_quantity in result.items():
            cursor.execute("SELECT product_name FROM product WHERE id = ?", (comp_id,))
            name = cursor.fetchone()
            if name:
                final_result.append((comp_id, name[0], total_quantity))

        print(f'для объекта с id = {object_id} компоненты, найденные рекурсивно: {final_result}')
        return final_result

    except Exception as e:
        print(f"Error occurred while finding components recursively: {e}")
        return []


def find_components_by_object_and_class(object_id, class_id):
    try:
        cursor.execute('''
            SELECT comp_id, quantity FROM prod_position_union WHERE prod_id = ?
        ''', (object_id,))
        components = cursor.fetchall()

        result = []
        for comp_id, quantity in components:
            cursor.execute("SELECT id_category, product_name FROM product WHERE id = ?", (comp_id,))
            parent_info = cursor.fetchone()
            if parent_info and parent_info[0] == class_id:  # Check if parent matches class_id
                result.append((comp_id, parent_info[1], quantity))

        print(f'для объекта с id={object_id} класса с id={class_id} компоненты: {result}')

        return result

    except Exception as e:
        print(f"Error occurred while finding components by object and class: {e}")
        return []





# def find_components_by_object_and_class_recursive(object_id, class_id):
#     try:
#         def find_components(obj_id, class_id, result):
#             # Query to get components for the given object ID
#             cursor.execute("SELECT comp_id, quantity FROM prod_position_union WHERE prod_id = ?", (obj_id,))
#             components = cursor.fetchall()

#             for comp_id, quantity in components:
#                 # Query to get the category and name of the current component
#                 cursor.execute("SELECT id_category, product_name FROM product WHERE id = ?", (comp_id,))
#                 parent_info = cursor.fetchone()

#                 # Log parent info for debugging purposes
#                 print(f"parent_info for component {comp_id}: {parent_info}")

#                 # Check if the component belongs to the specified class
#                 if parent_info:
#                     component_category = parent_info[0]  # Extract the component's category
#                     print(f'component_category - {component_category}')
#                     if component_category == class_id:
#                         # Add or update the accumulated quantity in the result dictionary
#                         if comp_id in result:
#                             result[comp_id] += quantity
#                         else:
#                             result[comp_id] = quantity

#                 # Recursively process child components
#                 find_components(comp_id, class_id, result)

#         # Initialize the result dictionary
#         result = {}
#         find_components(object_id, class_id, result)

#         # Prepare the final result with component names
#         final_result = []
#         for comp_id, total_quantity in result.items():
#             # Fetch the id_category of the comp_id object
#             cursor.execute("SELECT id_category FROM product WHERE id = ?", (comp_id,))
#             id_category = cursor.fetchone()

#             if id_category:
#                 # Fetch the terminal_classifier_name using the id_category
#                 cursor.execute("SELECT terminal_classifier_name FROM terminal_classifier WHERE id = ?", (id_category[0],))
#                 name = cursor.fetchone()

#                 if name:
#                     final_result.append((comp_id, name[0], total_quantity))


#         print(f"Final result for object_id={object_id} and class_id={class_id}: {final_result}")
#         return final_result

#     except Exception as e:
#         print(f"Error occurred while finding components recursively: {e}")
#         return []



def find_components_by_object_and_class_recursive(object_id, class_id):
    try:
        def get_classifier_name(category_id):
            cursor.execute("SELECT terminal_classifier_name FROM terminal_classifier WHERE id = ?", (category_id,))
            row = cursor.fetchone()
            return row[0] if row else None

        def find_components(obj_id, result):
            # Query to get components for the given object ID
            cursor.execute("SELECT comp_id, quantity FROM prod_position_union WHERE prod_id = ?", (obj_id,))
            components = cursor.fetchall()

            for comp_id, quantity in components:
                # Query to get the category and product_name_in_func of the component
                cursor.execute("SELECT id_category, product_name FROM product WHERE id = ?", (comp_id,))
                parent_info = cursor.fetchone()

                if parent_info:
                    product_category = parent_info[0]  # Component's category (id_category)
                    product_name_in_func = parent_info[1]  # Name from terminal_classifier table

                    # Fetch the name of the component category from terminal_classifier
                    classifier_name = get_classifier_name(product_category)

                    # Get all child category names for the given class_id
                    root_category_name = get_classifier_name(class_id)
                    category_children = get_category_children(root_category_name)

                    # Debug logs
                    # print(f"Processing component: {comp_id}")
                    # print(f"Product Name: {product_name_in_func}")
                    # print(f"Category Name: {classifier_name}")
                    # print(f"Category Children: {category_children}")
                    # print(f"Root Category Name: {root_category_name}")

                    # Check if the component's category name (classifier_name) is in the descendants
                    if classifier_name in category_children or classifier_name == root_category_name:
                        # Add or update the accumulated quantity in the result dictionary
                        if comp_id in result:
                            result[comp_id]["quantity"] += quantity
                        else:
                            result[comp_id] = {"name": product_name_in_func, "quantity": quantity, "category_name": classifier_name}

                cursor.execute("SELECT COUNT(*) FROM prod_position_union WHERE prod_id = ?", (comp_id,))
                has_nested_components = cursor.fetchone()[0] > 0

                if has_nested_components:
                    find_components(comp_id, result)

        result = {}
        find_components(object_id, result)

        # Prepare the final result as a list of tuples
        final_result = [
            (comp_id, data["name"], data["quantity"]) for comp_id, data in result.items()
        ]

        print(f"Final result for object_id={object_id} and class_id={class_id}: {final_result}")
        return final_result

    except Exception as e:
        print(f"Error
Соседние файлы в папке 1