diff --git a/test_tabel_check.py b/test_tabel_check.py index 4e03e19..5308a84 100644 --- a/test_tabel_check.py +++ b/test_tabel_check.py @@ -1,7 +1,12 @@ #!/usr/bin/env python3 """ Проверка подключения к SQL Server и загрузки данных табеля -за последние 5 месяцев. +за последние 5 месяцев для конкретного сотрудника. + +Поиск сотрудника: + 1. Ищем в AD по email (ds.krivochenko@sibcem.ru) → получаем extensionAttribute2 = CARD_ID + 2. По CARD_ID ищем в SQL (UOV_SELFSERVICE_PR_EMP) → получаем EMP_ID + 3. По EMP_ID загружаем табель (UOV_SELFSERVICE_TB_TABEL) за 5 месяцев Запуск: cd /opt/trueconf_bot @@ -35,6 +40,7 @@ load_env(ENV_PATH) # Карта соответствия: Имя переменной в боте -> Название карточки в сейфе CREDENTIALS_MAP = { "DB_PASSWORD": os.getenv("PW_ID_SQL", "").strip(' "\'\r\n'), + "AD_PASSWORD": os.getenv("PW_ID_AD", "").strip(' "\'\r\n'), } # ============================================================ @@ -42,78 +48,57 @@ CREDENTIALS_MAP = { # ============================================================ DB_USER = "" DB_PASSWORD = "" +AD_USER = "" +AD_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: +for pw_path in ["/opt/passwork", os.path.join(BASE_DIR, "passwork"), os.path.join(BASE_DIR, "config", "passwork")]: 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 найден!") - + print("🔐 Загрузка секретов из 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}' не найдена в ответе") + print(f" ⚠️ Карточка '{clean_card}' не найдена") continue - globals()[var_name] = card_data["password"].strip(' "\'\r\n') - if var_name == "DB_PASSWORD": + if var_name == "AD_PASSWORD": + globals()["AD_USER"] = card_data.get("login", "").strip(' "\'\r\n') + elif 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(" Варианты: модуль не установлен, нет прав, неверный путь") + print(f" ✓ {var_name} из карточки '{clean_card}'") +except ImportError: + print("⚠️ Модуль passwork не найден") except Exception as e: - print(f"\n⚠️ Ошибка Passwork: {e}") + print(f"⚠️ Ошибка 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 из переменной окружения") +if not AD_PASSWORD: + AD_PASSWORD = os.getenv("AD_PASSWORD", "").strip() + AD_USER = os.getenv("AD_USER", AD_USER).strip() # ============================================================ # 3. Настройки подключения # ============================================================ DB_SERVER = os.getenv("SQL_SERVER", "SRVKEM-MOBILEIN.sibcem.ru") DB_NAME = os.getenv("SQL_DB_NAME", "BossCopy") +AD_SERVER = os.getenv("AD_SERVER", "ldap://172.16.20.20") +AD_BASES = ( + "OU=-Пользователи,DC=sibcem,DC=ru", + "OU=Планшеты,OU=enabled,OU=БезКомпьютеров,DC=sibcem,DC=ru", +) print() print("=" * 60) @@ -133,7 +118,6 @@ try: print(f"✅ pymssql загружен (версия {pymssql.__version__})") except ImportError: print("❌ pymssql не установлен!") - print(" pip install pymssql") sys.exit(1) # ============================================================ @@ -155,60 +139,143 @@ except Exception as e: sys.exit(1) # ============================================================ -# 6. Проверка доступности таблиц +# 6. Поиск сотрудника в AD по email → CARD_ID # ============================================================ print() print("=" * 60) -print(" Проверка доступности таблиц") +print(" Поиск сотрудника в Active Directory") print("=" * 60) -tables_to_check = [ - ("UOV_SELFSERVICE_PR_EMP", "Таблица сотрудников"), - ("UOV_SELFSERVICE_TB_TABEL", "Табель учёта рабочего времени"), -] +# Email для поиска +TARGET_EMAIL = "ds.krivochenko@sibcem.ru" +print(f" Ищем: {TARGET_EMAIL}") -for table, desc in tables_to_check: - try: - cursor.execute(f"SELECT TOP 1 * FROM {table}") - row = cursor.fetchone() - if row: - cols = [col[0] for col in cursor.description] - print(f"✅ {desc}") - print(f" Таблица: {table}") - 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}") +# Импортируем ldap3 и ищем +try: + from ldap3 import Server, Connection, ALL + from ldap3.utils.conv import escape_filter_chars + + server = Server(AD_SERVER, get_info=ALL) + ldap_conn = Connection(server, user=AD_USER, password=AD_PASSWORD, auto_bind=True) + + # Строим фильтр как в ad_search.py + short_username = TARGET_EMAIL.split("@")[0] if "@" in TARGET_EMAIL else TARGET_EMAIL + + or_parts = [ + "(mail={})".format(TARGET_EMAIL), + "(userPrincipalName={})".format(TARGET_EMAIL), + "(userPrincipalName={})".format(short_username + "@sibcem.ru"), + "(sAMAccountName={})".format(short_username), + ] + or_filter = "(|{})".format("".join(or_parts)) + search_filter = "(&{}{})".format("(objectClass=user)", or_filter) + + print(f" LDAP-фильтр: {search_filter}") + + card_id_from_ad = None + ldap_entry = None + + for base in AD_BASES: + ldap_conn.search( + search_base=base, + search_filter=search_filter, + attributes=["cn", "sAMAccountName", "mail", "userPrincipalName", "extensionAttribute2"], + ) + if ldap_conn.entries: + ldap_entry = ldap_conn.entries[0] + print(f" ✅ Найден в OU: {base}") + print(f" CN : {ldap_entry.cn}") + print(f" sAMAccountName: {ldap_entry.sAMAccountName}") + print(f" mail : {ldap_entry.mail}") + ext2 = str(ldap_entry.extensionAttribute2) if hasattr(ldap_entry, 'extensionAttribute2') and ldap_entry.extensionAttribute2 else "(не задан)" + print(f" extensionAttribute2: {ext2}") + card_id_from_ad = ext2 + break + + if not ldap_entry: + print(f" ❌ Сотрудник не найден в AD по email {TARGET_EMAIL}") + +except ImportError: + print("❌ ldap3 не установлен") + sys.exit(1) +except Exception as e: + print(f"❌ Ошибка LDAP: {e}") + sys.exit(1) # ============================================================ -# 7. Загрузка табеля за последние 5 месяцев +# 7. Поиск EMP_ID по CARD_ID в SQL +# ============================================================ +print() +print("=" * 60) +print(" Поиск сотрудника в SQL Server") +print("=" * 60) + +emp_id = None +card_id = None + +if card_id_from_ad: + card_id = card_id_from_ad + print(f" CARD_ID из AD: {card_id}") + cursor.execute("SELECT e.ID, e.CARD_ID FROM UOV_SELFSERVICE_PR_EMP e WHERE e.CARD_ID = %s", (card_id,)) + row = cursor.fetchone() + if row: + emp_id = row[0] + print(f" ✅ Найден: emp_id={emp_id}, CARD_ID={row[1]}") + else: + print(f" ⚠️ Сотрудник с CARD_ID={card_id} не найден в UOV_SELFSERVICE_PR_EMP") + +# Если не нашли по CARD_ID из AD — пробуем по email через SQL +if not emp_id: + print(f" ⚠️ Пробуем поиск по email через SQL...") + cursor.execute( + "SELECT e.ID, e.CARD_ID, e.EMAIL FROM UOV_SELFSERVICE_PR_EMP e WHERE e.EMAIL LIKE %s OR e.EMAIL LIKE %s ORDER BY e.ID LIMIT 1", + (f"%{TARGET_EMAIL}%", f"%{short_username}@%") + ) + row = cursor.fetchone() + if row: + emp_id = row[0] + card_id = row[1] + print(f" ✅ Найден: emp_id={emp_id}, CARD_ID={card_id}") + else: + print(f" ❌ Сотрудник не найден") + +# Если нашли — выводим инфу +if emp_id: + cursor.execute( + "SELECT f.SNAME, d.NAME, appoint.NAME, e.EMAIL " + "FROM UOV_SELFSERVICE_PR_EMP e " + "JOIN UOV_SELFSERVICE_PR_TRANS t ON t.EMP_ID = e.ID " + "JOIN UOV_SELFSERVICE_HR_FIRM f ON f.ID = e.FIRM_ID " + "JOIN UOV_SELFSERVICE_HR_DEPT d ON d.ID = t.DEPT_ID " + "JOIN UOV_SELFSERVICE_ST_APPOINT appoint ON appoint.ID = t.APPOINT_ID " + "WHERE e.CARD_ID = %s AND t.D_FROM <= CAST(GETDATE() AS DATE) " + "AND (t.D_TO >= CAST(GETDATE() AS DATE) OR t.D_TO = CAST('1999-12-31' AS DATE))", + (card_id,) + ) + row = cursor.fetchone() + if row: + print(f"\n 📋 Информация о сотруднике:") + print(f" Компания : {row[0]}") + print(f" Отдел : {row[1]}") + print(f" Должность: {row[2]}") + print(f" Email : {row[3]}") + +# ============================================================ +# 8. Загрузка табеля за последние 5 месяцев # ============================================================ print() print("=" * 60) print(" Загрузка табеля за последние 5 месяцев") 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}") +if not emp_id: + print(" ❌ Не удалось найти сотрудника — завершение") conn.close() sys.exit(1) +now = datetime.now() +months_back = 5 + for i in range(months_back): month = now.month - i year = now.year @@ -227,7 +294,7 @@ for i in range(months_back): ORDER BY e.D ASC """ try: - cursor.execute(query, (test_emp_id, year, month)) + cursor.execute(query, (emp_id, year, month)) records = cursor.fetchall() except Exception as e: print(f" ❌ Ошибка запроса: {e}") @@ -260,34 +327,8 @@ for i in range(months_back): print(f" {d} | {str(r[1]).strip():>3} | {float(r[2]) if r[2] else 0:.1f} ч.") # ============================================================ -# 8. Тест с конкретным CARD_ID +# Закрытие # ============================================================ -print() -print("=" * 60) -print(" Тест с конкретным CARD_ID") -print("=" * 60) - -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,)) - row = cursor.fetchone() - if not row: - print(f" ⚠️ Сотрудник с CARD_ID={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)