fix(db): Added db to actual price
This commit is contained in:
1 parent
39cc73d71a
commit
beb94d2b0d
4 files changed
+356
-126
No files matched your search
+89
-23
@@ -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()
|
||||||
|
|
||||||
|
try:
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
INSERT OR IGNORE INTO filters (name, filter_key, filter_type)
|
INSERT OR IGNORE INTO filters (name, filter_key, filter_type)
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
''', (name, filter_key, filter_type))
|
''', (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()
|
||||||
|
|
||||||
|
# Если параметры не указаны явно, парсим из текста
|
||||||
|
if any(p is None for p in [diameter, wall_thickness, length, color, application_type, stiffness_class]):
|
||||||
product_data = parse_product_data(product_text)
|
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:
|
||||||
|
|||||||
+140
-32
@@ -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 = [
|
|
||||||
# Внутренние трубы
|
|
||||||
{"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"},
|
|
||||||
|
|
||||||
# Наружные трубы
|
# 1. Внутренние трубы (серые)
|
||||||
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х500", "image": "/images/products/external_110_sn4_500.jpg"},
|
internal_pipes = [
|
||||||
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х1000", "image": "/images/products/external_110_sn4_1000.jpg"},
|
("110х2,2х500", 110, 2.2, 500, "серый", "внутренняя", None),
|
||||||
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х2000", "image": "/images/products/external_110_sn4_2000.jpg"},
|
("110х2,2х1000", 110, 2.2, 1000, "серый", "внутренняя", None),
|
||||||
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х3000", "image": "/images/products/external_110_sn4_3000.jpg"},
|
("110х2,2х1500", 110, 2.2, 1500, "серый", "внутренняя", None),
|
||||||
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN4 110х3,2х4000", "image": "/images/products/external_110_sn4_4000.jpg"},
|
("110х2,2х2000", 110, 2.2, 2000, "серый", "внутренняя", None),
|
||||||
{"text": "Труба ПВХ для НАРУЖНОЙ канализации (цвет оранжево-коричневый), с внутренней структурной стенкой, класс жесткости SN2 160х3,6х1000", "image": "/images/products/external_160_sn2_1000.jpg"},
|
("110х2,2х3000", 110, 2.2, 3000, "серый", "внутренняя", None),
|
||||||
{"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"]
|
|
||||||
image_path = product_info["image"]
|
|
||||||
|
|
||||||
if "ВНУТРЕННЕЙ" in product_text:
|
for size, diameter, thickness, length, color, app_type, stiffness in internal_pipes:
|
||||||
category_id = internal_category_id
|
full_name = f"Труба ПВХ для ВНУТРЕННЕЙ канализации (цвет {color}), со сплошной стенкой толщиной {thickness} мм {diameter}x{thickness}x{length}"
|
||||||
else:
|
image_path = f"/images/products/internal_{diameter}_{length}.jpg"
|
||||||
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:
|
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} товаров в базу данных!")
|
||||||
@@ -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()
|
||||||
@@ -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']}")
|
||||||
|
|||||||
Reference in new issue
Block a user