fix(db): Added db to actual price
This commit is contained in:
1 parent
39cc73d71a
commit
beb94d2b0d
4 files changed
+364
-134
No files matched your search
+94
-28
@@ -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'):
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('''
|
||||
INSERT OR IGNORE INTO filters (name, filter_key, filter_type)
|
||||
VALUES (?, ?, ?)
|
||||
''', (name, filter_key, filter_type))
|
||||
try:
|
||||
cursor.execute('''
|
||||
INSERT OR IGNORE INTO filters (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):
|
||||
"""Парсинг данных продукта из текста"""
|
||||
# Определяем тип применения
|
||||
application_match = re.search(r'(ВНУТРЕННЕЙ|НАРУЖНОЙ)', product_text)
|
||||
application_type = "внутренняя" if application_match and application_match.group(1) == "ВНУТРЕННЕЙ" else "наружная"
|
||||
|
||||
# Определяем цвет
|
||||
color_match = re.search(r'цвет\s+([^)]+)', product_text)
|
||||
color = color_match.group(1).strip() if color_match else None
|
||||
|
||||
# Определяем класс жесткости
|
||||
stiffness_match = re.search(r'SN(\d+)', product_text)
|
||||
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(',', '.'))
|
||||
if size_match:
|
||||
diameter = int(size_match.group(1))
|
||||
@@ -46,7 +54,16 @@ def parse_product_data(product_text):
|
||||
else:
|
||||
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 {
|
||||
'short_name': short_name,
|
||||
@@ -59,11 +76,53 @@ def parse_product_data(product_text):
|
||||
'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()
|
||||
|
||||
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:
|
||||
cursor.execute('''
|
||||
@@ -73,33 +132,40 @@ def add_product(conn, product_text, category_id, image_path=None):
|
||||
application_type, stiffness_class, image_path
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', (
|
||||
product_data['short_name'],
|
||||
product_data['full_name'],
|
||||
f"Труба ПВХ для {product_data['application_type']} канализации",
|
||||
name,
|
||||
product_text,
|
||||
description,
|
||||
category_id,
|
||||
product_data['diameter'],
|
||||
product_data['wall_thickness'],
|
||||
product_data['length'],
|
||||
product_data['color'],
|
||||
product_data['application_type'],
|
||||
product_data['stiffness_class'],
|
||||
diameter,
|
||||
wall_thickness,
|
||||
length if length and length > 0 else None,
|
||||
color,
|
||||
application_type,
|
||||
stiffness_class,
|
||||
image_path
|
||||
))
|
||||
|
||||
product_id = cursor.lastrowid
|
||||
|
||||
filters_to_add = [
|
||||
('diameter', str(product_data['diameter'])),
|
||||
('length', str(product_data['length'])),
|
||||
('application_type', product_data['application_type']),
|
||||
('color', product_data['color']),
|
||||
]
|
||||
# Добавляем фильтры для товара
|
||||
filters_to_add = []
|
||||
|
||||
if product_data['wall_thickness']:
|
||||
filters_to_add.append(('wall_thickness', str(product_data['wall_thickness'])))
|
||||
|
||||
if product_data['stiffness_class']:
|
||||
filters_to_add.append(('stiffness_class', product_data['stiffness_class']))
|
||||
if diameter:
|
||||
filters_to_add.append(('diameter', str(diameter)))
|
||||
if length and length > 0:
|
||||
filters_to_add.append(('length', str(length)))
|
||||
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:
|
||||
if value:
|
||||
|
||||
+143
-35
@@ -19,6 +19,7 @@ def init_tables(db_name='pipe_store.db'):
|
||||
|
||||
log.info("Начинаем инициализацию базы категорий...")
|
||||
|
||||
# Основная категория
|
||||
main_category_id = add_category(
|
||||
conn,
|
||||
"Трубы ПВХ",
|
||||
@@ -26,6 +27,7 @@ def init_tables(db_name='pipe_store.db'):
|
||||
image_path="/images/categories/pvc_pipes_main.jpg"
|
||||
)
|
||||
|
||||
# Подкатегории для труб
|
||||
internal_category_id = add_category(
|
||||
conn,
|
||||
"Для внутренней канализации",
|
||||
@@ -42,7 +44,8 @@ def init_tables(db_name='pipe_store.db'):
|
||||
image_path="/images/categories/external_pipes.jpg"
|
||||
)
|
||||
|
||||
add_category(
|
||||
# Категория для фитингов
|
||||
fittings_category_id = add_category(
|
||||
conn,
|
||||
"Фитинги для ПВХ труб",
|
||||
"Соединительные элементы для ПВХ труб",
|
||||
@@ -50,63 +53,168 @@ def init_tables(db_name='pipe_store.db'):
|
||||
image_path="/images/categories/fittings.jpg"
|
||||
)
|
||||
|
||||
add_category(
|
||||
# Подкатегории для фитингов
|
||||
elbows_category_id = add_category(
|
||||
conn,
|
||||
"Колена и отводы",
|
||||
"Угловые соединения для ПВХ труб",
|
||||
main_category_id,
|
||||
fittings_category_id,
|
||||
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("Категории успешно созданы")
|
||||
|
||||
# Добавляем фильтры
|
||||
add_filter(conn, "Диаметр", "diameter", "multiple")
|
||||
add_filter(conn, "Длина", "length", "multiple")
|
||||
add_filter(conn, "Тип применения", "application_type", "single")
|
||||
add_filter(conn, "Цвет", "color", "single")
|
||||
add_filter(conn, "Класс жесткости", "stiffness_class", "single")
|
||||
add_filter(conn, "Толщина стенки", "wall_thickness", "multiple")
|
||||
add_filter(conn, "Угол", "angle", "multiple") # Для отводов и колен
|
||||
add_filter(conn, "Тип фитинга", "fitting_type", "single") # Для фитингов
|
||||
|
||||
log.info("Фильтры успешно добавлены")
|
||||
|
||||
# Данные продуктов
|
||||
products_data = [
|
||||
# Внутренние трубы
|
||||
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х500", "image": "/images/products/internal_110_500.jpg"},
|
||||
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х1000", "image": "/images/products/internal_110_1000.jpg"},
|
||||
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х1500", "image": "/images/products/internal_110_1500.jpg"},
|
||||
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х2000", "image": "/images/products/internal_110_2000.jpg"},
|
||||
{"text": "Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет серый), с внутренней структурной стенкой толщиной 2,2 мм 110х2,2х3000", "image": "/images/products/internal_110_3000.jpg"},
|
||||
|
||||
# Наружные трубы
|
||||
{"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"},
|
||||
# ==================== ТОВАРЫ ====================
|
||||
|
||||
# 1. Внутренние трубы (серые)
|
||||
internal_pipes = [
|
||||
("110х2,2х500", 110, 2.2, 500, "серый", "внутренняя", None),
|
||||
("110х2,2х1000", 110, 2.2, 1000, "серый", "внутренняя", None),
|
||||
("110х2,2х1500", 110, 2.2, 1500, "серый", "внутренняя", None),
|
||||
("110х2,2х2000", 110, 2.2, 2000, "серый", "внутренняя", None),
|
||||
("110х2,2х3000", 110, 2.2, 3000, "серый", "внутренняя", None),
|
||||
]
|
||||
|
||||
|
||||
added_products = 0
|
||||
for product_info in products_data:
|
||||
product_text = product_info["text"]
|
||||
image_path = product_info["image"]
|
||||
|
||||
for size, diameter, thickness, length, color, app_type, stiffness in internal_pipes:
|
||||
full_name = f"Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет {color}), со сплошной стенкой толщиной {thickness} мм {diameter}x{thickness}x{length}"
|
||||
image_path = f"/images/products/internal_{diameter}_{length}.jpg"
|
||||
|
||||
if "ВНУТРЕННЕЙ" in product_text:
|
||||
category_id = internal_category_id
|
||||
else:
|
||||
category_id = external_category_id
|
||||
|
||||
product_id = add_product(conn, product_text, category_id, image_path)
|
||||
product_id = add_product(
|
||||
conn, full_name, internal_category_id, image_path,
|
||||
diameter, thickness, length, color, app_type, stiffness
|
||||
)
|
||||
if product_id:
|
||||
added_products += 1
|
||||
log.info(f"Добавлен товар: {product_text[:50]}...")
|
||||
else:
|
||||
log.error(f"Ошибка при добавлении товара: {product_text}")
|
||||
log.info(f"Добавлен товар: {full_name[:50]}...")
|
||||
|
||||
# 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.close()
|
||||
|
||||
log.success(f"Успешно добавлено {added_products} товаров в базу категорий!")
|
||||
log.success(f"Успешно добавлено {added_products} товаров в базу данных!")
|
||||
@@ -12,7 +12,7 @@ def get_all_categories_with_attributes(db_name: str = 'pipe_store.db') -> List[D
|
||||
cursor.execute("""
|
||||
SELECT id, name, image_path
|
||||
FROM categories
|
||||
WHERE parent_id IS NULL OR parent_id = 1
|
||||
WHERE parent_id IS NULL
|
||||
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():
|
||||
category_id = cat_row['id']
|
||||
|
||||
# Получаем все фильтры для товаров в этой категории
|
||||
# Получаем все фильтры для товаров в этой категории и подкатегориях
|
||||
cursor.execute("""
|
||||
SELECT DISTINCT f.id, f.name, f.filter_key
|
||||
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
|
||||
FROM product_filters pf
|
||||
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
|
||||
""", (category_id,))
|
||||
""", (category_id, category_id))
|
||||
|
||||
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
|
||||
FROM product_filters pf
|
||||
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
|
||||
ORDER BY pf.value
|
||||
""", (category_id, filter_key))
|
||||
""", (category_id, category_id, filter_key))
|
||||
|
||||
vals = []
|
||||
for val_row in cursor.fetchall():
|
||||
# Генерируем уникальный ID для значения
|
||||
val_id = hash(f"{category_id}_{filter_key}_{val_row['value']}") % 1000000
|
||||
vals.append({
|
||||
"id": val_id,
|
||||
"val": val_row['value']
|
||||
})
|
||||
|
||||
if vals: # Добавляем только если есть значения
|
||||
if vals:
|
||||
attributes.append({
|
||||
"id": filter_id,
|
||||
"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()
|
||||
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 {
|
||||
"id": row['id'],
|
||||
"name": row['name'],
|
||||
"description": row['description'],
|
||||
"image": row['image_path'],
|
||||
"parent_id": row['parent_id']
|
||||
"parent_id": row['parent_id'],
|
||||
"subcategories": subcategories
|
||||
}
|
||||
return None
|
||||
|
||||
@@ -111,3 +133,34 @@ def get_category_by_id(category_id: int, db_name: str = 'pipe_store.db') -> Opti
|
||||
return None
|
||||
finally:
|
||||
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()
|
||||
@@ -77,11 +77,13 @@ def get_products_with_filters(
|
||||
# Формируем атрибуты товара
|
||||
attributes = {}
|
||||
|
||||
# Добавляем все возможные атрибуты
|
||||
if row['color']:
|
||||
attributes['color'] = row['color']
|
||||
if row['length']:
|
||||
attributes['size'] = f"{row['diameter']}x{row['wall_thickness']}x{row['length']}" if row['diameter'] else str(row['length'])
|
||||
if row['length'] and row['length'] > 0:
|
||||
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']:
|
||||
attributes['diameter'] = str(row['diameter'])
|
||||
if row['wall_thickness']:
|
||||
@@ -91,18 +93,30 @@ def get_products_with_filters(
|
||||
if 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({
|
||||
"id": row['id'],
|
||||
"name": row['name'],
|
||||
"description": row['description'] or f"Труба ПВХ {row['diameter']}мм",
|
||||
"price": calculate_price(row), # Функция для расчета цены
|
||||
"description": row['description'] or f"Труба ПВХ {row['diameter']}мм" if row['diameter'] else "Товар",
|
||||
# Цена не хранится в БД - возвращаем 0 или None
|
||||
"price": None,
|
||||
"categoryId": category_id,
|
||||
"images": get_product_images(row['id'], row['image_path'], conn),
|
||||
"attributes": attributes,
|
||||
"inStock": check_stock(row['id'], conn) # Проверка наличия
|
||||
"inStock": check_stock(row['id'], conn)
|
||||
})
|
||||
|
||||
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]]:
|
||||
"""
|
||||
Получить товар по ID с полной информацией
|
||||
|
||||
Args:
|
||||
product_id: ID товара
|
||||
db_name: Имя базы данных
|
||||
|
||||
Returns:
|
||||
Dict с полной информацией о товаре или None
|
||||
"""
|
||||
conn = sqlite3.connect(db_name)
|
||||
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:
|
||||
return None
|
||||
|
||||
# Получаем все изображения товара (если есть несколько)
|
||||
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)
|
||||
|
||||
# Формируем атрибуты
|
||||
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 {
|
||||
"id": row['id'],
|
||||
"name": row['name'],
|
||||
"full_name": row['full_name'],
|
||||
"description": full_description,
|
||||
"price": calculate_price(row),
|
||||
"price": None, # Цена не хранится в БД
|
||||
"categoryId": row['category_id'],
|
||||
"images": images,
|
||||
"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
|
||||
},
|
||||
"attributes": attributes,
|
||||
"inStock": check_stock(product_id, conn),
|
||||
"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()
|
||||
|
||||
def get_product_images(product_id: int, main_image: Optional[str], conn: sqlite3.Connection) -> List[str]:
|
||||
"""
|
||||
Получить список изображений товара
|
||||
(В текущей структуре только одно изображение, но можно расширить)
|
||||
"""
|
||||
"""Получить список изображений товара"""
|
||||
images = []
|
||||
if main_image:
|
||||
images.append(main_image)
|
||||
|
||||
# Здесь можно добавить логику для получения дополнительных изображений
|
||||
# Например, из отдельной таблицы product_images
|
||||
|
||||
# Если нет изображения, возвращаем заглушку
|
||||
if not images:
|
||||
images.append("/images/products/default.jpg")
|
||||
|
||||
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:
|
||||
"""
|
||||
Проверить наличие товара на складе
|
||||
(В реальном проекте должна быть таблица stock)
|
||||
"""
|
||||
"""Проверить наличие товара на складе"""
|
||||
# Временная логика - все товары в наличии
|
||||
# В будущем можно добавить таблицу stock
|
||||
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:
|
||||
"""Сгенерировать полное описание товара"""
|
||||
@@ -247,8 +248,10 @@ def generate_full_description(row: sqlite3.Row) -> str:
|
||||
if 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']} мм")
|
||||
elif row['diameter']:
|
||||
parts.append(f"Диаметр: {row['diameter']} мм")
|
||||
|
||||
if row['stiffness_class']:
|
||||
parts.append(f"Класс жесткости: {row['stiffness_class']}")
|
||||
|
||||
Reference in new issue
Block a user