302 lines
11 KiB
Python
302 lines
11 KiB
Python
#!/usr/bin/env python3
|
||
"""Диагностика данных сотрудника для модуля ЛК (расчетnye listki)."""
|
||
|
||
import os
|
||
import sys
|
||
|
||
BASE_DIR = "/opt/trueconf_bot"
|
||
os.chdir(BASE_DIR)
|
||
|
||
# Загрузка .env
|
||
def load_env(filepath):
|
||
with open(filepath, "r", encoding="utf-8") as f:
|
||
for line in f:
|
||
line = line.strip()
|
||
if line and not line.startswith("#") and "=" in line:
|
||
key, value = line.split("=", 1)
|
||
value = value.strip(' "')
|
||
value = value.strip("'")
|
||
value = value.strip()
|
||
os.environ[key.strip()] = value
|
||
|
||
load_env(os.path.join(BASE_DIR, "config", ".env"))
|
||
|
||
# Загрузка passwork
|
||
for pw_path in ["/opt/passwork", os.path.join(BASE_DIR, "passwork")]:
|
||
if os.path.isdir(pw_path) and pw_path not in sys.path:
|
||
sys.path.insert(0, pw_path)
|
||
|
||
from passwork import get_passwork_secrets
|
||
card_name = os.getenv("PW_ID_SQL", "").strip()
|
||
passwork_pool = get_passwork_secrets(required_cards=[card_name])
|
||
card_data = passwork_pool[card_name]
|
||
|
||
DB_USER = card_data["login"]
|
||
DB_PASSWORD = card_data["password"]
|
||
SQL_SERVER = os.getenv("SQL_SERVER", "SRVKEM-MOBILEIN.sibcem.ru")
|
||
SQL_DB_NAME = os.getenv("SQL_DB_NAME", "BossCopy")
|
||
|
||
import pymssql
|
||
import ldap3
|
||
|
||
# --- Подключение к AD ---
|
||
print("=" * 60)
|
||
print("Диагностика сотрудника: la.guseynova@sibcem.ru")
|
||
print("=" * 60)
|
||
|
||
email = "la.guseynova@sibcem.ru"
|
||
search_id = email.replace("@tcs.sibcem.ru", "@sibcem.ru")
|
||
short_name = search_id.split("@")[0] # la.guseynova — без домена
|
||
|
||
print(f"\n--- 0. Поиск в AD ---")
|
||
print(f" Email: {email}")
|
||
print(f" Search ID: {search_id}")
|
||
print(f" Short (без домена): {short_name}")
|
||
|
||
AD_SERVER = "172.16.20.20"
|
||
AD_BASE = "DC=sibcem,DC=ru"
|
||
|
||
try:
|
||
conn = ldap3.Connection(
|
||
ldap3.Server(AD_SERVER, connect_timeout=5),
|
||
auto_bind=True,
|
||
read_only=True
|
||
)
|
||
|
||
# Разделяем поиск:
|
||
# - mail: полный email с доменом (la.guseynova@sibcem.ru)
|
||
# - sAMAccountName: только логин без домена (la.guseynova)
|
||
# - userPrincipalName: полный UPN с доменом
|
||
# - anr: логин без домена (ANR ищет по sAMAccountName, displayName, etc.)
|
||
search_filter = f"(|(mail={search_id}*)(sAMAccountName={short_name})(userPrincipalName={search_id}*)(anr={short_name}))"
|
||
print(f" LDAP-фильтр: {search_filter}")
|
||
print(f" mail: {search_id} (полный email)")
|
||
print(f" sAMAccountName: {short_name} (без домена)")
|
||
print(f" userPrincipalName: {search_id} (полный UPN)")
|
||
print(f" anr: {short_name} (без домена)")
|
||
|
||
conn.search(
|
||
search_base=AD_BASE,
|
||
search_filter=search_filter,
|
||
attributes=["cn", "sAMAccountName", "mail", "userPrincipalName", "extensionAttribute2", "mobile", "personalPager"]
|
||
)
|
||
if conn.entries:
|
||
entry = conn.entries[0]
|
||
cn = str(entry.cn)
|
||
sam = str(entry.sAMAccountName)
|
||
mail = str(entry.mail) if 'mail' in entry else ""
|
||
upn = str(entry.userPrincipalName) if 'userPrincipalName' in entry else ""
|
||
ext2 = str(entry.extensionAttribute2) if 'extensionAttribute2' in entry else ""
|
||
mobile = str(entry.mobile) if 'mobile' in entry else ""
|
||
pager = str(entry.personalPager) if 'personalPager' in entry else ""
|
||
|
||
print(f"\n НАЙДЕН:")
|
||
print(f" CN: {cn}")
|
||
print(f" sAMAccountName: {sam}")
|
||
print(f" mail: {mail}")
|
||
print(f" UPN: {upn}")
|
||
print(f" extensionAttribute2 (CARD_ID): {ext2}")
|
||
print(f" mobile: {mobile}")
|
||
print(f" pager: {pager}")
|
||
else:
|
||
print(" Не найден по расширенному фильтру. Пробую ANR отдельно...")
|
||
conn.search(
|
||
search_base=AD_BASE,
|
||
search_filter=f"(anr={short_name})",
|
||
attributes=["cn", "sAMAccountName", "mail", "userPrincipalName", "extensionAttribute2", "mobile", "personalPager"]
|
||
)
|
||
if conn.entries:
|
||
entry = conn.entries[0]
|
||
cn = str(entry.cn)
|
||
sam = str(entry.sAMAccountName)
|
||
mail = str(entry.mail) if 'mail' in entry else ""
|
||
upn = str(entry.userPrincipalName) if 'userPrincipalName' in entry else ""
|
||
ext2 = str(entry.extensionAttribute2) if 'extensionAttribute2' in entry else ""
|
||
mobile = str(entry.mobile) if 'mobile' in entry else ""
|
||
pager = str(entry.personalPager) if 'personalPager' in entry else ""
|
||
|
||
print(f"\n НАЙДЕН (ANR fallback):")
|
||
print(f" CN: {cn}")
|
||
print(f" sAMAccountName: {sam}")
|
||
print(f" mail: {mail}")
|
||
print(f" UPN: {upn}")
|
||
print(f" extensionAttribute2 (CARD_ID): {ext2}")
|
||
print(f" mobile: {mobile}")
|
||
print(f" pager: {pager}")
|
||
else:
|
||
print(" НЕ НАЙДЕН в AD!")
|
||
conn.unbind()
|
||
sys.exit(0)
|
||
|
||
conn.unbind()
|
||
except Exception as e:
|
||
print(f" Ошибка подключения к AD: {e}")
|
||
sys.exit(0)
|
||
|
||
# --- Подключение к SQL ---
|
||
print(f"\n--- 1. Подключение к SQL ---")
|
||
try:
|
||
conn_sql = pymssql.connect(
|
||
server=SQL_SERVER,
|
||
user=DB_USER,
|
||
password=DB_PASSWORD,
|
||
database=SQL_DB_NAME,
|
||
charset="cp1251",
|
||
login_timeout=10
|
||
)
|
||
cursor = conn_sql.cursor()
|
||
print(f" Подключено к {SQL_SERVER}/{SQL_DB_NAME}")
|
||
except Exception as e:
|
||
print(f" Ошибка подключения к SQL: {e}")
|
||
sys.exit(0)
|
||
|
||
# Определяем card_id: через поиск в БД
|
||
card_id = None
|
||
|
||
# Пробуем найти CARD_ID через PR_CARD + PR_EMP
|
||
print(f"\n--- 2. Поиск CARD_ID в PR_CARD ---")
|
||
cursor.execute(
|
||
"SELECT c.ID FROM UOV_SELFSERVICE_PR_CARD c "
|
||
"JOIN UOV_SELFSERVICE_PR_EMP e ON e.CARD_ID = c.ID "
|
||
"WHERE e.EMAIL_ID LIKE %s OR e.USERNAME LIKE %s",
|
||
(f"%{short_name}%", f"%{short_name}%")
|
||
)
|
||
rows = cursor.fetchall()
|
||
if rows:
|
||
for r in rows:
|
||
print(f" CARD_ID (по username): {r[0]}")
|
||
card_id = rows[0][0]
|
||
else:
|
||
print(f" Не найден по username в PR_CARD/PR_EMP")
|
||
|
||
if not card_id:
|
||
cursor.execute(
|
||
"SELECT c.ID FROM UOV_SELFSERVICE_PR_CARD c "
|
||
"JOIN UOV_SELFSERVICE_PR_EMP e ON e.CARD_ID = c.ID "
|
||
"WHERE e.EMAIL_ID LIKE %s",
|
||
(f"%{search_id.split('@')[0]}%",)
|
||
)
|
||
rows = cursor.fetchall()
|
||
if rows:
|
||
for r in rows:
|
||
print(f" CARD_ID (по email): {r[0]}")
|
||
card_id = rows[0][0]
|
||
else:
|
||
print(f" Не найден по email в PR_CARD/PR_EMP")
|
||
|
||
if not card_id:
|
||
print("\n CARD_ID не найден в БД!")
|
||
conn_sql.close()
|
||
sys.exit(0)
|
||
|
||
print(f"\n Используем CARD_ID: {card_id}")
|
||
|
||
# --- 3. PR_EMP ---
|
||
print(f"\n--- 3. PR_EMP (профиль сотрудника) ---")
|
||
cursor.execute(
|
||
"SELECT ID, FIRM_ID, EMAIL_ID, USERNAME FROM UOV_SELFSERVICE_PR_EMP WHERE CARD_ID = %s",
|
||
(card_id,)
|
||
)
|
||
emp_rows = cursor.fetchall()
|
||
if emp_rows:
|
||
for r in emp_rows:
|
||
print(f" EMP_ID: {r[0]}, FIRM_ID: {r[1]}, EMAIL: {r[2]}, USERNAME: {r[3]}")
|
||
else:
|
||
print(" ПУСТО - нет записей в PR_EMP")
|
||
|
||
# --- 4. PR_TRANS ---
|
||
print(f"\n--- 4. PR_TRANS (кадровые назначения) ---")
|
||
if emp_rows:
|
||
emp_ids = [r[0] for r in emp_rows]
|
||
placeholders = ",".join(["%s"] * len(emp_ids))
|
||
cursor.execute(
|
||
f"SELECT EMP_ID, D_FROM, D_TO, TP_ABBR, SYSPAY_ID "
|
||
f"FROM UOV_SELFSERVICE_PR_TRANS "
|
||
f"WHERE EMP_ID IN ({placeholders}) "
|
||
f"ORDER BY D_FROM DESC",
|
||
emp_ids
|
||
)
|
||
trans_rows = cursor.fetchall()
|
||
if trans_rows:
|
||
print(f" Найдено записей: {len(trans_rows)}")
|
||
for r in trans_rows[:10]:
|
||
print(f" EMP_ID: {r[0]}, D_FROM: {r[1]}, D_TO: {r[2]}, TP: {r[3]}, SYSPAY: {r[4]}")
|
||
else:
|
||
print(" ПУСТО - нет записей в PR_TRANS")
|
||
else:
|
||
print(" Пропуск (нет PR_EMP)")
|
||
|
||
# --- 5. SL_YTAX ---
|
||
print(f"\n--- 5. SL_YTAX (периоды с данными) ---")
|
||
cursor.execute(
|
||
"SELECT DISTINCT TYEAR, TMONTH, CMONTH FROM UOV_SELFSERVICE_SL_YTAX "
|
||
"WHERE CARD_ID = %s ORDER BY CMONTH DESC",
|
||
(card_id,)
|
||
)
|
||
tax_rows = cursor.fetchall()
|
||
if tax_rows:
|
||
print(f" Найдено периодов: {len(tax_rows)}")
|
||
for r in tax_rows[:10]:
|
||
print(f" {r[0]}-{r[1]:02d} (CMONTH={r[2]})")
|
||
else:
|
||
print(" ПУСТО - нет периодов в SL_YTAX")
|
||
|
||
# --- 6. Проверка q_firm ---
|
||
print(f"\n--- 6. Проверка q_firm для последнего периода ---")
|
||
if tax_rows:
|
||
latest_cmonth = tax_rows[0][2]
|
||
tyear = (latest_cmonth - 1) // 12
|
||
tmonth = (latest_cmonth - 1) % 12 + 1
|
||
import calendar
|
||
_, last_day = calendar.monthrange(tyear, tmonth)
|
||
date_start = f"{tyear}-{tmonth:02d}-01"
|
||
date_end = f"{tyear}-{tmonth:02d}-{last_day:02d}"
|
||
date_params = (date_start, date_start, date_end, date_end, date_end)
|
||
|
||
print(f" Период: {tyear}-{tmonth:02d}")
|
||
|
||
q_firm = """
|
||
select e.FIRM_ID, f.SNAME from (select e.id, e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e
|
||
join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID where c.ID = %s
|
||
group by e.ID, e.FIRM_ID ) as 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
|
||
where ((t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO = '1999-12-31'))
|
||
group by e.FIRM_ID, f.SNAME
|
||
"""
|
||
cursor.execute(q_firm, (card_id, *date_params))
|
||
firm_row = cursor.fetchone()
|
||
if firm_row:
|
||
print(f" q_firm НАШЁЛ: FIRM_ID={firm_row[0]}, SNAME={firm_row[1]}")
|
||
else:
|
||
print(f" q_firm НЕ НАШЁЛ (NULL) - это вызовет ошибку!")
|
||
q_firm_fb = """
|
||
select e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e
|
||
join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID
|
||
where c.ID = %s
|
||
group by e.ID, e.FIRM_ID
|
||
"""
|
||
cursor.execute(q_firm_fb, (card_id,))
|
||
fb_row = cursor.fetchone()
|
||
if fb_row:
|
||
print(f" Фоллбэк НАШЁЛ: FIRM_ID={fb_row[0]}")
|
||
else:
|
||
print(f" Фоллбэк НЕ НАШЁЛ - критическая ошибка!")
|
||
|
||
# --- 7. Сводка ---
|
||
print(f"\n--- 7. Сводка ---")
|
||
cursor.execute(
|
||
"SELECT COUNT(DISTINCT CMONTH), MIN(CMONTH), MAX(CMONTH) FROM UOV_SELFSERVICE_SL_YTAX WHERE CARD_ID = %s",
|
||
(card_id,)
|
||
)
|
||
summary = cursor.fetchone()
|
||
if summary:
|
||
print(f" Периодов в SL_YTAX: {summary[0]}")
|
||
print(f" Диапазон: {summary[1]} - {summary[2]}")
|
||
|
||
print(f"\n{'=' * 60}")
|
||
print("Диагностика завершена")
|
||
print("=" * 60)
|
||
|
||
conn_sql.close()
|