/
Soitch
/
vacation-schedule
Обзор
Документация
Войти
/
Soitch
/
vacation-schedule
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/validators.py
115 строк
6 KB
Soitch
draft
12 дек 2025, 00:12
12 дек 2025, 00:12
5b3d7e2
Код
Авторство
О чём код?
""" Валидаторы для модуля отпусков. """ from src.utils import is_finite, parse_date, calculate_working_days, is_working_day, round2 from datetime import date, timedelta from src.config import ( MAX_VACATION_DAYS_PER_YEAR, MIN_VACATION_DURATION, MAX_VACATION_DURATION, MAX_PLANNING_MONTHS, MIN_NOTICE_DAYS, MAX_TEAM_SIZE, MAX_CONCURRENT_VACATIONS, MIN_WORK_EXPERIENCE, MAX_CARRYOVER_DAYS, MIN_VACATION_INTERVAL, MAX_SALARY, MAX_VACATION_PERCENTAGE ) def validate_positive_number(name: str, value: float, min_inclusive: float, max_inclusive: float) -> None: """Валидация положительного числа в заданном диапазоне.""" if not is_finite(value): raise ValueError(f"{name}: значение не является конечным числом.") if value < min_inclusive: raise ValueError(f"{name}: значение должно быть ≥ {min_inclusive}.") if value > max_inclusive: raise ValueError(f"{name}: значение слишком велико (>{max_inclusive}).") def validate_int_range(name: str, value: int, min_inclusive: int, max_inclusive: int) -> None: """Валидация целого числа в заданном диапазоне.""" if not isinstance(value, int): raise ValueError(f"{name}: значение должно быть целым числом.") if value < min_inclusive or value > max_inclusive: raise ValueError(f"{name}: значение должно быть в диапазоне [{min_inclusive}; {max_inclusive}].") def validate_date_string(name: str, date_str: str) -> date: """Валидация строки с датой.""" parsed_date = parse_date(date_str) if parsed_date is None: raise ValueError(f"{name}: неверный формат даты. Ожидается YYYY-MM-DD.") return parsed_date # Готовые профили проверок def check_vacation_days(x: int) -> None: """Проверка количества дней отпуска.""" validate_int_range("vacation_days", x, MIN_VACATION_DURATION, MAX_VACATION_DURATION) def check_planning_months(x: int) -> None: """Проверка периода планирования.""" validate_int_range("planning_months", x, 1, MAX_PLANNING_MONTHS) def check_notice_days(x: int) -> None: """Проверка срока уведомления.""" validate_int_range("notice_days", x, MIN_NOTICE_DAYS, 365) def check_team_size(x: int) -> None: """Проверка размера команды.""" validate_int_range("team_size", x, 1, MAX_TEAM_SIZE) def check_concurrent_vacations(x: int) -> None: """Проверка количества одновременных отпусков.""" validate_int_range("concurrent_vacations", x, 1, MAX_CONCURRENT_VACATIONS) def check_work_experience(x: int) -> None: """Проверка рабочего стажа.""" validate_int_range("work_experience_days", x, MIN_WORK_EXPERIENCE, 36500) # 100 лет def check_carryover_days(x: int) -> None: """Проверка переносимых дней отпуска.""" validate_int_range("carryover_days", x, 0, MAX_CARRYOVER_DAYS) def check_vacation_interval(x: int) -> None: """Проверка интервала между отпусками.""" validate_int_range("vacation_interval", x, MIN_VACATION_INTERVAL, 365) def check_vacation_percentage(x: float) -> None: """Проверка процента оплаты отпуска.""" validate_positive_number("vacation_percentage", x, 0.0, MAX_VACATION_PERCENTAGE) def check_daily_salary(x: float) -> None: """Проверка дневного оклада.""" validate_positive_number("daily_salary", x, 0.0, MAX_SALARY / 22) def validate_vacation_dates(start_date_str: str, end_date_str: str) -> Tuple[date, date]: """Валидация дат начала и окончания отпуска.""" start_date = validate_date_string("start_date", start_date_str) end_date = validate_date_string("end_date", end_date_str) if start_date > end_date: raise ValueError("Дата начала отпуска не может быть позже даты окончания") today = date.today() if start_date < today: raise ValueError("Дата начала отпуска не может быть в прошлом") # Проверка минимального срока уведомления min_start_date = today + timedelta(days=MIN_NOTICE_DAYS) if start_date < min_start_date: raise ValueError(f"Отпуск должен быть запланирован минимум за {MIN_NOTICE_DAYS} дней") # Проверка максимальной продолжительности duration = (end_date - start_date).days + 1 if duration > MAX_VACATION_DURATION: raise ValueError(f"Продолжительность отпуска не может превышать {MAX_VACATION_DURATION} дней") if duration < MIN_VACATION_DURATION: raise ValueError(f"Продолжительность отпуска должна быть не менее {MIN_VACATION_DURATION} дня") return start_date, end_date def calculate_working_vacation_days(start_date: date, end_date: date) -> int: """Рассчитывает количество рабочих дней в отпуске.""" return calculate_working_days(start_date, end_date)