Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Планёрка

Внутренний инструмент: кто с кем и когда встречается. Сотрудник добавляет встречу, любой другой видит расписание на день или неделю, а занять слот, в котором кто-то из участников уже занят, система не даст.

Список встреч на день

Возможности

  • Регистрация и вход — имя, логин, пароль (хэш, сессионная кука).
  • Создание встречи — тема, дата, время начала/окончания, участники (создатель включается автоматически).
  • Просмотр всеми — списки «День» и «Неделя» показывают все встречи компании с участниками; свои встречи подсвечены жёлтой меткой.
  • Защита слота — если интервал пересекается с другой встречей любого участника, бронь отклоняется с внятным объяснением: кто занят, чем и когда (docs/conflict.png). Встречи «встык» (11:00–12:00 и 12:00–13:00) конфликтом не считаются.
  • Статистика — сколько времени и на скольких встречах провёл каждый сотрудник за неделю, плюс итоги по компании (docs/stats.png).
  • Удаление — создатель встречи может её отменить.

Как запустить

Нужен Python 3.10 или новее — либо uv, который сам поставит и Python, и зависимости. Единственная зависимость приложения — Flask. Проверено на Python 3.10 и 3.14 (тесты проходят на обоих).

Вариант 1 — uv (рекомендуется: две команды и работает)

# если uv ещё нет:
#   Linux/macOS:  curl -LsSf https://astral.sh/uv/install.sh | sh
#   Windows:      powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

uv sync                  # создаст окружение и поставит зависимости из uv.lock
uv run python app.py     # запуск

Вариант 2 — классика (venv + pip)

Linux/macOS:

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python app.py

Windows (PowerShell):

py -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python app.py

Дальше

Откройте http://127.0.0.1:5000 — попадёте на страницу входа. Зарегистрируйте пару сотрудников (в разных браузерах/вкладках инкогнито, чтобы иметь две сессии) или загрузите демо-данные — 4 сотрудника и неделя встреч, пароль у всех demo1234:

uv run python seed_demo.py      # или: python seed_demo.py (в активированном venv)

Логины демо-сотрудников: m.orlova, i.petrov, a.sokolova, p.volkov.

Тесты

uv run pytest                   # или: pip install pytest && pytest

Если что-то пошло не так

Симптом Что сделать
ModuleNotFoundError: No module named 'flask' Не активировано окружение: source .venv/bin/activate (или запускайте через uv run).
SyntaxError при старте Python старше 3.10 — проверьте python --version.
Порт 5000 занят flask --app app run --port 5001 (тем же способом — через uv run или в venv).
Хочется начать с чистой базы Остановите сервер и удалите planerka.db.
«не создалась …» при seed_demo.py Скрипт рассчитан на чистую базу — удалите planerka.db и повторите.

База данных (planerka.db) и ключ сессий (.secret_key) создаются автоматически при первом запуске рядом с app.py — ничего настраивать не нужно.

Стек и структура

Что Почему
Flask + Jinja (server-rendered) Задача — формы и списки; SPA и сборка фронтенда здесь лишние.
SQLite (stdlib sqlite3) «Простая БД»: нулевая установка, один файл planerka.db, транзакции есть.
Один CSS-файл, без JS Нативные <input type="date/time">, чекбоксы-чипсы, CSS-анимации.
app.py            # вся логика: схема БД, авторизация, встречи, конфликты, статистика
templates/        # base, login, register, day, week, stats, new
static/style.css  # дизайн-система «вокзальное табло»
test_app.py       # смоук-тесты критичных путей
seed_demo.py      # демо-данные

Модель данных

users                meetings                        meeting_participants
  id                   id                              meeting_id → meetings (CASCADE)
  name                 title                           user_id    → users
  username (unique)    starts_at "YYYY-MM-DDTHH:MM"    PK (meeting_id, user_id)
  password_hash        ends_at   (CHECK ends > starts)
                       created_by → users

Время хранится строкой ISO YYYY-MM-DDTHH:MM — сравнивается лексикографически, индекса по starts_at хватает для выборок дня/недели.

Проверка конфликта

Классическое пересечение интервалов: занято, если существующая.start < новая.end AND существующая.end > новая.start хотя бы у одного участника. Проверка и вставка выполняются одной транзакцией BEGIN IMMEDIATE, поэтому две одновременные брони одного слота не проскочат — вторая дождётся первой и получит отказ.

Статистика

Сумма длительностей встреч недели по каждому участнику (julianday(ends) − julianday(starts)), лидерборд с барами и итоговые «человеко-часы» по компании.

Осознанные допущения (по договорённости)

Это тестовое задание, а не боевой сервис — «раздельные аккаунты и доступы» условны и упрощены намеренно:

  • Авторизация условная: логин/пароль без e-mail-подтверждения, ролей и восстановления; любой может зарегистрироваться и видит все встречи (так и задумано — инструмент внутренний). Пароли при этом захэшированы, сессии подписаны секретным ключом (генерируется в .secret_key при первом запуске).
  • Без CSRF-токенов — для внутреннего инструмента на сессионных куках это первый кандидат на добавление в проде.
  • Часовые пояса: всё в наивном локальном времени сервера — один офис.
  • Встреча живёт внутри одного дня (форма даёт одну дату) — «через полночь» не бронируется.
  • Запуск дев-сервером Flask (debug=True) — для проверки задания этого достаточно.
  • Список участников — чекбоксы: удобно до пары десятков сотрудников, дальше нужен поиск.

Что добавил бы для продакшена

CSRF-токены и rate-limit на вход; WSGI-сервер (gunicorn) и debug=False; Postgres + миграции (alembic) при росте; редактирование встреч и повторяющиеся встречи; часовые пояса (UTC в базе); поиск по участникам; e-mail/календарные уведомления.


Скриншоты: docs/login.png, docs/day.png, docs/week.png, docs/stats.png, docs/conflict.png.

About

Тестовое задание: «Планёрка» — внутренний планировщик встреч (Flask + SQLite, проверка конфликтов слотов)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages