105 lines
4.5 KiB
Python
105 lines
4.5 KiB
Python
import os
|
|
import pandas as pd
|
|
import warnings
|
|
from config import (
|
|
normalize_fio, clean_scud_fio_light, load_exceptions,
|
|
SCUD_FILE, SCUD_FILE_TODAY, SCUD_FILE_YESTERDAY,
|
|
STAFF_FILE_1C, ABSENT_FILE_1C
|
|
)
|
|
|
|
warnings.filterwarnings('ignore', category=UserWarning, module='pandas')
|
|
|
|
|
|
def is_excluded(fio, dept, pos, exceptions):
|
|
fio_clean = normalize_fio(fio)
|
|
dept_str = str(dept).strip().upper() if pd.notna(dept) else ""
|
|
pos_str = str(pos).strip().lower() if pd.notna(pos) else ""
|
|
|
|
if fio_clean in exceptions["fio"] or dept_str in exceptions["departments"] or pos_str in exceptions["positions"]:
|
|
return True
|
|
if any(keyword in pos_str for keyword in exceptions["position_keywords"]):
|
|
return True
|
|
return False
|
|
|
|
|
|
def load_staff_data():
|
|
if not os.path.exists(STAFF_FILE_1C):
|
|
raise FileNotFoundError(f"Файл штатного расписания не найден по пути: {STAFF_FILE_1C}")
|
|
df_staff = pd.read_excel(STAFF_FILE_1C, skiprows=7)
|
|
df_staff = df_staff.rename(columns={df_staff.columns[1]: 'ФИО'})
|
|
df_staff['fio_clean'] = df_staff['ФИО'].apply(normalize_fio)
|
|
return df_staff
|
|
|
|
|
|
def load_absent_data():
|
|
if not os.path.exists(ABSENT_FILE_1C):
|
|
raise FileNotFoundError(f"Файл отсутствий не найден по пути: {ABSENT_FILE_1C}")
|
|
df_absent_raw = pd.read_excel(ABSENT_FILE_1C, skiprows=3)
|
|
df_absent = df_absent_raw[1:].copy().reset_index(drop=True)
|
|
df_absent = df_absent.rename(columns={df_absent.columns[0]: 'ФИО', df_absent.columns[2]: 'Вид_отсутствия'})
|
|
df_absent['fio_clean'] = df_absent['ФИО'].apply(normalize_fio)
|
|
return df_absent[['fio_clean', 'Вид_отсутствия']].dropna(subset=['fio_clean'])
|
|
|
|
|
|
def load_scud_data(target_date_type="today"):
|
|
"""
|
|
Загружает файл СКУД за конкретную дату:
|
|
• target_date_type="today" -> data/scud/Сотрудники_СЕГОДНЯ.xlsx
|
|
• target_date_type="yesterday" -> data/scud/Сотрудники_ВЧЕРА.xlsx
|
|
"""
|
|
if target_date_type == "yesterday":
|
|
scud_path = SCUD_FILE_YESTERDAY
|
|
else:
|
|
scud_path = SCUD_FILE_TODAY
|
|
|
|
# Резервный фоллбэк, если конкретный файл отсутствия еще не создан
|
|
if not os.path.exists(scud_path):
|
|
if os.path.exists(SCUD_FILE):
|
|
scud_path = SCUD_FILE
|
|
else:
|
|
raise FileNotFoundError(f"Файл СКУД [{target_date_type}] не найден по пути: {scud_path}")
|
|
|
|
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)
|
|
|
|
start_col = 'Начало_дня' if 'Начало_дня' in df_scud.columns else ('Начало дня' if 'Начало дня' in df_scud.columns else None)
|
|
status_col = 'Статус' if 'Статус' in df_scud.columns else None
|
|
|
|
def is_person_present(row):
|
|
val_status = str(row.get(status_col, '')).strip().lower() if status_col else ''
|
|
val_time = str(row.get(start_col, '')).strip() if start_col else ''
|
|
|
|
if 'отсутствовал' in val_status or val_time in ['нет входа', 'none', 'nan', '', '00:00']:
|
|
return False
|
|
return True
|
|
|
|
df_scud['Пришел'] = df_scud.apply(is_person_present, axis=1)
|
|
|
|
df_scud['is_excluded'] = df_scud.apply(
|
|
lambda r: is_excluded(r.get('Сотрудник', ''), r.get('Подразделение', ''), r.get('Должность', ''), exceptions),
|
|
axis=1
|
|
)
|
|
return df_scud
|
|
|
|
|
|
def load_all_data():
|
|
"""
|
|
Загружает слитный датасет за сегодня, а также отдельный датасет за вчера.
|
|
Возвращает: df_scud_today, df_scud_yesterday, staff_fios_clean, df_absent
|
|
"""
|
|
df_scud_today = load_scud_data(target_date_type="today")
|
|
|
|
# Пытаемся забрать вчерашние данные СКУД
|
|
try:
|
|
df_scud_yesterday = load_scud_data(target_date_type="yesterday")
|
|
except FileNotFoundError:
|
|
df_scud_yesterday = df_scud_today.copy()
|
|
|
|
df_staff = load_staff_data()
|
|
df_absent = load_absent_data()
|
|
staff_fios_clean = df_staff['fio_clean'].dropna().tolist()
|
|
|
|
return df_scud_today, df_scud_yesterday, staff_fios_clean, df_absent |