From 8c07b1febcfad0fe415e3e507aba72987629cbe4 Mon Sep 17 00:00:00 2001 From: Kita Trofimov <144846094+NiTro005@users.noreply.github.com> Date: Sun, 26 Oct 2025 19:32:34 +0300 Subject: [PATCH] style(database): Changed logging --- db/connection.py | 36 ++- db/repositories/ai_prediction_repository.py | 37 ++- db/repositories/inventory_repository.py | 50 ++-- db/repositories/product_repository.py | 63 +++-- db/repositories/robot_repository.py | 62 +++-- db/repositories/user_repository.py | 277 +++++++++++++------- model/ai_prediction.py | 2 +- model/inventory.py | 2 +- model/product.py | 2 +- model/robot.py | 2 +- model/user.py | 2 +- 11 files changed, 359 insertions(+), 176 deletions(-) diff --git a/db/connection.py b/db/connection.py index 4d65310..c966677 100644 --- a/db/connection.py +++ b/db/connection.py @@ -1,6 +1,6 @@ -# db/connection.py import psycopg2 import os +import logging from contextlib import contextmanager from typing import Generator @@ -8,6 +8,8 @@ from utils.loadDotEnv import initializeENV initializeENV() +logger = logging.getLogger(__name__) + def PSQLConnect(): conn = psycopg2.connect(os.getenv('POSTDRESS_CONNECTION')) return conn @@ -22,30 +24,38 @@ def get_connection() -> Generator[psycopg2.extensions.connection, None, None]: conn = None try: conn = PSQLConnect() - print("Подключение к БД установлено") + logger.info("Подключение к БД установлено") yield conn except psycopg2.OperationalError as e: - print(f"Ошибка подключения к БД: {e}") + logger.error(f"Ошибка подключения к БД: {e}") + raise + except psycopg2.Error as e: + logger.error(f"Ошибка PostgreSQL: {e}") raise except Exception as e: - print(f"Неожиданная ошибка: {e}") + logger.error(f"Неожиданная ошибка при работе с БД: {e}") raise finally: if conn: - conn.close() - print("Соединение с БД закрыто") + try: + conn.close() + logger.info("Соединение с БД закрыто") + except Exception as e: + logger.warning(f"Ошибка при закрытии соединения: {e}") def test_connection() -> bool: try: with get_connection() as conn: cur = PSQLCursor(conn) - cur.execute("SELECT version();") - version = cur.fetchone() - print(f"Версия PostgreSQL: {version[0]}") - cur.close() - return True + try: + cur.execute("SELECT version();") + version = cur.fetchone() + logger.info(f"Версия PostgreSQL: {version[0]}") + return True + finally: + cur.close() + logger.debug("Курсор закрыт") except Exception as e: - print(f"Тест подключения к БД провален: {e}") + logger.error(f"Тест подключения к БД провален: {e}") return False - print(test_connection()) \ No newline at end of file diff --git a/db/repositories/ai_prediction_repository.py b/db/repositories/ai_prediction_repository.py index 3d3b430..afa25b0 100644 --- a/db/repositories/ai_prediction_repository.py +++ b/db/repositories/ai_prediction_repository.py @@ -1,8 +1,10 @@ from typing import List, Optional from datetime import datetime, date +import logging from db.connection import get_connection from model.ai_prediction import AIPrediction +logger = logging.getLogger(__name__) class AIPredictionsRepository: def get_all(self) -> List[AIPrediction]: @@ -10,7 +12,7 @@ class AIPredictionsRepository: with get_connection() as conn: with conn.cursor() as cur: cur.execute("SELECT * FROM ai_predictions ORDER BY prediction_date DESC, product_id") - return [ + predictions = [ AIPrediction( id=row[0], product_id=row[1], @@ -21,8 +23,10 @@ class AIPredictionsRepository: created_at=row[6] ) for row in cur.fetchall() ] + logger.info(f"Получено {len(predictions)} прогнозов") + return predictions except Exception as e: - print(f"Ошибка получения прогнозов: {e}") + logger.error(f"Ошибка получения прогнозов: {e}") return [] def get_by_id(self, prediction_id: int) -> Optional[AIPrediction]: @@ -31,9 +35,13 @@ class AIPredictionsRepository: with conn.cursor() as cur: cur.execute("SELECT * FROM ai_predictions WHERE id = %s", (prediction_id,)) row = cur.fetchone() - return AIPrediction(*row) if row else None + if row: + logger.info(f"Прогноз {prediction_id} найден") + return AIPrediction(*row) + logger.warning(f"Прогноз {prediction_id} не найден") + return None except Exception as e: - print(f"Ошибка получения прогноза {prediction_id}: {e}") + logger.error(f"Ошибка получения прогноза {prediction_id}: {e}") return None def get_by_product(self, product_id: str, limit: int = 10) -> List[AIPrediction]: @@ -46,9 +54,11 @@ class AIPredictionsRepository: ORDER BY prediction_date DESC LIMIT %s """, (product_id, limit)) - return [AIPrediction(*row) for row in cur.fetchall()] + predictions = [AIPrediction(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(predictions)} прогнозов для товара {product_id}") + return predictions except Exception as e: - print(f"Ошибка получения прогноза по товару {product_id}: {e}") + logger.error(f"Ошибка получения прогноза по товару {product_id}: {e}") return [] def get_latest_predictions(self) -> List[AIPrediction]: @@ -60,9 +70,11 @@ class AIPredictionsRepository: FROM ai_predictions ORDER BY product_id, prediction_date DESC """) - return [AIPrediction(*row) for row in cur.fetchall()] + predictions = [AIPrediction(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(predictions)} последних прогнозов по товарам") + return predictions except Exception as e: - print(f"Ошибка получения последних прогнозов по товарам: {e}") + logger.error(f"Ошибка получения последних прогнозов по товарам: {e}") return [] def create_prediction(self, product_id: str, prediction_date: date, @@ -80,12 +92,12 @@ class AIPredictionsRepository: prediction_id = cur.fetchone()[0] conn.commit() + logger.info(f"Создан новый прогноз ID: {prediction_id} для товара {product_id}") return prediction_id except Exception as e: - print(f"Ошибка создания прогноза: {e}") + logger.error(f"Ошибка создания прогноза: {e}") return None - def delete_old_predictions(self, older_than_days: int = 90) -> int: try: with get_connection() as conn: @@ -96,7 +108,8 @@ class AIPredictionsRepository: """, (older_than_days,)) deleted_count = cur.rowcount conn.commit() + logger.info(f"Удалено {deleted_count} старых прогнозов старше {older_than_days} дней") return deleted_count except Exception as e: - print(f"Ошибка удаления старых прогнозов: {e}") - return 0 \ No newline at end of file + logger.error(f"Ошибка удаления старых прогнозов: {e}") + return 0 diff --git a/db/repositories/inventory_repository.py b/db/repositories/inventory_repository.py index 4ba33fd..365f48f 100644 --- a/db/repositories/inventory_repository.py +++ b/db/repositories/inventory_repository.py @@ -1,10 +1,11 @@ # db/repositories/inventory_repository.py from typing import List, Optional, Tuple from datetime import datetime +import logging from db.connection import get_connection from model.inventory import InventoryRecord - +logger = logging.getLogger(__name__) class InventoryRepository: def get_all(self) -> List[InventoryRecord]: @@ -12,7 +13,7 @@ class InventoryRepository: with get_connection() as conn: with conn.cursor() as cur: cur.execute("SELECT * FROM inventory_history ORDER BY scanned_at DESC") - return [ + records = [ InventoryRecord( id=row[0], robot_id=row[1], @@ -26,8 +27,10 @@ class InventoryRepository: created_at=row[9] ) for row in cur.fetchall() ] + logger.info(f"Получено {len(records)} записей инвентаризации") + return records except Exception as e: - print(f"Ошибка получения истории инвентаризации: {e}") + logger.error(f"Ошибка получения истории инвентаризации: {e}") return [] def get_by_id(self, record_id: int) -> Optional[InventoryRecord]: @@ -36,9 +39,13 @@ class InventoryRepository: with conn.cursor() as cur: cur.execute("SELECT * FROM inventory_history WHERE id = %s", (record_id,)) row = cur.fetchone() - return InventoryRecord(*row) if row else None + if row: + logger.info(f"Запись инвентаризации {record_id} найдена") + return InventoryRecord(*row) + logger.warning(f"Запись инвентаризации {record_id} не найдена") + return None except Exception as e: - print(f"Ошибка получения записи инвентаризации {record_id}: {e}") + logger.error(f"Ошибка получения записи инвентаризации {record_id}: {e}") return None def create_record(self, robot_id: str, product_id: str, quantity: int, zone: str, @@ -55,9 +62,10 @@ class InventoryRepository: record_id = cur.fetchone()[0] conn.commit() + logger.info(f"Создана новая запись инвентаризации ID: {record_id}") return record_id except Exception as e: - print(f"Ошибка создания записи инвентаризации: {e}") + logger.error(f"Ошибка создания записи инвентаризации: {e}") return None def get_latest_inventory(self) -> List[InventoryRecord]: @@ -69,9 +77,11 @@ class InventoryRepository: FROM inventory_history ORDER BY product_id, scanned_at DESC """) - return [InventoryRecord(*row) for row in cur.fetchall()] + records = [InventoryRecord(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(records)} последних записей инвентаризации по товарам") + return records except Exception as e: - print(f"Ошибка получения последней записи инвентаризации по каждому товару: {e}") + logger.error(f"Ошибка получения последней записи инвентаризации по каждому товару: {e}") return [] def get_records_by_product(self, product_id: str, limit: int = 100) -> List[InventoryRecord]: @@ -84,9 +94,11 @@ class InventoryRepository: ORDER BY scanned_at DESC LIMIT %s """, (product_id, limit)) - return [InventoryRecord(*row) for row in cur.fetchall()] + records = [InventoryRecord(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(records)} записей инвентаризации для товара {product_id}") + return records except Exception as e: - print(f"Ошибка получения записи инвентаризации по продукту {product_id}: {e}") + logger.error(f"Ошибка получения записи инвентаризации по продукту {product_id}: {e}") return [] def get_records_by_robot(self, robot_id: str, limit: int = 100) -> List[InventoryRecord]: @@ -99,9 +111,11 @@ class InventoryRepository: ORDER BY scanned_at DESC LIMIT %s """, (robot_id, limit)) - return [InventoryRecord(*row) for row in cur.fetchall()] + records = [InventoryRecord(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(records)} записей инвентаризации для робота {robot_id}") + return records except Exception as e: - print(f"Ошибка получения записи инвентаризации по роботу {robot_id}: {e}") + logger.error(f"Ошибка получения записи инвентаризации по роботу {robot_id}: {e}") return [] def get_records_by_zone(self, zone: str, limit: int = 100) -> List[InventoryRecord]: @@ -114,9 +128,11 @@ class InventoryRepository: ORDER BY scanned_at DESC LIMIT %s """, (zone, limit)) - return [InventoryRecord(*row) for row in cur.fetchall()] + records = [InventoryRecord(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(records)} записей инвентаризации для зоны {zone}") + return records except Exception as e: - print(f"Ошибка получения записи инвентаризации по зоне {zone}: {e}") + logger.error(f"Ошибка получения записи инвентаризации по зоне {zone}: {e}") return [] def get_critical_items(self, hours: int = 24) -> List[InventoryRecord]: @@ -129,7 +145,9 @@ class InventoryRepository: AND scanned_at >= NOW() - INTERVAL '%s hours' ORDER BY scanned_at DESC """, (hours,)) - return [InventoryRecord(*row) for row in cur.fetchall()] + records = [InventoryRecord(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(records)} критических товаров за последние {hours} часов") + return records except Exception as e: - print(f"Ошибка получения товаров с критическим статусом: {e}") + logger.error(f"Ошибка получения товаров с критическим статусом: {e}") return [] diff --git a/db/repositories/product_repository.py b/db/repositories/product_repository.py index 8d55ce2..37154c6 100644 --- a/db/repositories/product_repository.py +++ b/db/repositories/product_repository.py @@ -1,8 +1,9 @@ -# db/repositories/product_repository.py from typing import List, Optional +import logging from db.connection import get_connection from model.product import Product +logger = logging.getLogger(__name__) class ProductRepository: def get_all(self) -> List[Product]: @@ -10,7 +11,7 @@ class ProductRepository: with get_connection() as conn: with conn.cursor() as cur: cur.execute("SELECT * FROM products ORDER BY id") - return [ + products = [ Product( id=row[0], name=row[1], @@ -19,8 +20,10 @@ class ProductRepository: optimal_stock=row[4] ) for row in cur.fetchall() ] + logger.info(f"Получено {len(products)} товаров") + return products except Exception as e: - print(f"Ошибка получения продуктов: {e}") + logger.error(f"Ошибка получения продуктов: {e}") return [] def get_by_id(self, product_id: str) -> Optional[Product]: @@ -29,9 +32,13 @@ class ProductRepository: with conn.cursor() as cur: cur.execute("SELECT * FROM products WHERE id = %s", (product_id,)) row = cur.fetchone() - return Product(*row) if row else None + if row: + logger.info(f"Товар {product_id} найден") + return Product(*row) + logger.warning(f"Товар {product_id} не найден") + return None except Exception as e: - print(f"Ошибка получения товара {product_id}: {e}") + logger.error(f"Ошибка получения товара {product_id}: {e}") return None def get_by_category(self, category: str) -> List[Product]: @@ -39,9 +46,11 @@ class ProductRepository: with get_connection() as conn: with conn.cursor() as cur: cur.execute("SELECT * FROM products WHERE category = %s ORDER BY name", (category,)) - return [Product(*row) for row in cur.fetchall()] + products = [Product(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(products)} товаров категории {category}") + return products except Exception as e: - print(f"Ошибка получения товаров по категории {category}: {e}") + logger.error(f"Ошибка получения товаров по категории {category}: {e}") return [] def create_product(self, product_id: str, name: str, category: str, @@ -54,9 +63,14 @@ class ProductRepository: VALUES (%s, %s, %s, %s, %s) """, (product_id, name, category, min_stock, optimal_stock)) conn.commit() - return cur.rowcount > 0 + success = cur.rowcount > 0 + if success: + logger.info(f"Создан новый товар {product_id}: {name}") + else: + logger.warning(f"Не удалось создать товар {product_id}") + return success except Exception as e: - print(f"Ошибка создания товара {product_id}: {e}") + logger.error(f"Ошибка создания товара {product_id}: {e}") return False def update_product(self, product_id: str, name: str = None, category: str = None, @@ -84,6 +98,7 @@ class ProductRepository: params.append(optimal_stock) if not updates: + logger.warning(f"Нет данных для обновления товара {product_id}") return False params.append(product_id) @@ -91,9 +106,14 @@ class ProductRepository: cur.execute(query, params) conn.commit() - return cur.rowcount > 0 + success = cur.rowcount > 0 + if success: + logger.info(f"Товар {product_id} успешно обновлен") + else: + logger.warning(f"Товар {product_id} не найден для обновления") + return success except Exception as e: - print(f"Ошибка обновления товара {product_id}: {e}") + logger.error(f"Ошибка обновления товара {product_id}: {e}") return False def delete_product(self, product_id: str) -> bool: @@ -102,9 +122,14 @@ class ProductRepository: with conn.cursor() as cur: cur.execute("DELETE FROM products WHERE id = %s", (product_id,)) conn.commit() - return cur.rowcount > 0 + success = cur.rowcount > 0 + if success: + logger.info(f"Товар {product_id} удален") + else: + logger.warning(f"Товар {product_id} не найден для удаления") + return success except Exception as e: - print(f"Ошибка удаления товара {product_id}: {e}") + logger.error(f"Ошибка удаления товара {product_id}: {e}") return False def search_products(self, search_term: str) -> List[Product]: @@ -116,9 +141,11 @@ class ProductRepository: WHERE name ILIKE %s OR id ILIKE %s ORDER BY name """, (f'%{search_term}%', f'%{search_term}%')) - return [Product(*row) for row in cur.fetchall()] + products = [Product(*row) for row in cur.fetchall()] + logger.info(f"Найдено {len(products)} товаров по запросу '{search_term}'") + return products except Exception as e: - print(f"Ошибка поиска товров по названию '{search_term}': {e}") + logger.error(f"Ошибка поиска товаров по названию '{search_term}': {e}") return [] def get_low_stock_products(self) -> List[Product]: @@ -133,7 +160,9 @@ class ProductRepository: AND ih.scanned_at >= NOW() - INTERVAL '1 day' ORDER BY p.name """) - return [Product(*row) for row in cur.fetchall()] + products = [Product(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(products)} товаров с низким запасом") + return products except Exception as e: - print(f"Ошибка получения товаров с низким запасом: {e}") + logger.error(f"Ошибка получения товаров с низким запасом: {e}") return [] \ No newline at end of file diff --git a/db/repositories/robot_repository.py b/db/repositories/robot_repository.py index a259e34..c460562 100644 --- a/db/repositories/robot_repository.py +++ b/db/repositories/robot_repository.py @@ -1,15 +1,18 @@ # db/repositories/robot_repository.py from typing import List, Optional +import logging from db.connection import get_connection from model.robot import Robot +logger = logging.getLogger(__name__) + class RobotRepository: def get_all(self) -> List[Robot]: try: with get_connection() as conn: with conn.cursor() as cur: cur.execute("SELECT * FROM robots ORDER BY id") - return [ + robots = [ Robot( id=row[0], status=row[1], @@ -20,8 +23,10 @@ class RobotRepository: current_shelf=row[6] ) for row in cur.fetchall() ] + logger.info(f"Получено {len(robots)} роботов") + return robots except Exception as e: - print(f"Ошика получения всех роботов: {e}") + logger.error(f"Ошибка получения всех роботов: {e}") return [] def get_by_id(self, robot_id: str) -> Optional[Robot]: @@ -30,9 +35,13 @@ class RobotRepository: with conn.cursor() as cur: cur.execute("SELECT * FROM robots WHERE id = %s", (robot_id,)) row = cur.fetchone() - return Robot(*row) if row else None + if row: + logger.info(f"Робот {robot_id} найден") + return Robot(*row) + logger.warning(f"Робот {robot_id} не найден") + return None except Exception as e: - print(f"Ошибка получения роботов {robot_id}: {e}") + logger.error(f"Ошибка получения робота {robot_id}: {e}") return None def update_robot(self, robot_id: str, status: str = None, battery_level: int = None, @@ -68,9 +77,14 @@ class RobotRepository: cur.execute(query, params) conn.commit() - return cur.rowcount > 0 + success = cur.rowcount > 0 + if success: + logger.info(f"Робот {robot_id} успешно обновлен") + else: + logger.warning(f"Робот {robot_id} не найден для обновления") + return success except Exception as e: - print(f"Ошибка обновления робота {robot_id}: {e}") + logger.error(f"Ошибка обновления робота {robot_id}: {e}") return False def get_robots_by_status(self, status: str) -> List[Robot]: @@ -78,9 +92,11 @@ class RobotRepository: with get_connection() as conn: with conn.cursor() as cur: cur.execute("SELECT * FROM robots WHERE status = %s ORDER BY id", (status,)) - return [Robot(*row) for row in cur.fetchall()] + robots = [Robot(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(robots)} роботов со статусом {status}") + return robots except Exception as e: - print(f"Ошибка получения роботов по статусу {status}: {e}") + logger.error(f"Ошибка получения роботов по статусу {status}: {e}") return [] def get_low_battery_robots(self, threshold: int = 20) -> List[Robot]: @@ -92,9 +108,11 @@ class RobotRepository: WHERE battery_level < %s AND status = 'active' ORDER BY battery_level ASC """, (threshold,)) - return [Robot(*row) for row in cur.fetchall()] + robots = [Robot(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(robots)} роботов с низким зарядом (<{threshold}%)") + return robots except Exception as e: - print(f"Ошибка получения роботов с низким зарядом: {e}") + logger.error(f"Ошибка получения роботов с низким зарядом: {e}") return [] def get_robots_in_zone(self, zone: str) -> List[Robot]: @@ -102,9 +120,11 @@ class RobotRepository: with get_connection() as conn: with conn.cursor() as cur: cur.execute("SELECT * FROM robots WHERE current_zone = %s ORDER BY id", (zone,)) - return [Robot(*row) for row in cur.fetchall()] + robots = [Robot(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(robots)} роботов в зоне {zone}") + return robots except Exception as e: - print(f"Ошибка получения роботов в зоне {zone}: {e}") + logger.error(f"Ошибка получения роботов в зоне {zone}: {e}") return [] def create_robot(self, robot_id: str, status: str = 'active', battery_level: int = 100) -> bool: @@ -116,9 +136,14 @@ class RobotRepository: VALUES (%s, %s, %s, CURRENT_TIMESTAMP) """, (robot_id, status, battery_level)) conn.commit() - return cur.rowcount > 0 + success = cur.rowcount > 0 + if success: + logger.info(f"Создан новый робот {robot_id}") + else: + logger.warning(f"Не удалось создать робота {robot_id}") + return success except Exception as e: - print(f"Ошибка создания робота {robot_id}: {e}") + logger.error(f"Ошибка создания робота {robot_id}: {e}") return False def delete_robot(self, robot_id: str) -> bool: @@ -127,7 +152,12 @@ class RobotRepository: with conn.cursor() as cur: cur.execute("DELETE FROM robots WHERE id = %s", (robot_id,)) conn.commit() - return cur.rowcount > 0 + success = cur.rowcount > 0 + if success: + logger.info(f"Робот {robot_id} удален") + else: + logger.warning(f"Робот {robot_id} не найден для удаления") + return success except Exception as e: - print(f"Ошибка удаления робота {robot_id}: {e}") + logger.error(f"Ошибка удаления робота {robot_id}: {e}") return False \ No newline at end of file diff --git a/db/repositories/user_repository.py b/db/repositories/user_repository.py index 7b1d979..31f527e 100644 --- a/db/repositories/user_repository.py +++ b/db/repositories/user_repository.py @@ -1,130 +1,213 @@ from typing import List, Optional +import logging from model.user import User from db.connection import get_connection +logger = logging.getLogger(__name__) + class UserRepository: def get_all(self) -> List[User]: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute("SELECT * FROM users ORDER BY id") - return [ - User( - id=row[0], - email=row[1], - password_hash=row[2], - name=row[3], - role=row[4], - created_at=row[5] - ) for row in cur.fetchall() - ] + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute("SELECT * FROM users ORDER BY id") + users = [ + User( + id=row[0], + email=row[1], + password_hash=row[2], + name=row[3], + role=row[4], + created_at=row[5] + ) for row in cur.fetchall() + ] + logger.info(f"Получено {len(users)} пользователей") + return users + except Exception as e: + logger.error(f"Ошибка получения пользователей: {e}") + return [] def get_by_id(self, user_id: int) -> Optional[User]: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute("SELECT * FROM users WHERE id = %s", (user_id,)) - row = cur.fetchone() - if row: - return User(*row) - return None + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute("SELECT * FROM users WHERE id = %s", (user_id,)) + row = cur.fetchone() + if row: + logger.info(f"Пользователь {user_id} найден") + return User(*row) + logger.warning(f"Пользователь {user_id} не найден") + return None + except Exception as e: + logger.error(f"Ошибка получения пользователя {user_id}: {e}") + return None def get_by_email(self, email: str) -> Optional[User]: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute("SELECT * FROM users WHERE email = %s", (email,)) - row = cur.fetchone() - if row: - return User(*row) - return None + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute("SELECT * FROM users WHERE email = %s", (email,)) + row = cur.fetchone() + if row: + logger.info(f"Пользователь с email {email} найден") + return User(*row) + logger.warning(f"Пользователь с email {email} не найден") + return None + except Exception as e: + logger.error(f"Ошибка получения пользователя по email {email}: {e}") + return None def create_user(self, email: str, password_hash: str, name: str, role: str) -> Optional[User]: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute(""" - INSERT INTO users (email, password_hash, name, role) - VALUES (%s, %s, %s, %s) - RETURNING id, email, password_hash, name, role, created_at - """, (email, password_hash, name, role)) + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute(""" + INSERT INTO users (email, password_hash, name, role) + VALUES (%s, %s, %s, %s) + RETURNING id, email, password_hash, name, role, created_at + """, (email, password_hash, name, role)) - row = cur.fetchone() - conn.commit() + row = cur.fetchone() + conn.commit() - if row: - return User(*row) - return None + if row: + logger.info(f"Создан новый пользователь {email} с ID {row[0]}") + return User(*row) + logger.warning(f"Не удалось создать пользователя {email}") + return None + except Exception as e: + logger.error(f"Ошибка создания пользователя {email}: {e}") + return None def update_user(self, user_id: int, name: str = None, role: str = None) -> bool: - with get_connection() as conn: - with conn.cursor() as cur: - updates = [] - params = [] + try: + with get_connection() as conn: + with conn.cursor() as cur: + updates = [] + params = [] - if name is not None: - updates.append("name = %s") - params.append(name) + if name is not None: + updates.append("name = %s") + params.append(name) - if role is not None: - updates.append("role = %s") - params.append(role) + if role is not None: + updates.append("role = %s") + params.append(role) - if not updates: - return False + if not updates: + logger.warning(f"Нет данных для обновления пользователя {user_id}") + return False - params.append(user_id) - query = f"UPDATE users SET {', '.join(updates)} WHERE id = %s" + params.append(user_id) + query = f"UPDATE users SET {', '.join(updates)} WHERE id = %s" - cur.execute(query, params) - conn.commit() - return cur.rowcount > 0 + cur.execute(query, params) + conn.commit() + success = cur.rowcount > 0 + if success: + logger.info(f"Пользователь {user_id} успешно обновлен") + else: + logger.warning(f"Пользователь {user_id} не найден для обновления") + return success + except Exception as e: + logger.error(f"Ошибка обновления пользователя {user_id}: {e}") + return False def delete_user(self, user_id: int) -> bool: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute("DELETE FROM users WHERE id = %s", (user_id,)) - conn.commit() - return cur.rowcount > 0 + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute("DELETE FROM users WHERE id = %s", (user_id,)) + conn.commit() + success = cur.rowcount > 0 + if success: + logger.info(f"Пользователь {user_id} удален") + else: + logger.warning(f"Пользователь {user_id} не найден для удаления") + return success + except Exception as e: + logger.error(f"Ошибка удаления пользователя {user_id}: {e}") + return False def get_users_by_role(self, role: str) -> List[User]: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute("SELECT * FROM users WHERE role = %s ORDER BY name", (role,)) - return [ - User(*row) for row in cur.fetchall() - ] + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute("SELECT * FROM users WHERE role = %s ORDER BY name", (role,)) + users = [User(*row) for row in cur.fetchall()] + logger.info(f"Получено {len(users)} пользователей с ролью {role}") + return users + except Exception as e: + logger.error(f"Ошибка получения пользователей по роли {role}: {e}") + return [] def change_password(self, user_id: int, new_password_hash: str) -> bool: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute(""" - UPDATE users - SET password_hash = %s - WHERE id = %s - """, (new_password_hash, user_id)) - conn.commit() - return cur.rowcount > 0 + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute(""" + UPDATE users + SET password_hash = %s + WHERE id = %s + """, (new_password_hash, user_id)) + conn.commit() + success = cur.rowcount > 0 + if success: + logger.info(f"Пароль пользователя {user_id} изменен") + else: + logger.warning(f"Пользователь {user_id} не найден для смены пароля") + return success + except Exception as e: + logger.error(f"Ошибка смены пароля пользователя {user_id}: {e}") + return False def authenticate_user(self, email: str, password_hash: str) -> Optional[User]: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute(""" - SELECT * FROM users - WHERE email = %s AND password_hash = %s - """, (email, password_hash)) - row = cur.fetchone() - if row: - return User(*row) - return None + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute(""" + SELECT * FROM users + WHERE email = %s AND password_hash = %s + """, (email, password_hash)) + row = cur.fetchone() + if row: + logger.info(f"Успешная аутентификация пользователя {email}") + return User(*row) + logger.warning(f"Неудачная аутентификация пользователя {email}") + return None + except Exception as e: + logger.error(f"Ошибка аутентификации пользователя {email}: {e}") + return None def is_valid_authenticate(self, email: str, password_hash: str) -> bool: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute(""" - SELECT 1 FROM users - WHERE email = %s AND password_hash = %s - """, (email, password_hash)) - return cur.fetchone() is not None + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute(""" + SELECT 1 FROM users + WHERE email = %s AND password_hash = %s + """, (email, password_hash)) + is_valid = cur.fetchone() is not None + if is_valid: + logger.info(f"Валидные учетные данные для пользователя {email}") + else: + logger.warning(f"Невалидные учетные данные для пользователя {email}") + return is_valid + except Exception as e: + logger.error(f"Ошибка проверки учетных данных пользователя {email}: {e}") + return False def user_exists(self, email: str) -> bool: - with get_connection() as conn: - with conn.cursor() as cur: - cur.execute("SELECT 1 FROM users WHERE email = %s", (email,)) - return cur.fetchone() is not None \ No newline at end of file + try: + with get_connection() as conn: + with conn.cursor() as cur: + cur.execute("SELECT 1 FROM users WHERE email = %s", (email,)) + exists = cur.fetchone() is not None + if exists: + logger.info(f"Пользователь с email {email} существует") + else: + logger.info(f"Пользователь с email {email} не существует") + return exists + except Exception as e: + logger.error(f"Ошибка проверки существования пользователя {email}: {e}") + return False diff --git a/model/ai_prediction.py b/model/ai_prediction.py index 1685105..acf9978 100644 --- a/model/ai_prediction.py +++ b/model/ai_prediction.py @@ -9,4 +9,4 @@ class AIPrediction: days_until_stockout: int recommended_order: int confidence_score: float - created_at: datetime \ No newline at end of file + created_at: datetime diff --git a/model/inventory.py b/model/inventory.py index dc7820d..9f42e08 100644 --- a/model/inventory.py +++ b/model/inventory.py @@ -11,4 +11,4 @@ class InventoryRecord: shelf_number: int status: str scanned_at: datetime - created_at: datetime \ No newline at end of file + created_at: datetime diff --git a/model/product.py b/model/product.py index 8afdd95..4034b37 100644 --- a/model/product.py +++ b/model/product.py @@ -6,4 +6,4 @@ class Product: name: str category: str min_stock: int - optimal_stock: int \ No newline at end of file + optimal_stock: int diff --git a/model/robot.py b/model/robot.py index fd3847e..2e68e18 100644 --- a/model/robot.py +++ b/model/robot.py @@ -10,4 +10,4 @@ class Robot: last_update: datetime current_zone: Optional[str] = None current_row: Optional[int] = None - current_shelf: Optional[int] = None \ No newline at end of file + current_shelf: Optional[int] = None diff --git a/model/user.py b/model/user.py index 9eda604..e9ea4da 100644 --- a/model/user.py +++ b/model/user.py @@ -9,4 +9,4 @@ class User: password_hash: str name: str role: str - created_at: datetime \ No newline at end of file + created_at: datetime