Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions docs/modules/feed.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ handlers для служебных записей.

## Архитектура

- `feed/views.py` - endpoint `/feed/`, фильтрация по типам и финальная сборка
response payload.
- `feed/serializers.py` - `FeedNewsResponseSerializer`, который превращает
`news.News` в элемент ленты.
- `feed/views.py` - endpoint `/feed/` и фильтрация по типам.
- `feed/serializers.py` - `FeedItemResponseSerializer`, который превращает
`news.News` в элемент ленты формата `{type_model, content}`.
- `feed/services.py` - helpers для лайков и служебных feed-записей.
- `feed/mapping.py` - соответствие content object типам и serializers.
- `feed/constants.py` - типы моделей, для которых signals создают feed-записи.
Expand All @@ -45,14 +44,28 @@ Frontend вызывает `/feed/?type=...`.
View выбирает подходящие `news.News`, сериализует их и возвращает элементы
ленты с полями `type_model` и `content`.

Ответ использует стандартную пагинацию DRF: `count`, `next`, `previous`,
`results`. Каждый элемент `results` содержит только:

- `type_model` - тип элемента ленты;
- `content` - сериализованный объект, соответствующий этому типу.

### 2. В ленту попадает обычная новость

Если `news.News` содержит текст и относится к пользователю или проекту, лента
возвращает ее как новость.
Если `news.News` содержит текст и относится к пользователю, проекту или
партнерской программе, лента возвращает ее как новость.

Проектная новость с текстом возвращается как `type_model = "news"`, даже если
ее `content_object` - проект.

Новость партнерской программы с текстом тоже возвращается как
`type_model = "news"`. Отдельный `type_model = "partner_program"` пока не
вводится.

Служебные feed-записи партнерских программ сейчас не создаются. Если такой
сценарий понадобится, для него нужно отдельно согласовать `type_model` и
frontend-контракт.

### 3. В ленту попадает служебная запись

Служебные feed-записи создаются через `feed.services.create_news_for_model()`.
Expand All @@ -78,14 +91,17 @@ View выбирает подходящие `news.News`, сериализует
- `GET /feed/?type=news` - новости пользователей.
- `GET /feed/?type=project` - проектные новости и проектные feed-записи.
- `GET /feed/?type=vacancy` - служебные feed-записи вакансий.
- `GET /feed/?type=project|news|vacancy` - комбинированная выдача по нескольким
типам.
- `GET /feed/?type=partnerprogram` - новости партнерских программ.
- `GET /feed/?type=project|vacancy|news|partnerprogram` - комбинированная
выдача по нескольким типам.

## Ограничения и правила

- Feed читает данные из `news.News`, но не отвечает за создание обычных
project/user/program news.
- Служебная feed-запись определяется через пустой `text`.
- Новости партнерских программ с текстом отображаются как обычные новости;
отдельные служебные карточки программ в ленте пока не поддерживаются.
- Signals `feed` создают или удаляют служебные feed-записи для проектов и
вакансий. Более широкие сценарии публикации проекта остаются в модуле
`projects`.
Expand All @@ -96,6 +112,8 @@ View выбирает подходящие `news.News`, сериализует

- `/feed/?type=news` возвращает пользовательские новости;
- `/feed/?type=project` возвращает проектные новости в frontend-формате;
- `/feed/?type=partnerprogram` возвращает новости программ как
`type_model = "news"`;
- `/feed/?type=project` возвращает служебную feed-запись проекта как
`type_model = "project"`;
- `/feed/?type=vacancy` возвращает служебную feed-запись вакансии как
Expand Down
211 changes: 210 additions & 1 deletion docs/modules/partner-programs.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,212 @@
# Partner Programs

TODO
## Назначение

Модуль `partner_programs` отвечает за партнерские программы: регистрацию
участников, привязку проектов к программе, дополнительные поля заявки,
сдачу проектов на проверку, фильтрацию и выгрузки проектов программы.

Программа объединяет пользователей, проекты, новости, курсы и оценки проектов.

## Статус модуля

Модуль рабочий и используется продуктом, но пока остается архитектурно тяжелым:
значительная часть бизнес-логики находится во `views.py`, а тесты только
начинают приводиться к структуре, принятой для свежих модулей.

## Основные возможности

