Веб-приложение для отслеживания статуса откликов на вакансии в процессе поиска работы.
Реализовано в формате канбан-доски с Drag & Drop, историей изменений статусов и админ-панелью.
- Технологический стек
- Функциональность
- Модели данных
- API Endpoints
- Быстрый старт
- Конфигурация
- Миграции базы данных
- Тестирование
- Лицензия
| Компонент | Технология |
|---|---|
| Бэкенд | Python 3.14+, FastAPI, SQLAlchemy 2.0 (async), Alembic |
| База данных | PostgreSQL 16 (asyncpg) |
| Кэш/сессии | Redis 7 |
| Аутентификация | JWT (access + refresh tokens), bcrypt (passlib) |
| Фронтенд | HTML, CSS, JavaScript (vanilla), Jinja2-шаблоны, Chart.js |
| Инфраструктура | Docker, Docker Compose |
| Защита | Yandex SmartCaptcha, rate limiting |
| Тестирование | pytest, pytest-asyncio, httpx, aiosqlite |
- Регистрация и вход с JWT-токенами (access + refresh)
- HttpOnly cookies для безопасного хранения токенов
- Возможность выйти с одного устройства или со всех устройств
- Автоматическое обновление refresh-токенов (rotation)
- Хранение активных сессий в Redis
- CRUD заявок: компания, название вакансии, контакты, URL вакансии, комментарии
- Статусы заявок:
created— созданаhr_interview— HR-собеседованиеtech_interview— техническое собеседованиеoffer— офферrejected— отказauto_reject— автоматический отказignored— игнорировано
- История изменения статусов с временными метками
- Drag & Drop на канбан-доске для быстрого изменения статуса
- Фильтрация заявок по периодам:
today,yesterday,week,month,old - Фильтрация по произвольному интервалу дат
- Автоматический перевод старых заявок в статус
ignored(настраиваемый период в днях)
- Отдельная страница
/statisticsс аналитикой по откликам - Фильтрация по произвольному диапазону дат (по умолчанию — последние 6 месяцев)
- Счётчики: всего откликов, активных, отказов, автоотказов, в игноре, офферов
- Воронка откликов — визуализация прохождения заявок по этапам:
created → hr_interview → tech_interview → offer, с процентами конверсии - Время между этапами — столбчатая диаграмма и детальная таблица со средним, медианой, минимумом и максимумом в днях
- Графики построены на Chart.js
- Просмотр всех пользователей с сортировкой
- Назначение/снятие роли администратора (только суперадмин)
- Удаление пользователей
- Защита:
- Суперадмина нельзя удалить
- Последнего администратора нельзя удалить (чтобы не потерять доступ)
- Страница
/adminс веб-интерфейсом
- Yandex SmartCaptcha на регистрацию и вход
- Rate limiting на endpoint логина (10 попыток за 5 минут)
- Валидация пароля: минимум 8 символов, заглавные/строчные буквы, цифры, только ASCII
- Режим
ONLY_ALLOWED_USERNAMES_MODE— доступ только по белому списку логинов - JWT с проверкой подписи и срока действия
- Защита от удаления первой записи истории статуса
| Поле | Тип | Описание |
|---|---|---|
id |
int | Первичный ключ |
login |
str(50) | Уникальный логин пользователя |
hashed_password |
str(255) | Хеш пароля (bcrypt) |
is_admin |
bool | Флаг администратора |
created_at |
datetime | Дата регистрации |
| Поле | Тип | Описание |
|---|---|---|
id |
int | Первичный ключ |
user_id |
FK -> User | Владелец заявки |
company_name |
str(255) | Название компании |
vacancy_name |
str(255) | Название вакансии |
contacts |
str(500) | Контакты (опционально) |
comments |
Text | Комментарии (опционально) |
vacancy_url |
str(500) | URL вакансии (опционально) |
status |
Enum | Текущий статус |
created_at |
datetime | Дата создания |
updated_at |
datetime | Дата последнего обновления |
| Поле | Тип | Описание |
|---|---|---|
id |
int | Первичный ключ |
application_id |
FK -> Application | Заявка |
status |
Enum | Статус на момент записи |
changed_at |
datetime | Дата изменения |
| Метод | Путь | Описание |
|---|---|---|
POST |
/register |
Регистрация нового пользователя |
POST |
/login |
Вход в систему |
POST |
/refresh |
Обновление access/refresh токенов |
POST |
/logout |
Выход из текущей сессии |
POST |
/logout-all |
Выход из всех сессий |
| Метод | Путь | Описание |
|---|---|---|
GET |
/ |
Список пользователей (admin) |
GET |
/me |
Информация о текущем пользователе |
DELETE |
/me |
Удаление своего аккаунта |
DELETE |
/{user_id} |
Удаление пользователя (admin) |
PATCH |
/{user_id}/admin |
Назначение/снятие admin (суперадмин) |
| Метод | Путь | Описание |
|---|---|---|
GET |
/ |
Список заявок с фильтрацией |
POST |
/ |
Создание заявки |
GET |
/{id} |
Заявка по ID |
PATCH |
/{id} |
Обновление заявки |
DELETE |
/{id} |
Удаление заявки |
GET |
/{id}/history |
История изменения статусов |
DELETE |
/{id}/history/{history_id} |
Удаление записи истории |
POST |
/auto-ignore |
Авто-игнорирование старых заявок |
| Метод | Путь | Описание |
|---|---|---|
GET |
/ |
Главная страница (HTML) |
GET |
/api/statistics |
Статистика текущего пользователя (параметры: date_from, date_to) |
GET |
/statistics |
Страница статистики (HTML) |
GET |
/admin |
Админ-панель (HTML, только admin) |
GET |
/docs |
Swagger-документация (только dev) |
GET |
/redoc |
ReDoc-документация (только dev) |
# 1. Клонировать репозиторий
git clone https://github.com/Duzer61/career_tracker.git
cd career_tracker
# 2. Скопировать и настроить .env
cp .env.example .env
# Отредактировать .env под свои параметры
# 3. Запустить
docker compose up -dПриложение будет доступно по адресу: http://localhost:8000
Требования: Python 3.14+, PostgreSQL, Redis
# 1. Установить uv (если ещё не установлен)
pip install uv
# 2. Создать виртуальное окружение и установить зависимости
uv venv
source .venv/bin/activate
uv pip install -e .
# 3. Настроить .env (пример в .env.example)
# 4. Применить миграции
alembic upgrade head
# 5. Запустить
python main.pyВсе настройки задаются через переменные окружения (файл .env).
Подробный пример — в .env.example.
| Переменная | Описание |
|---|---|
POSTGRES_* |
Параметры подключения к PostgreSQL |
REDIS_* |
Параметры подключения к Redis |
SECRET_KEY |
Ключ для подписи JWT |
ALGORITHM |
Алгоритм JWT (по умолчанию HS256) |
ACCESS_TOKEN_EXP_MINUTES |
Время жизни access-токена (в минутах) |
REFRESH_TOKEN_EXP_DAYS |
Время жизни refresh-токена (в днях) |
ENVIRON |
Окружение: dev или prod |
SMARTCAPTCHA_* |
Ключи Yandex SmartCaptcha |
ONLY_ALLOWED_USERNAMES_MODE |
Включить режим белого списка логинов |
ALLOWED_USERNAMES |
Список разрешённых логинов через запятую |
SUPERADMIN_LOGIN |
Логин суперадминистратора |
AUTO_IGNORE_DAYS |
Через сколько дней заявка автоматически игнорируется |
Управление миграциями — через Alembic.
# Создать новую миграцию
alembic revision --autogenerate -m "описание изменений"
# Применить все миграции
alembic upgrade head
# Откатить на одну миграцию назад
alembic downgrade -1При запуске через Docker миграции применяются автоматически.
Проект использует pytest с асинхронными тестами.
Для тестов используется SQLite in-memory вместо PostgreSQL и in-memory mock вместо Redis.
# Запустить все тесты
pytest -v
# Запустить с отчётом о покрытии
pytest --cov=app -vВ тестовом окружении:
- Суперадмин:
superadmin - Redis заменяется на
InMemoryRedisMock - PostgreSQL заменяется на
sqlite+aiosqlite:///:memory: - Captcha отключена
Проект распространяется под лицензией MIT. Подробнее — в файле LICENSE.