fix(api): fix err with filters

This commit is contained in:
Black_Raven committed 2026-04-23 17:27:41 +03:00
1 parent ba81b2cf32
commit 77ebb0e3a8
2 files changed
+67 -80

No files matched your search

+36 -62
View File
@@ -10,12 +10,17 @@ def get_products_with_filters(
filters: Dict[str, Any] = None,
db_name: str = 'pipe_store.db'
) -> Dict[str, Any]:
"""
Получение товаров с фильтрацией и пагинацией.
Все фильтры (включая диаметр, длину, цвет и т.д.) ищутся в таблице product_filters.
"""
print(f"Received filters: {filters}")
conn = sqlite3.connect(db_name)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
try:
# Рекурсивный CTE для получения всех подкатегорий
# 1. Получаем все ID категорий (включая подкатегории)
hierarchy_query = """
WITH RECURSIVE category_hierarchy AS (
SELECT id FROM categories WHERE id = ?
@@ -27,7 +32,7 @@ def get_products_with_filters(
"""
cursor.execute(hierarchy_query, (category_id,))
category_ids = [row['id'] for row in cursor.fetchall()]
if not category_ids:
return {"items": [], "total": 0, "page": page, "limit": limit, "total_pages": 0}
@@ -35,71 +40,43 @@ def get_products_with_filters(
base_where = f"WHERE p.category_id IN ({placeholders_cats})"
params = list(category_ids)
# Обработка фильтров
# 2. Обработка всех фильтров через product_filters
if filters:
column_map = {
'diameter': 'p.diameter',
'length': 'p.length',
'wall_thickness': 'p.wall_thickness',
'color': 'p.color',
'application_type': 'p.application_type',
'stiffness_class': 'p.stiffness_class'
}
def cast_value(col_name, val):
if col_name in ('diameter', 'length'):
try:
return int(val)
except:
return val
if col_name == 'wall_thickness':
try:
return float(val)
except:
return val
return val
for key, value in filters.items():
if not value:
continue
if key in column_map:
col = column_map[key]
if isinstance(value, list):
casted = [cast_value(key, v) for v in value]
v_ph = ','.join(['?' for _ in casted])
base_where += f" AND {col} IN ({v_ph})"
params.extend(casted)
else:
casted = cast_value(key, value)
base_where += f" AND {col} = ?"
params.append(casted)
# Подзапрос для проверки наличия фильтра у товара
if isinstance(value, list):
# Множественный фильтр (например, несколько диаметров)
placeholders = ','.join(['?' for _ in value])
base_where += f"""
AND p.id IN (
SELECT product_id FROM product_filters
WHERE filter_key = ? AND value IN ({placeholders})
)
"""
params.append(key)
params.extend([str(v) for v in value])
else:
# Фильтры из product_filters
if isinstance(value, list):
v_ph = ','.join(['?' for _ in value])
base_where += f"""
AND p.id IN (
SELECT product_id FROM product_filters
WHERE filter_key = ? AND value IN ({v_ph})
)"""
params.append(key)
params.extend([str(v) for v in value])
else:
base_where += f"""
AND p.id IN (
SELECT product_id FROM product_filters
WHERE filter_key = ? AND value = ?
)"""
params.append(key)
params.append(str(value))
# Одиночный фильтр
base_where += f"""
AND p.id IN (
SELECT product_id FROM product_filters
WHERE filter_key = ? AND value = ?
)
"""
params.append(key)
params.append(str(value))
# Подсчёт общего количества
# 3. Подсчёт общего количества
count_query = f"SELECT COUNT(*) as total FROM products p {base_where}"
cursor.execute(count_query, params)
print("SQL QUERY:", count_query)
print("PARAMS:", params)
total = cursor.fetchone()['total']
# Пагинация
# 4. Пагинация
offset = (page - 1) * limit
query = f"""
SELECT p.* FROM products p
@@ -110,6 +87,7 @@ def get_products_with_filters(
cursor.execute(query, params + [limit, offset])
rows = cursor.fetchall()
# 5. Формируем ответ
items = []
for row in rows:
items.append({
@@ -228,15 +206,12 @@ def get_product_images(product_id: int, main_image: Optional[str], conn: sqlite3
def check_stock(product_id: int, conn: sqlite3.Connection) -> bool:
"""Проверить наличие товара на складе"""
# Временная логика - все товары в наличии
# В будущем можно добавить таблицу stock
return True
def get_pack_amount(product_id: int, diameter: int = None, conn: sqlite3.Connection = None) -> str:
"""
Получить количество в упаковке
В реальном проекте должно быть в базе данных
"""
# Временная логика на основе диаметра
if diameter:
if diameter == 110:
return "6-10"
@@ -272,7 +247,7 @@ def generate_full_description(row: sqlite3.Row) -> str:
def get_product_list(page=1, limit=100, category_id=None):
"""
Получить список товаров с пагинацией.
Получить список товаров с пагинацией (без фильтров).
Возвращает список словарей с полями id, full_name, description.
"""
conn = None
@@ -281,7 +256,6 @@ def get_product_list(page=1, limit=100, category_id=None):
conn = sqlite3.connect('pipe_store.db')
conn.row_factory = sqlite3.Row
offset = (page - 1) * limit
rows = get_products_by_page(conn, page, limit, category_id)
products = []