122 lines
3.7 KiB
Python
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
|