перед внедрением веб интерфейса и API для взаимодействием с gemini.

This commit is contained in:
2026-08-05 23:02:35 +03:00
parent 8f611ec41a
commit 9deca9ab34
10 changed files with 495 additions and 194 deletions
+29 -18
View File
@@ -7,6 +7,7 @@ from config import (
)
# Импортируем прямую SQL-выгрузку отсутствий из 1С
from services.zup_extractor import fetch_zup_absences_from_sql
from core.database import load_scud_from_db_by_snapshot
warnings.filterwarnings('ignore', category=UserWarning, module='pandas')
@@ -138,27 +139,40 @@ def process_scud_anomalies(df_scud, exceptions=None):
return df_scud
def load_scud_data(target_date_type="today"):
"""Загружает файл СКУД за 'today' или 'yesterday' и выполняет валидацию аномалий."""
def load_scud_data(target_date_type="today", snapshot_param=None):
"""
Загружает логи СКУД за 'today' или 'yesterday' НАПРЯМУЮ из локальной базы SQLite.
"""
target_date = DATE_TODAY if target_date_type == "today" else DATE_YESTERDAY
scud_path = find_dated_file("Сотрудники", target_date, search_dirs=[SCUD_DIR])
# Загружаем данные строго из SQLite БД
df_scud = load_scud_from_db_by_snapshot(target_date, snapshot_param=snapshot_param)
if df_scud is None or df_scud.empty:
# Fallback на случай отсутствия записей за вчера — пробуем взять за сегодня
df_scud = load_scud_from_db_by_snapshot(DATE_TODAY, snapshot_param=snapshot_param)
if df_scud is None or df_scud.empty:
raise FileNotFoundError(f"В базе SQLite не найдены логи СКУД за {target_date}!")
if not scud_path:
scud_path = find_dated_file("Сотрудники", DATE_TODAY, search_dirs=[SCUD_DIR])
if not scud_path:
raise FileNotFoundError(f"Файл СКУД [{target_date_type}] за {target_date} не найден в {SCUD_DIR}!")
df_scud = pd.read_excel(scud_path)
exceptions = load_exceptions()
df_scud['fio_raw'] = df_scud['Сотрудник'].astype(str) if 'Сотрудник' in df_scud.columns else df_scud[df_scud.columns[0]].astype(str)
df_scud['fio_clean'] = df_scud['fio_raw'].apply(clean_scud_fio_light)
if 'fio_clean' not in df_scud.columns:
fio_raw_col = 'fio' if 'fio' in df_scud.columns else ('Сотрудник' if 'Сотрудник' in df_scud.columns else df_scud.columns[0])
df_scud['fio_raw'] = df_scud[fio_raw_col].astype(str)
df_scud['fio_clean'] = df_scud['fio_raw'].apply(clean_scud_fio_light)
# Применяем обработчик аномалий и первой активности
df_scud = process_scud_anomalies(df_scud, exceptions=exceptions)
# Нормализация колонок под единый стандарт отчета
if 'Начало_дня' not in df_scud.columns and 'time_in' in df_scud.columns:
df_scud['Начало_дня'] = df_scud['time_in']
if 'Конец_дня' not in df_scud.columns and 'time_out' in df_scud.columns:
df_scud['Конец_дня'] = df_scud['time_out']
if 'Первая_активность' not in df_scud.columns and 'first_activity' in df_scud.columns:
df_scud['Первая_активность'] = df_scud['first_activity']
if 'Пришел' not in df_scud.columns and 'is_present' in df_scud.columns:
df_scud['Пришел'] = df_scud['is_present'].astype(bool)
df_scud['is_excluded'] = df_scud.apply(
lambda r: is_excluded(r.get('Сотрудник', ''), r.get('Подразделение', ''), r.get('Должность', ''), exceptions),
lambda r: is_excluded(r.get('fio', r.get('Сотрудник', '')), r.get('department', r.get('Подразделение', '')), r.get('position', r.get('Должность', '')), exceptions),
axis=1
)
return df_scud
@@ -166,8 +180,7 @@ def load_scud_data(target_date_type="today"):
def load_all_data():
"""
Загружает слитные датасеты за Сегодня и за Вчера.
Если данных за Сегодня нет, возвращает для них None.
Загружает слитные датасеты за Сегодня и за Вчера напрямую из базы SQLite и 1С.
"""
df_scud_today = load_scud_data(target_date_type="today")
try:
@@ -175,11 +188,9 @@ def load_all_data():
except FileNotFoundError:
df_scud_yesterday = df_scud_today.copy()
# Загружаем 1С за Сегодня (может быть None)
df_staff_today = load_staff_data(DATE_TODAY)
df_absent_today = load_absent_data(DATE_TODAY)
# Загружаем 1С за Вчера (гарантированно есть)
df_staff_yesterday = load_staff_data(DATE_YESTERDAY)
df_absent_yesterday = load_absent_data(DATE_YESTERDAY)