fix(db): Added db to actual price

This commit is contained in:
Black_Raven committed 2026-03-30 20:36:24 +03:00
1 parent 39cc73d71a
commit beb94d2b0d
4 files changed
+364 -134

No files matched your search

+94 -28
View File
@@ -23,21 +23,29 @@ def add_category(conn, name, description=None, parent_id=None, image_path=None):
def add_filter(conn, name, filter_key, filter_type='single'): def add_filter(conn, name, filter_key, filter_type='single'):
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(''' try:
INSERT OR IGNORE INTO filters (name, filter_key, filter_type) cursor.execute('''
VALUES (?, ?, ?) INSERT OR IGNORE INTO filters (name, filter_key, filter_type)
''', (name, filter_key, filter_type)) VALUES (?, ?, ?)
''', (name, filter_key, filter_type))
except sqlite3.Error as e:
log.error(f"Ошибка при добавлении фильтра: {e}")
def parse_product_data(product_text): def parse_product_data(product_text):
"""Парсинг данных продукта из текста"""
# Определяем тип применения
application_match = re.search(r'(ВНУТРЕННЕЙ|НАРУЖНОЙ)', product_text) application_match = re.search(r'(ВНУТРЕННЕЙ|НАРУЖНОЙ)', product_text)
application_type = "внутренняя" if application_match and application_match.group(1) == "ВНУТРЕННЕЙ" else "наружная" application_type = "внутренняя" if application_match and application_match.group(1) == "ВНУТРЕННЕЙ" else "наружная"
# Определяем цвет
color_match = re.search(r'цвет\s+([^)]+)', product_text) color_match = re.search(r'цвет\s+([^)]+)', product_text)
color = color_match.group(1).strip() if color_match else None color = color_match.group(1).strip() if color_match else None
# Определяем класс жесткости
stiffness_match = re.search(r'SN(\d+)', product_text) stiffness_match = re.search(r'SN(\d+)', product_text)
stiffness_class = f"SN{stiffness_match.group(1)}" if stiffness_match else None stiffness_class = f"SN{stiffness_match.group(1)}" if stiffness_match else None
# Определяем размеры
size_match = re.search(r'(\d+)х(\d+[,.]?\d*)х(\d+)', product_text.replace(',', '.')) size_match = re.search(r'(\d+)х(\d+[,.]?\d*)х(\d+)', product_text.replace(',', '.'))
if size_match: if size_match:
diameter = int(size_match.group(1)) diameter = int(size_match.group(1))
@@ -46,7 +54,16 @@ def parse_product_data(product_text):
else: else:
diameter = wall_thickness = length = None diameter = wall_thickness = length = None
short_name = f"Труба ПВХ {diameter}мм {application_type} {length}мм" # Для фитингов может не быть длины
if not length and diameter:
# Проверяем на отводы
angle_match = re.search(r'(\d+)°', product_text)
if angle_match:
length = None
else:
length = 0
short_name = f"Труба ПВХ {diameter}мм {application_type} {length}мм" if diameter else product_text[:50]
return { return {
'short_name': short_name, 'short_name': short_name,
@@ -59,11 +76,53 @@ def parse_product_data(product_text):
'stiffness_class': stiffness_class 'stiffness_class': stiffness_class
} }
def add_product(conn, product_text, category_id, image_path=None): def add_product(conn, product_text, category_id, image_path=None,
"""Добавление товара с парсингом параметров и изображением""" diameter=None, wall_thickness=None, length=None,
color=None, application_type=None, stiffness_class=None,
fitting_type=None, angle=None):
"""
Добавление товара с возможностью явного указания параметров
Если параметры не указаны, они парсятся из product_text
"""
cursor = conn.cursor() cursor = conn.cursor()
product_data = parse_product_data(product_text) # Если параметры не указаны явно, парсим из текста
if any(p is None for p in [diameter, wall_thickness, length, color, application_type, stiffness_class]):
product_data = parse_product_data(product_text)
diameter = diameter or product_data['diameter']
wall_thickness = wall_thickness or product_data['wall_thickness']
length = length or product_data['length']
color = color or product_data['color']
application_type = application_type or product_data['application_type']
stiffness_class = stiffness_class or product_data['stiffness_class']
# Формируем короткое имя
if diameter and length:
name = f"Труба ПВХ {diameter}мм {application_type} {length}мм"
elif fitting_type and diameter:
name = f"{fitting_type.capitalize()} ПВХ {diameter}мм"
else:
name = product_text[:100]
# Формируем описание
description_parts = []
if fitting_type:
description_parts.append(f"{fitting_type.capitalize()} для канализационных систем")
else:
description_parts.append(f"Труба ПВХ для {application_type} канализации")
if diameter:
description_parts.append(f"Диаметр: {diameter}мм")
if wall_thickness:
description_parts.append(f"Толщина стенки: {wall_thickness}мм")
if length and length > 0:
description_parts.append(f"Длина: {length}мм")
if stiffness_class:
description_parts.append(f"Класс жесткости: {stiffness_class}")
if angle:
description_parts.append(f"Угол: {angle}")
description = ", ".join(description_parts)
try: try:
cursor.execute(''' cursor.execute('''
@@ -73,33 +132,40 @@ def add_product(conn, product_text, category_id, image_path=None):
application_type, stiffness_class, image_path application_type, stiffness_class, image_path
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', ( ''', (
product_data['short_name'], name,
product_data['full_name'], product_text,
f"Труба ПВХ для {product_data['application_type']} канализации", description,
category_id, category_id,
product_data['diameter'], diameter,
product_data['wall_thickness'], wall_thickness,
product_data['length'], length if length and length > 0 else None,
product_data['color'], color,
product_data['application_type'], application_type,
product_data['stiffness_class'], stiffness_class,
image_path image_path
)) ))
product_id = cursor.lastrowid product_id = cursor.lastrowid
filters_to_add = [ # Добавляем фильтры для товара
('diameter', str(product_data['diameter'])), filters_to_add = []
('length', str(product_data['length'])),
('application_type', product_data['application_type']),
('color', product_data['color']),
]
if product_data['wall_thickness']: if diameter:
filters_to_add.append(('wall_thickness', str(product_data['wall_thickness']))) filters_to_add.append(('diameter', str(diameter)))
if length and length > 0:
if product_data['stiffness_class']: filters_to_add.append(('length', str(length)))
filters_to_add.append(('stiffness_class', product_data['stiffness_class'])) if application_type:
filters_to_add.append(('application_type', application_type))
if color:
filters_to_add.append(('color', color))
if wall_thickness:
filters_to_add.append(('wall_thickness', str(wall_thickness)))
if stiffness_class:
filters_to_add.append(('stiffness_class', stiffness_class))
if fitting_type:
filters_to_add.append(('fitting_type', fitting_type))
if angle:
filters_to_add.append(('angle', angle))
for filter_key, value in filters_to_add: for filter_key, value in filters_to_add:
if value: if value:
+143 -35
View File
@@ -19,6 +19,7 @@ def init_tables(db_name='pipe_store.db'):
log.info("Начинаем инициализацию базы категорий...") log.info("Начинаем инициализацию базы категорий...")
# Основная категория
main_category_id = add_category( main_category_id = add_category(
conn, conn,
"Трубы ПВХ", "Трубы ПВХ",
@@ -26,6 +27,7 @@ def init_tables(db_name='pipe_store.db'):
image_path="/images/categories/pvc_pipes_main.jpg" image_path="/images/categories/pvc_pipes_main.jpg"
) )
# Подкатегории для труб
internal_category_id = add_category( internal_category_id = add_category(
conn, conn,
"Для внутренней канализации", "Для внутренней канализации",
@@ -42,7 +44,8 @@ def init_tables(db_name='pipe_store.db'):
image_path="/images/categories/external_pipes.jpg" image_path="/images/categories/external_pipes.jpg"
) )
add_category( # Категория для фитингов
fittings_category_id = add_category(
conn, conn,
"Фитинги для ПВХ труб", "Фитинги для ПВХ труб",
"Соединительные элементы для ПВХ труб", "Соединительные элементы для ПВХ труб",
@@ -50,63 +53,168 @@ def init_tables(db_name='pipe_store.db'):
image_path="/images/categories/fittings.jpg" image_path="/images/categories/fittings.jpg"
) )
add_category( # Подкатегории для фитингов
elbows_category_id = add_category(
conn, conn,
"Колена и отводы", "Колена и отводы",
"Угловые соединения для ПВХ труб", "Угловые соединения для ПВХ труб",
main_category_id, fittings_category_id,
image_path="/images/categories/elbows.jpg" image_path="/images/categories/elbows.jpg"
) )
tee_category_id = add_category(
conn,
"Тройники",
"Тройники для разветвления труб",
fittings_category_id,
image_path="/images/categories/tees.jpg"
)
couplings_category_id = add_category(
conn,
"Муфты и переходы",
"Соединительные муфты и переходники",
fittings_category_id,
image_path="/images/categories/couplings.jpg"
)
accessories_category_id = add_category(
conn,
"Заглушки и ревизии",
"Заглушки и ревизионные элементы",
fittings_category_id,
image_path="/images/categories/accessories.jpg"
)
log.info("Категории успешно созданы") log.info("Категории успешно созданы")
# Добавляем фильтры
add_filter(conn, "Диаметр", "diameter", "multiple") add_filter(conn, "Диаметр", "diameter", "multiple")
add_filter(conn, "Длина", "length", "multiple") add_filter(conn, "Длина", "length", "multiple")
add_filter(conn, "Тип применения", "application_type", "single") add_filter(conn, "Тип применения", "application_type", "single")
add_filter(conn, "Цвет", "color", "single") add_filter(conn, "Цвет", "color", "single")
add_filter(conn, "Класс жесткости", "stiffness_class", "single") add_filter(conn, "Класс жесткости", "stiffness_class", "single")
add_filter(conn, "Толщина стенки", "wall_thickness", "multiple") add_filter(conn, "Толщина стенки", "wall_thickness", "multiple")
add_filter(conn, "Угол", "angle", "multiple") # Для отводов и колен
add_filter(conn, "Тип фитинга", "fitting_type", "single") # Для фитингов
log.info("Фильтры успешно добавлены") log.info("Фильтры успешно добавлены")
# Данные продуктов # ==================== ТОВАРЫ ====================
products_data = [
# Внутренние трубы # 1. Внутренние трубы (серые)
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х500", "image": "/images/products/internal_110_500.jpg"}, internal_pipes = [
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х1000", "image": "/images/products/internal_110_1000.jpg"}, ("110х2,2х500", 110, 2.2, 500, "серый", "внутренняя", None),
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х1500", "image": "/images/products/internal_110_1500.jpg"}, ("110х2,2х1000", 110, 2.2, 1000, "серый", "внутренняя", None),
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х2000", "image": "/images/products/internal_110_2000.jpg"}, ("110х2,2х1500", 110, 2.2, 1500, "серый", "внутренняя", None),
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х3000", "image": "/images/products/internal_110_3000.jpg"}, ("110х2,2х2000", 110, 2.2, 2000, "серый", "внутренняя", None),
("110х2,2х3000", 110, 2.2, 3000, "серый", "внутренняя", None),
# Наружные трубы
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х500", "image": "/images/products/external_110_sn4_500.jpg"},
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х1000", "image": "/images/products/external_110_sn4_1000.jpg"},
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х2000", "image": "/images/products/external_110_sn4_2000.jpg"},
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х3000", "image": "/images/products/external_110_sn4_3000.jpg"},
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х4000", "image": "/images/products/external_110_sn4_4000.jpg"},
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN2 160х3,6х1000", "image": "/images/products/external_160_sn2_1000.jpg"},
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN2 160х3,6х2000", "image": "/images/products/external_160_sn2_2000.jpg"},
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN2 160х3,6х3000", "image": "/images/products/external_160_sn2_3000.jpg"},
] ]
added_products = 0 added_products = 0
for product_info in products_data:
product_text = product_info["text"] for size, diameter, thickness, length, color, app_type, stiffness in internal_pipes:
image_path = product_info["image"] full_name = f"Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет {color}), со сплошной стенкой толщиной {thickness} мм {diameter}x{thickness}x{length}"
image_path = f"/images/products/internal_{diameter}_{length}.jpg"
if "ВНУТРЕННЕЙ" in product_text: product_id = add_product(
category_id = internal_category_id conn, full_name, internal_category_id, image_path,
else: diameter, thickness, length, color, app_type, stiffness
category_id = external_category_id )
product_id = add_product(conn, product_text, category_id, image_path)
if product_id: if product_id:
added_products += 1 added_products += 1
log.info(f"Добавлен товар: {product_text[:50]}...") log.info(f"Добавлен товар: {full_name[:50]}...")
else:
log.error(f"Ошибка при добавлении товара: {product_text}") # 2. Наружные трубы (оранжево-коричневые) - все типы
external_pipes = [
# Без маркировки (обычные)
("110х2,3х500", 110, 2.3, 500, "оранжево-коричневый", "наружная", None),
("110х2,3х1000", 110, 2.3, 1000, "оранжево-коричневый", "наружная", None),
("110х2,3х2000", 110, 2.3, 2000, "оранжево-коричневый", "наружная", None),
("110х2,3х3000", 110, 2.3, 3000, "оранжево-коричневый", "наружная", None),
("110х2,3х4000", 110, 2.3, 4000, "оранжево-коричневый", "наружная", None),
# SN2
("110х2,7х500 SN2", 110, 2.7, 500, "оранжево-коричневый", "наружная", "SN2"),
("110х2,7х1000 SN2", 110, 2.7, 1000, "оранжево-коричневый", "наружная", "SN2"),
("110х2,7х2000 SN2", 110, 2.7, 2000, "оранжево-коричневый", "наружная", "SN2"),
("110х2,7х3000 SN2", 110, 2.7, 3000, "оранжево-коричневый", "наружная", "SN2"),
("110х2,7х4000 SN2", 110, 2.7, 4000, "оранжево-коричневый", "наружная", "SN2"),
# SN4
("110х3,2х500 SN4", 110, 3.2, 500, "оранжево-коричневый", "наружная", "SN4"),
("110х3,2х1000 SN4", 110, 3.2, 1000, "оранжево-коричневый", "наружная", "SN4"),
("110х3,2х2000 SN4", 110, 3.2, 2000, "оранжево-коричневый", "наружная", "SN4"),
("110х3,2х3000 SN4", 110, 3.2, 3000, "оранжево-коричневый", "наружная", "SN4"),
("110х3,2х4000 SN4", 110, 3.2, 4000, "оранжево-коричневый", "наружная", "SN4"),
# 160 мм
("160х3,6х1000 SN2", 160, 3.6, 1000, "оранжево-коричневый", "наружная", "SN2"),
("160х3,6х2000 SN2", 160, 3.6, 2000, "оранжево-коричневый", "наружная", "SN2"),
("160х3,6х3000 SN2", 160, 3.6, 3000, "оранжево-коричневый", "наружная", "SN2"),
("160х4,0х1000 SN4", 160, 4.0, 1000, "оранжево-коричневый", "наружная", "SN4"),
("160х4,0х2000 SN4", 160, 4.0, 2000, "оранжево-коричневый", "наружная", "SN4"),
("160х4,0х3000 SN4", 160, 4.0, 3000, "оранжево-коричневый", "наружная", "SN4"),
]
for size, diameter, thickness, length, color, app_type, stiffness in external_pipes:
stiffness_text = f", класс жесткости {stiffness}" if stiffness else ""
full_name = f"Труба ПВХ для НАРУЖНОЙ канализации (цвет {color}), со сплошной стенкой{stiffness_text} {diameter}x{thickness}x{length}"
image_path = f"/images/products/external_{diameter}_{stiffness or 'std'}_{length}.jpg"
product_id = add_product(
conn, full_name, external_category_id, image_path,
diameter, thickness, length, color, app_type, stiffness
)
if product_id:
added_products += 1
log.info(f"Добавлен товар: {full_name[:50]}...")
# 3. Фитинги
fittings = [
# Отводы (колена)
("Отвод 110х15°", elbows_category_id, "отвод", 110, None, None, None, None, "15°"),
("Отвод 110х30°", elbows_category_id, "отвод", 110, None, None, None, None, "30°"),
("Отвод 110х45°", elbows_category_id, "отвод", 110, None, None, None, None, "45°"),
("Отвод 110х87°", elbows_category_id, "отвод", 110, None, None, None, None, "87°"),
("Отвод 160х15°", elbows_category_id, "отвод", 160, None, None, None, None, "15°"),
("Отвод 160х30°", elbows_category_id, "отвод", 160, None, None, None, None, "30°"),
("Отвод 160х45°", elbows_category_id, "отвод", 160, None, None, None, None, "45°"),
("Отвод 160х87°", elbows_category_id, "отвод", 160, None, None, None, None, "87°"),
# Тройники
("Тройник 45° 110х110", tee_category_id, "тройник", 110, None, None, None, None, "45°"),
("Тройник 45° 160х110", tee_category_id, "тройник", 160, None, None, None, None, "45°"),
("Тройник 45° 160х160", tee_category_id, "тройник", 160, None, None, None, None, "45°"),
("Тройник 87° 110х110", tee_category_id, "тройник", 110, None, None, None, None, "87°"),
("Тройник 87° 160х110", tee_category_id, "тройник", 160, None, None, None, None, "87°"),
("Тройник 87° 160х160", tee_category_id, "тройник", 160, None, None, None, None, "87°"),
# Муфты
("Муфта надвижная (ремонтная) 110", couplings_category_id, "муфта", 110, None, None, None, None, None),
("Муфта надвижная (ремонтная) 160", couplings_category_id, "муфта", 160, None, None, None, None, None),
("Муфта соединительная 110", couplings_category_id, "муфта", 110, None, None, None, None, None),
("Муфта соединительная 160", couplings_category_id, "муфта", 160, None, None, None, None, None),
("Редуктор 160", couplings_category_id, "редуктор", 160, None, None, None, None, None),
# Заглушки и ревизии
("Заглушка для раструба 110", accessories_category_id, "заглушка", 110, None, None, None, None, None),
("Заглушка для раструба 160", accessories_category_id, "заглушка", 160, None, None, None, None, None),
("Ревизия 110", accessories_category_id, "ревизия", 110, None, None, None, None, None),
("Ревизия 160", accessories_category_id, "ревизия", 160, None, None, None, None, None),
]
for name, cat_id, fitting_type, diameter, thickness, length, color, app_type, angle in fittings:
full_name = f"{name} для наружной канализации"
image_path = f"/images/products/{name.lower().replace(' ', '_').replace('°', 'deg')}.jpg"
product_id = add_product(
conn, full_name, cat_id, image_path,
diameter, thickness, length, color, app_type, None,
fitting_type=fitting_type, angle=angle
)
if product_id:
added_products += 1
log.info(f"Добавлен товар: {full_name[:50]}...")
conn.commit() conn.commit()
conn.close() conn.close()
log.success(f"Успешно добавлено {added_products} товаров в базу категорий!") log.success(f"Успешно добавлено {added_products} товаров в базу данных!")
+62 -9
View File
@@ -12,7 +12,7 @@ def get_all_categories_with_attributes(db_name: str = 'pipe_store.db') -> List[D
cursor.execute(""" cursor.execute("""
SELECT id, name, image_path SELECT id, name, image_path
FROM categories FROM categories
WHERE parent_id IS NULL OR parent_id = 1 WHERE parent_id IS NULL
ORDER BY id ORDER BY id
""") """)
@@ -21,7 +21,7 @@ def get_all_categories_with_attributes(db_name: str = 'pipe_store.db') -> List[D
for cat_row in cursor.fetchall(): for cat_row in cursor.fetchall():
category_id = cat_row['id'] category_id = cat_row['id']
# Получаем все фильтры для товаров в этой категории # Получаем все фильтры для товаров в этой категории и подкатегориях
cursor.execute(""" cursor.execute("""
SELECT DISTINCT f.id, f.name, f.filter_key SELECT DISTINCT f.id, f.name, f.filter_key
FROM filters f FROM filters f
@@ -29,10 +29,13 @@ def get_all_categories_with_attributes(db_name: str = 'pipe_store.db') -> List[D
SELECT DISTINCT pf.filter_key SELECT DISTINCT pf.filter_key
FROM product_filters pf FROM product_filters pf
JOIN products p ON pf.product_id = p.id JOIN products p ON pf.product_id = p.id
WHERE p.category_id = ? WHERE p.category_id IN (
SELECT id FROM categories
WHERE id = ? OR parent_id = ?
)
) )
ORDER BY f.id ORDER BY f.id
""", (category_id,)) """, (category_id, category_id))
attributes = [] attributes = []
@@ -46,21 +49,24 @@ def get_all_categories_with_attributes(db_name: str = 'pipe_store.db') -> List[D
SELECT DISTINCT pf.value, COUNT(*) as count SELECT DISTINCT pf.value, COUNT(*) as count
FROM product_filters pf FROM product_filters pf
JOIN products p ON pf.product_id = p.id JOIN products p ON pf.product_id = p.id
WHERE p.category_id = ? AND pf.filter_key = ? WHERE p.category_id IN (
SELECT id FROM categories
WHERE id = ? OR parent_id = ?
)
AND pf.filter_key = ?
GROUP BY pf.value GROUP BY pf.value
ORDER BY pf.value ORDER BY pf.value
""", (category_id, filter_key)) """, (category_id, category_id, filter_key))
vals = [] vals = []
for val_row in cursor.fetchall(): for val_row in cursor.fetchall():
# Генерируем уникальный ID для значения
val_id = hash(f"{category_id}_{filter_key}_{val_row['value']}") % 1000000 val_id = hash(f"{category_id}_{filter_key}_{val_row['value']}") % 1000000
vals.append({ vals.append({
"id": val_id, "id": val_id,
"val": val_row['value'] "val": val_row['value']
}) })
if vals: # Добавляем только если есть значения if vals:
attributes.append({ attributes.append({
"id": filter_id, "id": filter_id,
"name": filter_name, "name": filter_name,
@@ -97,12 +103,28 @@ def get_category_by_id(category_id: int, db_name: str = 'pipe_store.db') -> Opti
row = cursor.fetchone() row = cursor.fetchone()
if row: if row:
# Получаем подкатегории
cursor.execute("""
SELECT id, name, image_path
FROM categories
WHERE parent_id = ?
""", (category_id,))
subcategories = []
for sub_row in cursor.fetchall():
subcategories.append({
"id": sub_row['id'],
"name": sub_row['name'],
"image": sub_row['image_path']
})
return { return {
"id": row['id'], "id": row['id'],
"name": row['name'], "name": row['name'],
"description": row['description'], "description": row['description'],
"image": row['image_path'], "image": row['image_path'],
"parent_id": row['parent_id'] "parent_id": row['parent_id'],
"subcategories": subcategories
} }
return None return None
@@ -111,3 +133,34 @@ def get_category_by_id(category_id: int, db_name: str = 'pipe_store.db') -> Opti
return None return None
finally: finally:
conn.close() conn.close()
def get_subcategories(parent_id: int, db_name: str = 'pipe_store.db') -> List[Dict[str, Any]]:
"""Получить подкатегории для родительской категории"""
conn = sqlite3.connect(db_name)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
try:
cursor.execute("""
SELECT id, name, description, image_path
FROM categories
WHERE parent_id = ?
ORDER BY id
""", (parent_id,))
subcategories = []
for row in cursor.fetchall():
subcategories.append({
"id": row['id'],
"name": row['name'],
"description": row['description'],
"image": row['image_path']
})
return subcategories
except sqlite3.Error as e:
log.error(f"Ошибка при получении подкатегорий для {parent_id}: {e}")
return []
finally:
conn.close()
+65 -62
View File
@@ -77,11 +77,13 @@ def get_products_with_filters(
# Формируем атрибуты товара # Формируем атрибуты товара
attributes = {} attributes = {}
# Добавляем все возможные атрибуты
if row['color']: if row['color']:
attributes['color'] = row['color'] attributes['color'] = row['color']
if row['length']: if row['length'] and row['length'] > 0:
attributes['size'] = f"{row['diameter']}x{row['wall_thickness']}x{row['length']}" if row['diameter'] else str(row['length']) if row['diameter'] and row['wall_thickness']:
attributes['size'] = f"{row['diameter']}x{row['wall_thickness']}x{row['length']}"
else:
attributes['size'] = str(row['length'])
if row['diameter']: if row['diameter']:
attributes['diameter'] = str(row['diameter']) attributes['diameter'] = str(row['diameter'])
if row['wall_thickness']: if row['wall_thickness']:
@@ -91,18 +93,30 @@ def get_products_with_filters(
if row['application_type']: if row['application_type']:
attributes['application_type'] = row['application_type'] attributes['application_type'] = row['application_type']
# Получаем дополнительные атрибуты из product_filters
cursor.execute("""
SELECT filter_key, value
FROM product_filters
WHERE product_id = ?
""", (row['id'],))
for filter_row in cursor.fetchall():
if filter_row['filter_key'] not in attributes:
attributes[filter_row['filter_key']] = filter_row['value']
# Определяем количество в упаковке (можно вынести в отдельную таблицу) # Определяем количество в упаковке (можно вынести в отдельную таблицу)
attributes['amount'] = get_pack_amount(row['id'], conn) attributes['amount'] = get_pack_amount(row['id'], row['diameter'], conn)
items.append({ items.append({
"id": row['id'], "id": row['id'],
"name": row['name'], "name": row['name'],
"description": row['description'] or f"Труба ПВХ {row['diameter']}мм", "description": row['description'] or f"Труба ПВХ {row['diameter']}мм" if row['diameter'] else "Товар",
"price": calculate_price(row), # Функция для расчета цены # Цена не хранится в БД - возвращаем 0 или None
"price": None,
"categoryId": category_id, "categoryId": category_id,
"images": get_product_images(row['id'], row['image_path'], conn), "images": get_product_images(row['id'], row['image_path'], conn),
"attributes": attributes, "attributes": attributes,
"inStock": check_stock(row['id'], conn) # Проверка наличия "inStock": check_stock(row['id'], conn)
}) })
return { return {
@@ -122,13 +136,6 @@ def get_products_with_filters(
def get_product_by_id(product_id: int, db_name: str = 'pipe_store.db') -> Optional[Dict[str, Any]]: def get_product_by_id(product_id: int, db_name: str = 'pipe_store.db') -> Optional[Dict[str, Any]]:
""" """
Получить товар по ID с полной информацией Получить товар по ID с полной информацией
Args:
product_id: ID товара
db_name: Имя базы данных
Returns:
Dict с полной информацией о товаре или None
""" """
conn = sqlite3.connect(db_name) conn = sqlite3.connect(db_name)
conn.row_factory = sqlite3.Row conn.row_factory = sqlite3.Row
@@ -148,29 +155,46 @@ def get_product_by_id(product_id: int, db_name: str = 'pipe_store.db') -> Option
if not row: if not row:
return None return None
# Получаем все изображения товара (если есть несколько)
images = get_product_images(product_id, row['image_path'], conn) images = get_product_images(product_id, row['image_path'], conn)
# Формируем полное описание # Получаем дополнительные фильтры
cursor.execute("""
SELECT filter_key, value
FROM product_filters
WHERE product_id = ?
""", (product_id,))
extra_attributes = {}
for filter_row in cursor.fetchall():
extra_attributes[filter_row['filter_key']] = filter_row['value']
full_description = generate_full_description(row) full_description = generate_full_description(row)
# Формируем атрибуты
attributes = {
"color": row['color'],
"diameter": str(row['diameter']) if row['diameter'] else None,
"wall_thickness": str(row['wall_thickness']) if row['wall_thickness'] else None,
"length": str(row['length']) if row['length'] and row['length'] > 0 else None,
"stiffness_class": row['stiffness_class'],
"application_type": row['application_type'],
}
if all([row['diameter'], row['wall_thickness'], row['length'] and row['length'] > 0]):
attributes["size"] = f"{row['diameter']}x{row['wall_thickness']}x{row['length']}"
# Добавляем дополнительные атрибуты
attributes.update(extra_attributes)
return { return {
"id": row['id'], "id": row['id'],
"name": row['name'], "name": row['name'],
"full_name": row['full_name'], "full_name": row['full_name'],
"description": full_description, "description": full_description,
"price": calculate_price(row), "price": None, # Цена не хранится в БД
"categoryId": row['category_id'], "categoryId": row['category_id'],
"images": images, "images": images,
"attributes": { "attributes": attributes,
"color": row['color'],
"diameter": str(row['diameter']) if row['diameter'] else None,
"wall_thickness": str(row['wall_thickness']) if row['wall_thickness'] else None,
"length": str(row['length']) if row['length'] else None,
"stiffness_class": row['stiffness_class'],
"application_type": row['application_type'],
"size": f"{row['diameter']}x{row['wall_thickness']}x{row['length']}" if all([row['diameter'], row['wall_thickness'], row['length']]) else None
},
"inStock": check_stock(product_id, conn), "inStock": check_stock(product_id, conn),
"created_at": row['created_at'] "created_at": row['created_at']
} }
@@ -182,57 +206,34 @@ def get_product_by_id(product_id: int, db_name: str = 'pipe_store.db') -> Option
conn.close() conn.close()
def get_product_images(product_id: int, main_image: Optional[str], conn: sqlite3.Connection) -> List[str]: def get_product_images(product_id: int, main_image: Optional[str], conn: sqlite3.Connection) -> List[str]:
""" """Получить список изображений товара"""
Получить список изображений товара
(В текущей структуре только одно изображение, но можно расширить)
"""
images = [] images = []
if main_image: if main_image:
images.append(main_image) images.append(main_image)
# Здесь можно добавить логику для получения дополнительных изображений
# Например, из отдельной таблицы product_images
# Если нет изображения, возвращаем заглушку
if not images: if not images:
images.append("/images/products/default.jpg") images.append("/images/products/default.jpg")
return images return images
def calculate_price(row: sqlite3.Row) -> float:
"""
Рассчитать цену товара на основе параметров
(В реальном проекте цена должна быть в базе данных)
"""
# Временная логика расчета цены
base_price = 500
if row['diameter']:
base_price += (row['diameter'] - 50) * 5
if row['length']:
base_price += row['length'] * 0.1
if row['stiffness_class'] == 'SN4':
base_price *= 1.2
return round(base_price, 2)
def check_stock(product_id: int, conn: sqlite3.Connection) -> bool: def check_stock(product_id: int, conn: sqlite3.Connection) -> bool:
""" """Проверить наличие товара на складе"""
Проверить наличие товара на складе
(В реальном проекте должна быть таблица stock)
"""
# Временная логика - все товары в наличии # Временная логика - все товары в наличии
# В будущем можно добавить таблицу stock
return True return True
def get_pack_amount(product_id: int, conn: sqlite3.Connection) -> str: def get_pack_amount(product_id: int, diameter: int = None, conn: sqlite3.Connection = None) -> str:
""" """
Получить количество в упаковке Получить количество в упаковке
(В реальном проекте должно быть в базе данных) В реальном проекте должно быть в базе данных
""" """
# Временная логика # Временная логика на основе диаметра
return "4" if diameter:
if diameter == 110:
return "6-10"
elif diameter == 160:
return "2"
return "1"
def generate_full_description(row: sqlite3.Row) -> str: def generate_full_description(row: sqlite3.Row) -> str:
"""Сгенерировать полное описание товара""" """Сгенерировать полное описание товара"""
@@ -247,8 +248,10 @@ def generate_full_description(row: sqlite3.Row) -> str:
if row['application_type']: if row['application_type']:
parts.append(f"Тип применения: {row['application_type']} канализация") parts.append(f"Тип применения: {row['application_type']} канализация")
if row['diameter'] and row['wall_thickness'] and row['length']: if row['diameter'] and row['wall_thickness'] and row['length'] and row['length'] > 0:
parts.append(f"Размеры: {row['diameter']}x{row['wall_thickness']}x{row['length']} мм") parts.append(f"Размеры: {row['diameter']}x{row['wall_thickness']}x{row['length']} мм")
elif row['diameter']:
parts.append(f"Диаметр: {row['diameter']} мм")
if row['stiffness_class']: if row['stiffness_class']:
parts.append(f"Класс жесткости: {row['stiffness_class']}") parts.append(f"Класс жесткости: {row['stiffness_class']}")