- список и детальная карточка партнерских программ;
- регистрация пользователя в программе;
- регистрация нового пользователя через внешнюю форму;
- просмотр материалов и связанных курсов программы;
- подача проекта в программу;
- заполнение дополнительных полей проекта в программе;
- сдача конкурсного проекта на проверку;
- список и фильтрация проектов программы для менеджеров;
- экспорт проектов и оценок;
- публикация проектов после окончания программы;
- новости программы через общий модуль `news`.

## Архитектура

- `partner_programs/models.py` - модели программ, участников, материалов,
проектов программы и дополнительных полей.
- `partner_programs/views.py` - API программы, регистрации, подачи проектов,
фильтров и экспортов.
- `partner_programs/serializers/` - request/response serializers и validation
дополнительных полей.
- `partner_programs/services/` - сервисы регистрации в программе, подачи
проектов, фильтрации проектов, публикации проектов и подготовки
Excel-выгрузок.
- `partner_programs/selectors.py` - выборки участников для аналитики и
напоминаний.
- `partner_programs/permissions.py` - проверки менеджера программы, админа и
лидера проекта.
- `partner_programs/tasks.py` - celery-задача публикации проектов после
завершения программы.
- `partner_programs/tests/` - regression-тесты API, serializers и сервисов.

## Ключевые сущности

- `PartnerProgram` - сама программа, даты регистрации, подачи и завершения,
настройки конкурсности и публикации проектов.
- `PartnerProgramUserProfile` - участие пользователя в программе и данные
регистрационной формы.
- `PartnerProgramProject` - связь проекта с программой, статус сдачи проекта и
дата сдачи.
- `PartnerProgramField` - дополнительное поле программы.
- `PartnerProgramFieldValue` - значение дополнительного поля для проекта в
программе.
- `PartnerProgramMaterial` - материал программы: ссылка или файл.

## API

- `GET /programs/` - список опубликованных программ.
- `GET /programs/?participating=1` - активные программы текущего участника.
- `GET /programs/<id>/` - детальная карточка программы.
- `GET /programs/<id>/schema/` - схема регистрационных данных программы.
- `POST /programs/<id>/register/` - регистрация текущего пользователя в
программе.
- `POST /programs/<id>/register_new/` - регистрация нового пользователя через
внешнюю форму.
- `POST /programs/<id>/set_liked/` - лайк программы.
- `POST /programs/<id>/set_viewed/` - просмотр программы.
- `GET /programs/<id>/news/` - новости программы.
- `POST /programs/<id>/news/` - создание новости программы менеджером.
- `GET /programs/<id>/projects/apply/` - данные формы подачи проекта.
- `POST /programs/<id>/projects/apply/` - подача проекта в программу.
- `POST /programs/partner-program-projects/<link_id>/submit/` - сдача проекта
на проверку.
- `PUT /projects/<project_id>/program-fields/` - обновление дополнительных
полей проекта в программе.
- `GET /programs/<id>/filters/` - доступные фильтры проектов программы.
- `POST /programs/<id>/projects/filter/` - фильтрация проектов по
дополнительным полям.
- `GET /programs/<id>/projects/` - список проектов программы.
- `GET /programs/<id>/export-projects/` - Excel-выгрузка проектов.
- `GET /programs/<id>/export-rates/` - Excel-выгрузка оценок.

## Основные сценарии

### 1. Пользователь смотрит список программ

Список `/programs/` показывает только программы с `draft = False`.
Для авторизованного пользователя response дополнительно показывает признак
`is_user_member`.

Фильтр `participating=1` возвращает только активные программы, в которых
текущий пользователь является участником.

### 2. Пользователь открывает программу

Детальная карточка возвращает разные поля для участника и не-участника.
Если пользователь авторизован, просмотр программы фиксируется через общий
механизм просмотров.

Связанные курсы программы возвращаются в поле `courses`; для каждого курса
указывается `is_available`.

### 3. Пользователь регистрируется в программе

`POST /programs/<id>/register/` создает `PartnerProgramUserProfile` для текущего
пользователя и сохраняет переданные данные формы в `partner_program_data`.

Если срок регистрации завершен или пользователь уже зарегистрирован, API
возвращает ошибку.

### 4. Пользователь подает проект в программу

