242 lines
9.1 KiB
Python
242 lines
9.1 KiB
Python
import re
|
||
import sqlite3
|
||
from loguru import logger as log
|
||
from utils.slugify import slugify
|
||
|
||
def add_category(conn, name, description=None, parent_id=None, image_path=None):
|
||
cursor = conn.cursor()
|
||
|
||
try:
|
||
cursor.execute('''
|
||
INSERT OR IGNORE INTO categories (name, description, parent_id, image_path)
|
||
VALUES (?, ?, ?, ?)
|
||
''', (name, description, parent_id, image_path))
|
||
|
||
cursor.execute('SELECT id FROM categories WHERE name = ?', (name,))
|
||
result = cursor.fetchone()
|
||
category_id = result[0] if result else None
|
||
|
||
return category_id
|
||
except sqlite3.Error as e:
|
||
log.error(f"Ошибка при добавлении категории: {e}")
|
||
return None
|
||
|
||
def add_filter(conn, name, filter_key, filter_type='single'):
|
||
cursor = conn.cursor()
|
||
|
||
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))
|
||
wall_thickness = float(size_match.group(2))
|
||
length = int(size_match.group(3))
|
||
else:
|
||
diameter = wall_thickness = length = None
|
||
|
||
# Для фитингов может не быть длины
|
||
if not length and diameter:
|
||
# Проверяем на отводы
|
||
angle_match = re.search(r'(\d+)°', product_text)
|
||
if angle_match:
|
||
length = None
|
||
else:
|
||
length = 0
|
||
|
||
return {
|
||
'name': product_text,
|
||
'diameter': diameter,
|
||
'wall_thickness': wall_thickness,
|
||
'length': length,
|
||
'color': color,
|
||
'application_type': application_type,
|
||
'stiffness_class': stiffness_class
|
||
}
|
||
|
||
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, slug=None, artikul=None):
|
||
"""
|
||
Добавление товара с возможностью явного указания параметров
|
||
Если параметры не указаны, они парсятся из product_text
|
||
"""
|
||
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)
|
||
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']
|
||
|
||
# Формируем описание
|
||
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)
|
||
|
||
if fitting_type:
|
||
slug_source = product_text
|
||
else:
|
||
slug_parts = [product_text]
|
||
if stiffness_class:
|
||
slug_parts.append(stiffness_class)
|
||
if diameter:
|
||
slug_parts.append(f"d{diameter}")
|
||
if wall_thickness:
|
||
slug_parts.append(f"stenka{int(wall_thickness)}")
|
||
if length and length > 0:
|
||
slug_parts.append(f"l{length}")
|
||
slug_source = " ".join(slug_parts)
|
||
slug_value = slug or slugify(slug_source)
|
||
if artikul:
|
||
slug_value = f"{slug_value}-{artikul.lower()}"
|
||
|
||
try:
|
||
cursor.execute('''
|
||
INSERT INTO products (
|
||
name, description, category_id,
|
||
diameter, wall_thickness, length, color,
|
||
application_type, stiffness_class, image_path, slug
|
||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||
''', (
|
||
product_text,
|
||
description,
|
||
category_id,
|
||
diameter,
|
||
wall_thickness,
|
||
length if length and length > 0 else None,
|
||
color,
|
||
application_type,
|
||
stiffness_class,
|
||
image_path,
|
||
slug_value
|
||
))
|
||
|
||
product_id = cursor.lastrowid
|
||
|
||
# Добавляем фильтры для товара
|
||
filters_to_add = []
|
||
|
||
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:
|
||
cursor.execute('''
|
||
INSERT OR IGNORE INTO product_filters (product_id, filter_key, value)
|
||
VALUES (?, ?, ?)
|
||
''', (product_id, filter_key, value))
|
||
|
||
return product_id
|
||
|
||
except sqlite3.Error as e:
|
||
log.error(f"Ошибка при добавлении товара: {e}")
|
||
return None
|
||
|
||
def get_categories_by_page(conn, page_number=1, items_per_page=9):
|
||
"""Получить категории для определенной страницы"""
|
||
cursor = conn.cursor()
|
||
offset = (page_number - 1) * items_per_page
|
||
|
||
cursor.execute('''
|
||
SELECT * FROM categories
|
||
ORDER BY id
|
||
LIMIT ? OFFSET ?
|
||
''', (items_per_page, offset))
|
||
|
||
return cursor.fetchall()
|
||
|
||
def get_products_by_page(conn, page_number=1, items_per_page=9, category_id=None):
|
||
"""Получить товары для определенной страницы"""
|
||
cursor = conn.cursor()
|
||
offset = (page_number - 1) * items_per_page
|
||
|
||
if category_id:
|
||
cursor.execute('''
|
||
SELECT * FROM products
|
||
WHERE category_id = ?
|
||
ORDER BY id
|
||
LIMIT ? OFFSET ?
|
||
''', (category_id, items_per_page, offset))
|
||
else:
|
||
cursor.execute('''
|
||
SELECT * FROM products
|
||
ORDER BY id
|
||
LIMIT ? OFFSET ?
|
||
''', (items_per_page, offset))
|
||
|
||
return cursor.fetchall()
|
||
|
||
def get_total_categories_pages(conn, items_per_page=9):
|
||
"""Получить общее количество страниц категорий"""
|
||
cursor = conn.cursor()
|
||
cursor.execute('SELECT COUNT(*) FROM categories')
|
||
total_categories = cursor.fetchone()[0]
|
||
return (total_categories + items_per_page - 1) // items_per_page
|
||
|
||
def get_total_products_pages(conn, items_per_page=9, category_id=None):
|
||
"""Получить общее количество страниц товаров"""
|
||
cursor = conn.cursor()
|
||
|
||
if category_id:
|
||
cursor.execute('SELECT COUNT(*) FROM products WHERE category_id = ?', (category_id,))
|
||
else:
|
||
cursor.execute('SELECT COUNT(*) FROM products')
|
||
|
||
total_products = cursor.fetchone()[0]
|
||
return (total_products + items_per_page - 1) // items_per_page
|