feat(reports): stabilize on-demand generation, live presence and 1C fallback
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
===============================================================================
|
||||
FILE: services/scud_etl/pipeline.py
|
||||
ROLE: Загрузка наилучших срезов СКУД и штата/отсутствий 1С с умным fallback-ом.
|
||||
===============================================================================
|
||||
"""
|
||||
|
||||
@@ -12,7 +13,7 @@ import pandas as pd
|
||||
from core.connection import get_connection
|
||||
from core.database import load_scud_from_db_by_snapshot
|
||||
from config import DATA_DIR
|
||||
from services.data_loader import load_staff_data, load_absent_data
|
||||
from services.data_loader import load_1c_data_smart, load_staff_data, load_absent_data
|
||||
|
||||
logger = logging.getLogger("SCUD_PIPELINE")
|
||||
|
||||
@@ -57,8 +58,42 @@ def load_best_snapshot_for_date(date_str: str, prefer_final_y: bool = False) ->
|
||||
|
||||
def load_1c_files_for_date(date_str: str) -> Tuple[Optional[pd.DataFrame], Optional[pd.DataFrame]]:
|
||||
"""
|
||||
Загружает реестры штата и отсутствий 1С на указанную дату через data_loader.
|
||||
Загружает штат и отсутствия с каскадным fallback:
|
||||
1. Синхронизирует свежие файлы с сетевой шары.
|
||||
2. Загружает штат и отсутствия через load_1c_data_smart(..., use_db=True).
|
||||
3. Если штат пуст — берет последний доступный срез штата из zup_staff в SQLite.
|
||||
"""
|
||||
df_staff = load_staff_data(date_str)
|
||||
df_abs = load_absent_data(date_str)
|
||||
clean_date = date_str.replace('_', '.')
|
||||
|
||||
try:
|
||||
from services.share_copier import copy_1c_files_from_share
|
||||
copy_1c_files_from_share()
|
||||
except Exception as e:
|
||||
logger.warning(f"[Pipeline] Ошибка копирования с шары: {e}")
|
||||
|
||||
df_staff, df_abs = load_1c_data_smart(clean_date, use_db=True)
|
||||
|
||||
# Fallback за штат: ако данашњи штат још увек није доступан, користи се претходни из базе
|
||||
if df_staff is None or df_staff.empty:
|
||||
with get_connection(row_factory=True) as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT snapshot_date
|
||||
FROM zup_staff
|
||||
ORDER BY
|
||||
SUBSTR(snapshot_date, 7, 4) DESC,
|
||||
SUBSTR(snapshot_date, 4, 2) DESC,
|
||||
SUBSTR(snapshot_date, 1, 2) DESC,
|
||||
id DESC
|
||||
LIMIT 1
|
||||
""")
|
||||
row = cursor.fetchone()
|
||||
if row and row[0]:
|
||||
fallback_date = row[0]
|
||||
df_staff = pd.read_sql_query(
|
||||
"SELECT fio as 'ФИО', fio_clean, department as 'Подразделение', position as 'Должность' FROM zup_staff WHERE snapshot_date = ?",
|
||||
conn, params=(fallback_date,)
|
||||
)
|
||||
logger.info(f"[Pipeline] Для даты {clean_date} применен штат за {fallback_date} ({len(df_staff)} чел.)")
|
||||
|
||||
return df_staff, df_abs
|
||||
Reference in New Issue
Block a user