Files
manager_employees_python/src/scheduler/manager/conflict.py
T
2026-09-18 20:46:32 -04:00

122 lines
3.7 KiB
Python

from datetime import datetime
from scheduler.database import storage
from scheduler.manager.validator import (
validate_employee_can_join_shift,
validate_user_has_not_worked_more_than_five_days,
validate_user_has_not_worked_same_day,
)
SHIFTS = ("morning", "afternoon", "evening")
DAYS = ("sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday")
MAX_EMPLOYEES_PER_SHIFT = 2
def _value(value):
return value.value if hasattr(value, "value") else value
def _count_shift_employees(connection, day_of_week, shift, company_id=None):
count = storage.count_shift_employees(
connection, _value(day_of_week), _value(shift), company_id
)
if isinstance(count, dict):
return count.get("cnt", count.get("employee_count", 0))
return count
def _is_shift_full(connection, day_of_week, shift, company_id=None):
return (
_count_shift_employees(connection, day_of_week, shift, company_id)
>= MAX_EMPLOYEES_PER_SHIFT
)
def _get_user_company_id(connection, user_id):
return storage.get_user_company_id(connection, user_id)
def _get_company_employee_ids(connection, company_id):
return storage.get_company_employee_ids(connection, company_id)
def _get_shift_preferences(connection, user_id, day_of_week):
row = storage.get_weekly_preferences(connection, user_id, _value(day_of_week))
if row is None:
return list(SHIFTS)
return [row["first"], row["second"], row["third"]]
def _get_next_day(current_day):
day = _value(current_day)
if day not in DAYS:
return None
return DAYS[(DAYS.index(day) + 1) % len(DAYS)]
def _assign_shift(connection, user_id, day_of_week, shift, company_id=None):
company_id = (
company_id
if company_id is not None
else _get_user_company_id(connection, user_id)
)
if _is_shift_full(connection, day_of_week, shift, company_id):
return None
if not validate_employee_can_join_shift(
connection, user_id, _value(day_of_week), _value(shift)
):
return None
return storage.add_schedule(
connection,
user_id,
datetime.now(),
_value(day_of_week),
None,
_value(shift),
)
def detect_preferred_shift_conflict(connection, user_id, day_of_week, preferred_shift):
company_id = _get_user_company_id(connection, user_id)
return (
_is_shift_full(connection, day_of_week, preferred_shift, company_id)
or not validate_user_has_not_worked_same_day(
connection, user_id, _value(day_of_week)
)
or not validate_user_has_not_worked_more_than_five_days(connection, user_id)
)
def resolve_conflict_same_day(connection, user_id, day_of_week):
for shift in SHIFTS:
schedule = _assign_shift(connection, user_id, day_of_week, shift)
if schedule is not None:
return schedule
return None
def resolve_conflict_next_day(connection, user_id, current_day):
next_day = _get_next_day(current_day)
if next_day is None:
return None
for shift in _get_shift_preferences(connection, user_id, next_day):
schedule = _assign_shift(connection, user_id, next_day, shift)
if schedule is not None:
return schedule
return None
def resolve_missing_second_employee(connection, company_id, day_of_week, shift):
if (
_count_shift_employees(connection, day_of_week, shift, company_id)
>= MAX_EMPLOYEES_PER_SHIFT
):
return None
for user_id in _get_company_employee_ids(connection, company_id):
schedule = _assign_shift(connection, user_id, day_of_week, shift, company_id)
if schedule is not None:
return schedule
return None