diff --git a/test_tabel_check.py b/test_tabel_check.py index 3a472d9..4e03e19 100644 --- a/test_tabel_check.py +++ b/test_tabel_check.py @@ -3,27 +3,22 @@ Проверка подключения к SQL Server и загрузки данных табеля за последние 5 месяцев. -Запуск внутри Docker-контейнера проекта: - docker exec -it trueconf-bot python3 test_tabel_check.py - -ИЛИ напрямую на production (если есть доступ к серверу): +Запуск: cd /opt/trueconf_bot python3 test_tabel_check.py - -Требования: pymssql, passwork (опционально) """ import sys import os import calendar -from datetime import datetime, timedelta +from datetime import datetime # ============================================================ -# 1. Загрузка .env из /opt/trueconf_bot/config/.env +# 1. Загрузка .env # ============================================================ -ENV_PATH = "/opt/trueconf_bot/config/.env" +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +ENV_PATH = os.path.join(BASE_DIR, "config", ".env") def load_env(filepath): - """Загружает переменные из .env файла.""" try: with open(filepath, "r", encoding="utf-8") as f: for line in f: @@ -33,30 +28,94 @@ def load_env(filepath): key, value = line.split("=", 1) os.environ[key.strip()] = value.strip(' "\'\r\n') except FileNotFoundError: - print(f"⚠️ Файл {filepath} не найден. Используются системные переменные.") + print(f"⚠️ Файл {filepath} не найден.") load_env(ENV_PATH) +# Карта соответствия: Имя переменной в боте -> Название карточки в сейфе +CREDENTIALS_MAP = { + "DB_PASSWORD": os.getenv("PW_ID_SQL", "").strip(' "\'\r\n'), +} + # ============================================================ -# 2. Попытка загрузки из Passwork (как в оригинальном config.py) +# 2. Загрузка паролей из Passwork +# ============================================================ +DB_USER = "" +DB_PASSWORD = "" + +# Пытаемся найти passwork в нескольких местах +passwork_paths = [ + "/opt/passwork", + os.path.join(BASE_DIR, "passwork"), + os.path.join(BASE_DIR, "config", "passwork"), +] + +# Добавляем /opt/trueconf_bot в путь, если мы в контейнере +if BASE_DIR.startswith("/"): + passwork_paths.append("/passwork") + +print("🔍 Ищем модуль passwork в путях:") +for pw_path in passwork_paths: + exists = "✅" if os.path.isdir(pw_path) else "❌" + print(f" {exists} {pw_path}") + +# Добавляем все существующие пути +for pw_path in passwork_paths: + if os.path.isdir(pw_path) and pw_path not in sys.path: + sys.path.insert(0, pw_path) + print(f" → Добавлен в sys.path: {pw_path}") + +# Также добавляем корень проекта +if BASE_DIR not in sys.path: + sys.path.insert(0, BASE_DIR) + +passwork_loaded = False +try: + from passwork import get_passwork_secrets + print("\n✅ Модуль passwork найден!") + + required_cards = [name for name in CREDENTIALS_MAP.values() if name] + print(f" Запрашиваем карточки: {required_cards}") + + passwork_pool = get_passwork_secrets(required_cards=required_cards) + print(f" Получено карточек: {len(passwork_pool)}") + + for var_name, card_name in CREDENTIALS_MAP.items(): + if not card_name: + continue + clean_card = card_name.strip(' "\'\r\n') + card_data = passwork_pool.get(clean_card) + if card_data is None: + print(f" ⚠️ Карточка '{clean_card}' не найдена в ответе") + continue + + globals()[var_name] = card_data["password"].strip(' "\'\r\n') + if var_name == "DB_PASSWORD": + globals()["DB_USER"] = card_data.get("login", "").strip(' "\'\r\n') + print(f" ✓ {var_name} загружен из карточки '{clean_card}'") + + passwork_loaded = True + +except ImportError as e: + print(f"\n❌ Модуль passwork не импортируется: {e}") + print(" Варианты: модуль не установлен, нет прав, неверный путь") +except Exception as e: + print(f"\n⚠️ Ошибка Passwork: {e}") + +# Фоллбэк: проверяем системные переменные окружения +if not DB_PASSWORD: + DB_PASSWORD = os.getenv("DB_PASSWORD", "").strip() + DB_USER = os.getenv("DB_USER", DB_USER).strip() + if DB_PASSWORD: + print(" ✓ DB_PASSWORD из переменной окружения") + +# ============================================================ +# 3. Настройки подключения # ============================================================ DB_SERVER = os.getenv("SQL_SERVER", "SRVKEM-MOBILEIN.sibcem.ru") DB_NAME = os.getenv("SQL_DB_NAME", "BossCopy") -DB_USER = os.getenv("DB_USER", "") -DB_PASSWORD = os.getenv("DB_PASSWORD", "") -# Если Passwork не загружен, пробуем .db.env -if not DB_PASSWORD: - db_env_path = "/opt/trueconf_bot/config/.db.env" - if os.path.exists(db_env_path): - print(f"📂 Попытка загрузки DB-пароля из {db_env_path}...") - load_env(db_env_path) - DB_USER = os.getenv("DB_USER", DB_USER) - DB_PASSWORD = os.getenv("DB_PASSWORD", DB_PASSWORD) - -# ============================================================ -# 3. Подключение к SQL Server -# ============================================================ +print() print("=" * 60) print(" Проверка подключения к SQL Server") print("=" * 60) @@ -66,6 +125,9 @@ print(f" Логин : {DB_USER}") print(f" Пароль : {'*' * len(DB_PASSWORD) if DB_PASSWORD else '(не задан)'}") print() +# ============================================================ +# 4. Проверка pymssql +# ============================================================ try: import pymssql print(f"✅ pymssql загружен (версия {pymssql.__version__})") @@ -74,6 +136,9 @@ except ImportError: print(" pip install pymssql") sys.exit(1) +# ============================================================ +# 5. Подключение к SQL Server +# ============================================================ try: conn = pymssql.connect( server=DB_SERVER, @@ -90,7 +155,7 @@ except Exception as e: sys.exit(1) # ============================================================ -# 4. Проверка доступности таблиц +# 6. Проверка доступности таблиц # ============================================================ print() print("=" * 60) @@ -98,7 +163,7 @@ print(" Проверка доступности таблиц") print("=" * 60) tables_to_check = [ - ("UOV_SELFSERVICE_PR_EMP", "Таблица сотрудников (поиск по CARD_ID)"), + ("UOV_SELFSERVICE_PR_EMP", "Таблица сотрудников"), ("UOV_SELFSERVICE_TB_TABEL", "Табель учёта рабочего времени"), ] @@ -110,14 +175,16 @@ for table, desc in tables_to_check: cols = [col[0] for col in cursor.description] print(f"✅ {desc}") print(f" Таблица: {table}") - print(f" Столбцы: {', '.join(cols)}") + print(f" Столбцы: {', '.join(cols[:8])}") + if len(cols) > 8: + print(f" ... ещё {len(cols) - 8} столбцов") else: print(f"⚠️ {desc} — таблица пуста") except Exception as e: print(f"❌ {desc} — ошибка: {e}") # ============================================================ -# 5. Загрузка табеля за последние 5 месяцев +# 7. Загрузка табеля за последние 5 месяцев # ============================================================ print() print("=" * 60) @@ -127,8 +194,22 @@ print("=" * 60) now = datetime.now() months_back = 5 +try: + cursor.execute("SELECT TOP 1 e.ID, e.CARD_ID FROM UOV_SELFSERVICE_PR_EMP e ORDER BY e.ID") + emp_row = cursor.fetchone() + if not emp_row: + print("❌ Нет сотрудников в таблице UOV_SELFSERVICE_PR_EMP") + conn.close() + sys.exit(1) + test_emp_id = emp_row[0] + test_card_id = emp_row[1] + print(f"Тестовый сотрудник: emp_id={test_emp_id}, card_id={test_card_id}") +except Exception as e: + print(f"❌ Ошибка: {e}") + conn.close() + sys.exit(1) + for i in range(months_back): - # Вычисляем год и месяц month = now.month - i year = now.year while month <= 0: @@ -139,21 +220,6 @@ for i in range(months_back): print(f"\n📅 {month_name} {year}") print("-" * 40) - # Запрос 1: ищем EMP_ID по CARD_ID (тестовый — берём первого попавшегося) - try: - cursor.execute("SELECT TOP 1 e.ID, e.CARD_ID FROM UOV_SELFSERVICE_PR_EMP e ORDER BY e.ID") - emp_row = cursor.fetchone() - if not emp_row: - print(" ⚠️ Нет сотрудников в таблице UOV_SELFSERVICE_PR_EMP") - continue - emp_id = emp_row[0] - card_id = emp_row[1] - print(f" Тестовый сотрудник: emp_id={emp_id}, card_id={card_id}") - except Exception as e: - print(f" ❌ Ошибка поиска сотрудника: {e}") - continue - - # Запрос 2: данные табеля query = """ SELECT e.D, e.TDAY_ID, e.H FROM UOV_SELFSERVICE_TB_TABEL e @@ -161,10 +227,10 @@ for i in range(months_back): ORDER BY e.D ASC """ try: - cursor.execute(query, (emp_id, year, month)) + cursor.execute(query, (test_emp_id, year, month)) records = cursor.fetchall() except Exception as e: - print(f" ❌ Ошибка запроса табеля: {e}") + print(f" ❌ Ошибка запроса: {e}") continue if not records: @@ -173,54 +239,35 @@ for i in range(months_back): print(f" Записей: {len(records)}") - # Агрегация total_days = 0 total_hours = 0.0 codes = {} for r in records: - day_date = r[0] tday_id = str(r[1]).strip() if r[1] else "?" hours = float(r[2]) if r[2] is not None else 0.0 - codes[tday_id] = codes.get(tday_id, 0) + 1 - if tday_id == 'Я': total_days += 1 total_hours += hours - print(f" Явки (Я): {codes.get('Я', 0)} дн., всего часов: {total_hours:.1f}") - print(f" Коды дней: {', '.join(f'{k}={v}' for k, v in codes.items())}") + print(f" Явки (Я): {codes.get('Я', 0)} дн., часов: {total_hours:.1f}") + print(f" Коды: {', '.join(f'{k}={v}' for k, v in codes.items())}") - # Показываем первые 5 и последние 5 записей print(f" Первые 5 записей:") for r in records[:5]: d = r[0].strftime('%d.%m.%Y') if hasattr(r[0], 'strftime') else str(r[0]) print(f" {d} | {str(r[1]).strip():>3} | {float(r[2]) if r[2] else 0:.1f} ч.") - if len(records) > 5: - print(f" ... ещё {len(records) - 5} записей ...") - print(f" Последние 5 записей:") - for r in records[-5:]: - d = r[0].strftime('%d.%m.%Y') if hasattr(r[0], 'strftime') else str(r[0]) - print(f" {d} | {str(r[1]).strip():>3} | {float(r[2]) if r[2] else 0:.1f} ч.") # ============================================================ -# 6. Тест с конкретным CARD_ID пользователя +# 8. Тест с конкретным CARD_ID # ============================================================ print() print("=" * 60) print(" Тест с конкретным CARD_ID") print("=" * 60) -# Спрашиваем CARD_ID у пользователя -test_card_id = input("Введите CARD_ID для проверки (или Enter для теста с первым): ").strip() -if not test_card_id: - # Берём первый - cursor.execute("SELECT TOP 1 CARD_ID FROM UOV_SELFSERVICE_PR_CARD ORDER BY ID") - row = cursor.fetchone() - test_card_id = str(row[0]).strip() if row else "" - print(f" Тестовый CARD_ID (первый): {test_card_id}") - +test_card_id = input("Введите CARD_ID (или Enter для теста с первым): ").strip() if test_card_id: print(f" Поиск сотрудника с CARD_ID={test_card_id}...") cursor.execute("SELECT e.ID FROM UOV_SELFSERVICE_PR_EMP e WHERE e.CARD_ID = %s", (test_card_id,)) @@ -230,22 +277,17 @@ if test_card_id: else: emp_id = row[0] print(f" ✅ Найден: emp_id={emp_id}") - for i in range(min(3, months_back)): month = now.month - i year = now.year while month <= 0: month += 12 year -= 1 - month_name = calendar.month_name[month] cursor.execute(query, (emp_id, year, month)) records = cursor.fetchall() print(f" {month_name} {year}: {len(records)} записей") -# ============================================================ -# Закрытие -# ============================================================ conn.close() print() print("=" * 60)