Участник программы открывает форму `/programs/<id>/projects/apply/`, получает
список дополнительных полей и отправляет проект.

При успешной подаче создаются:

- черновой непубличный `Project`;
- связь `PartnerProgramProject`;
- значения `PartnerProgramFieldValue`;
- связь `PartnerProgramUserProfile.project` с новым проектом.

Подача запрещена не-участнику, после дедлайна, при повторной подаче проекта и
при некорректных дополнительных полях.

### 5. Лидер обновляет поля проекта в программе

`PUT /projects/<project_id>/program-fields/` обновляет значения дополнительных
полей проекта.

Изменять значения может только лидер проекта. Для конкурсной программы после
сдачи проекта на проверку редактирование блокируется.

### 6. Лидер сдает проект на проверку

`POST /programs/partner-program-projects/<link_id>/submit/` переводит связь
проекта с программой в `submitted = True` и заполняет `datetime_submitted`.

Сдача доступна только лидеру проекта, только для конкурсных программ и только
до дедлайна подачи проектов.

### 7. Менеджер работает с проектами программы

Менеджер или администратор программы может:

- смотреть список проектов программы;
- получать список доступных фильтров;
- фильтровать проекты по значениям дополнительных полей;
- выгружать проекты и оценки в Excel.

## Связи с другими модулями

- `projects` - проекты подаются в программу и связываются через
`PartnerProgramProject`.
- `users` - участники и менеджеры программы.
- `news` - новости программы создаются и читаются через общий news API.
- `feed` - текстовые новости программы могут попадать в общую ленту как
`type_model = "news"`.
- `courses` - курс может быть связан с программой и доступен участникам
программы.
- `project_rates` - оценки проектов используются в выгрузке результатов.
- `mailing` / `vacancy.tasks.send_email` - уведомления после регистрации в
программе.
- `files` - материалы программы могут ссылаться на `UserFile`.

## Ограничения и правила

- Дополнительные поля программы задаются через `PartnerProgramField`.
- Значения дополнительных полей хранятся в `PartnerProgramFieldValue`.
- После сдачи проекта в конкурсной программе значения полей редактировать
нельзя.
- Служебные feed-карточки программ пока не поддерживаются; новости программ в
feed отображаются как обычные новости.
- Основной API-код пока сосредоточен во `views.py`; перед крупным рефакторингом
нужно зафиксировать больше regression-тестов.

## Тесты

Текущие regression-тесты проверяют:

- validation дополнительных полей: `text`, `textarea`, `checkbox`, `select`,
`radio`, `file`;
- список программ и фильтр `participating`;
- регистрацию текущего пользователя в программе;
- регистрацию нового пользователя через внешнюю форму;
- запрет повторной регистрации и регистрации после дедлайна;
- detail программы с курсами для участника и не-участника;
- подачу проекта участником программы или менеджером программы;
- запрет повторной подачи проекта тем же лидером;
- запрет подачи проекта не-участником, после дедлайна, с дублями полей,
незаполненными обязательными полями и полями другой программы;
- обновление дополнительных полей проекта лидером;
- запрет обновления полей не-лидером и после сдачи конкурсного проекта;
- сдачу проекта на проверку;
- запрет сдачи проекта не-лидером, после дедлайна и для неконкурсной программы;
- список фильтров программы;
- фильтрацию проектов программы по дополнительным полям;
- список проектов программы для менеджера;
- Excel-выгрузку проектов программы, включая режим `only_submitted`;
- запрет выгрузки проектов пользователем без прав менеджера;
- Excel-выгрузку оценок проектов программы;
- подготовку данных выгрузки оценок, когда критерии есть, но оценок еще нет;
- базовые permissions для менеджера программы, staff-пользователя,
постороннего пользователя, anonymous и лидера проекта;
- публикацию проектов после завершения программы.
3 changes: 1 addition & 2 deletions feed/mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
from vacancy.models import Vacancy
from vacancy.serializers import VacancyDetailSerializer

CONTENT_OBJECT_MAPPING: dict[str, str | None] = {
CONTENT_OBJECT_MAPPING: dict[str, str] = {
Project.__name__.lower(): "project",
CustomUser.__name__.lower(): "news",
"partnerprogram": None,
Vacancy.__name__.lower(): "vacancy",
}

Expand Down
Loading
Loading