import os import pandas as pd import warnings from config import ( normalize_fio, clean_scud_fio_light, load_exceptions, DATA_DIR, 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(): scud_path = SCUD_FILE_TODAY if os.path.exists(SCUD_FILE_TODAY) else (SCUD_FILE_YESTERDAY if os.path.exists(SCUD_FILE_YESTERDAY) else SCUD_FILE) if not os.path.exists(scud_path): raise FileNotFoundError(f"Файл СКУД не найден в папке data/scud: {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 = load_scud_data() df_staff = load_staff_data() df_absent = load_absent_data() staff_fios_clean = df_staff['fio_clean'].dropna().tolist() return df_scud, staff_fios_clean, df_absent