refactor(reports): модульное разделение excel_exporter на styles, calculators и билдеры отчетов
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
===============================================================================
|
||||
FILE: services/reports/calculators.py
|
||||
ROLE: Расчет баланса рабочего времени, обеденного перерыва и отклонений от нормы.
|
||||
===============================================================================
|
||||
"""
|
||||
|
||||
import pandas as pd
|
||||
|
||||
|
||||
def calculate_deviation(time_in_building_str, reason="", norm_hours=8, lunch_minutes=30):
|
||||
"""
|
||||
Расчет отклонения от нормы.
|
||||
Для удаленщиков при наличии физического времени в здании вычисляется реальное отклонение.
|
||||
"""
|
||||
reason_clean = str(reason).strip().lower() if pd.notna(reason) else ""
|
||||
is_remote = "удален" in reason_clean or "дистанцион" in reason_clean
|
||||
|
||||
has_building_time = isinstance(time_in_building_str, str) and time_in_building_str not in ['00:00', '0', '', 'None', 'nan', 'NaN']
|
||||
|
||||
# Если есть уважительная причина (больничный, отпуск, командировка и т.д.) не удаленка
|
||||
if reason_clean != "" and not is_remote:
|
||||
return "0:00"
|
||||
|
||||
# Если удаленщик работал исключительно из дома (00:00 в здании)
|
||||
if is_remote and not has_building_time:
|
||||
return "0:00"
|
||||
|
||||
# Если сотрудника не было в здании и нет уважительной причины
|
||||
if not has_building_time:
|
||||
return f"-{norm_hours}:00"
|
||||
|
||||
try:
|
||||
parts = time_in_building_str.strip().split(':')
|
||||
hh = int(parts[0])
|
||||
mm = int(parts[1]) if len(parts) > 1 else 0
|
||||
total_in_building_minutes = hh * 60 + mm
|
||||
|
||||
if total_in_building_minutes == 0:
|
||||
return "0:00" if is_remote else f"-{norm_hours}:00"
|
||||
|
||||
work_minutes = max(0, total_in_building_minutes - lunch_minutes)
|
||||
norm_minutes = norm_hours * 60
|
||||
diff = work_minutes - norm_minutes
|
||||
|
||||
if diff == 0:
|
||||
return "0:00"
|
||||
|
||||
sign = "-" if diff < 0 else ""
|
||||
abs_diff = abs(diff)
|
||||
res_hh = abs_diff // 60
|
||||
res_mm = abs_diff % 60
|
||||
|
||||
return f"{sign}{res_hh}:{res_mm:02d}"
|
||||
except Exception:
|
||||
return "0:00" if is_remote else f"-{norm_hours}:00"
|
||||
Reference in New Issue
Block a user