Skip to content

Commit b573898

Browse files
authored
Merge pull request #660 from PROCOLLAB-github/feature/program-participation-policy
Добавить правила участия в программе
2 parents 9102c85 + 86c5edc commit b573898

6 files changed

Lines changed: 656 additions & 12 deletions

File tree

docs/case-championship-domain.md

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,18 @@ Program
4848
**Связи.** Имеет регистрации, заявки и сдачи; связывается с менеджерами,
4949
экспертами, курсами, материалами и legacy-проектами.
5050

51-
**Что хранит.** Описание и изображения, даты начала и завершения, дедлайны
52-
регистрации, legacy-дедлайн подачи проектов и дедлайн оценки, схему
53-
регистрационных данных, настройки конкурсности и доступности проектов.
51+
**Что хранит.** Описание и изображения, даты начала и завершения, дедлайн
52+
регистрации, отдельный дедлайн Application, legacy-дедлайн подачи проектов и
53+
дедлайн оценки, схему регистрационных данных, настройки конкурсности,
54+
доступности проектов, формата участия и размера команды.
5455

5556
**Что не должна хранить.** Ответы конкретного участника, состав команды,
5657
решение или оценку конкретной работы.
5758

5859
**Текущее состояние.** Реализована как `partner_programs.PartnerProgram`.
59-
Специальных настроек формата участия, минимального/максимального размера
60-
команды, дедлайна заявки и отдельного дедлайна решения пока нет.
60+
Формат участия, минимальный/максимальный размер команды и отдельный дедлайн
61+
Application хранятся в модели и защищены validation/constraints. Enforcement
62+
в Application/team service и отдельный дедлайн решения пока отсутствуют.
6163

6264
### Registration
6365

@@ -615,6 +617,7 @@ Registration.
615617
| Область | Уже реализовано | Частично | Отсутствует | Комментарий |
616618
|---|---|---|---|---|
617619
| Registration | `PartnerProgramUserProfile`, register endpoints, `participating=1`, deadline и uniqueness | Статус Registration и связь с новым flow | Отдельная модель/явный contract Registration | Application create не требует Registration |
620+
| Program participation policy | Форматы `individual_only/team_only/individual_or_team`, размеры Team, application deadline, model/DB validation и admin | Helpers пока вызываются только явно | Enforcement в Application/team service и публичный API | Default `individual_only`, размеры и deadline существующих программ остаются `null` |
618621
| Application model | Program, user, created_by, participation_mode, form_data, nullable Project, timestamps, partial unique constraint | Ownership по-прежнему опирается на Application.user | returned, snapshot, review reason | Default participation_mode временно individual |
619622
| Application API | create/my/detail/patch/submit/withdraw, idempotency create/submit/withdraw, scoped throttle create | Owner/staff access | review endpoints, manager access, deadline/form/team checks | 404 my application корректно означает отсутствие записи |
620623
| Application statuses | Шесть статусов и timestamps submit/approve/reject/withdraw | Переходы draft/submit/withdraw | `returned`, return/approve/reject/cancel actions | approved/rejected могут появиться только вне нового API, например через admin |
@@ -628,7 +631,7 @@ Registration.
628631
| Notification | Email и chat WebSocket infrastructure | Mailing logs не являются inbox | Доменная Notification и пользовательский центр | Не входит в первый Team PR |
629632
| Evaluation | `Criteria`, `ProjectScore`, `ProjectExpertAssignment` для legacy Project | Эксперты и распределенное оценивание проекта | Evaluation по Submission | Нельзя смешивать с ProjectScore без миграции |
630633
| Result | Legacy scores и пользовательские достижения существуют отдельно | Нет единого результата заявки | Result/ranking/publication contract | Требует решения об источнике итогов |
631-
| Deadlines | Registration и legacy project submission/evaluation dates | Поля Program можно переиспользовать только после решения semantics | Проверки в Application/Submission API, отдельные application/solution deadlines | Сейчас новый flow позволяет действия после дедлайнов |
634+
| Deadlines | Registration, отдельный Application deadline и legacy project submission/evaluation dates | Application helper не подключен к endpoints | Проверки в Application/Submission API и отдельный solution deadline | Application deadline не имеет fallback на legacy-поля |
632635
| Permissions | Owner/staff для новых API; manager/expert permissions есть для legacy flow | Staff имеет расширенный доступ | Captain/member, manager и expert permissions для новых сущностей | Нужен общий domain permission layer |
633636
| Constraints | Registration uniqueness; active individual Application; Team one-to-one/member/captain constraints; Submission version; Project collaborators | Captain/member validation есть только внутри одной Team | Cross-team active participation и team size | Cross-table race требует транзакционного service |
634637
| Admin | PartnerProgram, Registration, Application, Team, TeamMember, Submission, Project, Invite и legacy evaluation зарегистрированы | Admin позволяет ручную диагностику | TeamInvite/Evaluation admin | Admin не заменяет transition services |
@@ -683,12 +686,12 @@ Registration.
683686
| Team и TeamMember | Модели, admin, constraints и tests реализованы | Добавить транзакционный service и публичный API | P0 | Application/team invariants |
684687
| Только зарегистрированный создает Application | Не проверяется | Domain service должен проверять PartnerProgramUserProfile | P0 | Application eligibility and lifecycle |
685688
| Одна активная заявка на пользователя с учетом Team | Constraint покрывает только `Application.user` | Транзакционная проверка индивидуальных и командных участий | P0 | Application/team invariants |
686-
| Валидация команды перед submit | Есть модель Team, но нет program policy/service | Настройки формата/размера Program и submit validation | P0 | Program participation policy |
689+
| Валидация команды перед submit | Team и Program policy реализованы | Транзакционная проверка accepted-состава и формата перед submit | P0 | Application/team invariants |
687690
| Captain-only actions | Captain хранится, endpoints Team не учитывают | Team-aware permissions для Application и Submission | P0 | Team permissions |
688691
| Team API | Отсутствует | CRUD ограниченного MVP, members, leave/transfer captain | P1 | Team API |
689692
| Полный lifecycle Application | Нет returned/review actions | Добавить return/approve/reject/cancel с reason/audit | P1 | Application review API |
690693
| TeamInvite | Есть только Project Invite | Отдельные token/email/user invites и идемпотентный accept | P1 | TeamInvite model and API |
691-
| Application deadlines | Новый API их не проверяет | Зафиксировать поля Program и проверять create/edit/submit/withdraw | P0 | Application eligibility and lifecycle |
694+
| Application deadlines | Отдельное поле и helper Program реализованы, API их не проверяет | Проверять create/edit/submit/withdraw без fallback на legacy deadlines | P0 | Application eligibility and lifecycle |
692695
| Submission deadlines и роли | Новый API не проверяет сроки, manager/expert/team | Добавить policy и единый permission layer | P1 | Submission lifecycle hardening |
693696
| Return/finalize Submission | Статусы есть, действий нет | Организаторские endpoints и audit fields/reasons | P1 | Submission review API |
694697
| Semantics версий Submission | Несколько записей и auto-next уже есть | Определить current/final/evaluated version и поведение after return | P1 | Submission version workflow |
@@ -704,8 +707,9 @@ Registration.
704707
1. **`feature/application-team-model` — реализовано.** Добавлены
705708
`participation_mode`, Team и TeamMember с миграцией, admin, модельными
706709
ограничениями и тестами; без API.
707-
2. **Program participation policy.** Зафиксировать разрешенные форматы,
708-
минимальный/максимальный размер команды и реальные дедлайны Application.
710+
2. **`feature/program-participation-policy` — реализовано.** Добавлены
711+
разрешенные форматы, минимальный/максимальный размер команды и отдельный
712+
дедлайн Application; enforcement в API намеренно не включен.
709713
3. **Application/team invariants.** Ввести транзакционный service для проверки
710714
Registration, конфликтов активного участия, капитана и accepted-состава.
711715
4. **Team permissions and API.** Добавить owner/captain/member/manager access,
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Program Participation Policy
2+
3+
## Назначение
4+
5+
Policy хранится в `PartnerProgram` и задает допустимый формат участия,
6+
границы размера команды и отдельный дедлайн подачи `Application`. Эти данные
7+
станут источником истины для будущего транзакционного сервиса создания и
8+
отправки заявок.
9+
10+
В текущем изменении policy валидируется на уровне модели и базы данных, но еще
11+
не применяется существующими Application endpoints. Публичные Program
12+
serializers также намеренно не расширены.
13+
14+
## Формат участия
15+
16+
Поле `participation_format` поддерживает три значения:
17+
18+
| Значение | Разрешенные финальные `Application.participation_mode` |
19+
|---|---|
20+
| `individual_only` | Только `individual` |
21+
| `team_only` | Только `team` |
22+
| `individual_or_team` | `individual` и `team` |
23+
24+
`undecided` остается допустимым состоянием черновика Application, но не
25+
считается разрешенным финальным форматом. Метод
26+
`allows_participation_mode(mode)` возвращает `False` и для `undecided`, и для
27+
неизвестного значения.
28+
29+
Runtime default — `individual_only`. Он сохраняет поведение существующих
30+
программ и не включает командные заявки без явной настройки организатора.
31+
После миграции все существующие строки получают это значение.
32+
33+
## Размер команды
34+
35+
`team_min_size` и `team_max_size` применяются только к `team_only` и
36+
`individual_or_team`. Для этих форматов оба поля обязательны, минимальный
37+
размер не может быть меньше двух, а максимальный — меньше минимального.
38+
39+
Для `individual_only` оба значения должны быть `null`. Существующим программам
40+
произвольные границы не назначаются.
41+
42+
Размер команды в будущем рассчитывается только по `TeamMember` со статусом
43+
`accepted`. Капитан имеет accepted-запись `TeamMember` и входит в размер
44+
команды. Фактическое число участников нельзя надежно проверить constraint-ом
45+
одной таблицы: оно зависит от связанных строк и конкурентных изменений.
46+
Поэтому эту проверку должен выполнять будущий транзакционный domain service
47+
непосредственно перед submit Application.
48+
49+
## Дедлайн Application
50+
51+
`datetime_application_ends` — nullable datetime отдельного процесса заявки.
52+
Он не переиспользует и не меняет semantics следующих legacy-полей:
53+
54+
- `datetime_registration_ends`;
55+
- `datetime_project_submission_ends`;
56+
- `datetime_evaluation_ends`.
57+
58+
Значение `null` означает, что отдельный дедлайн Application не настроен. Метод
59+
`is_application_deadline_passed(at=None)` в таком случае возвращает `False`.
60+
Fallback на регистрацию или сдачу проекта намеренно отсутствует: будущий
61+
domain service должен явно определить поведение при `null`.
62+
63+
## Validation и database constraints
64+
65+
`PartnerProgram.clean()` привязывает русскоязычные ошибки к
66+
`team_min_size`/`team_max_size` и проверяет соответствие размеров выбранному
67+
формату.
68+
69+
Database constraints дополнительно гарантируют:
70+
71+
- каждый заданный размер не меньше двух;
72+
- `team_max_size >= team_min_size`, когда заданы оба значения;
73+
- у `individual_only` оба размера равны `null`;
74+
- у форматов с командами оба размера заданы.
75+
76+
Constraints защищают данные при обходе model validation, но не проверяют
77+
фактический состав `Team`.
78+
79+
## Текущие ограничения и следующий шаг
80+
81+
Существующие Application API, Team API и legacy registration/project flow не
82+
изменены. Policy пока не блокирует create/edit/submit Application, не проверяет
83+
Registration и не разрешает конфликты участия между командами.
84+
85+
Следующий PR должен добавить транзакционный Application/team service. Перед
86+
submit он использует policy для проверки Registration, финального
87+
`participation_mode`, accepted-состава Team и дедлайна без изменения legacy
88+
дедлайнов.

partner_programs/admin.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,20 +229,28 @@ class Meta:
229229

230230
inlines = [PartnerProgramMaterialInline, PartnerProgramFieldInline]
231231
form = PartnerProgramAdminForm
232-
list_display = ("id", "name", "tag", "city", "datetime_created")
232+
list_display = (
233+
"id",
234+
"name",
235+
"tag",
236+
"city",
237+
"participation_format",
238+
"datetime_created",
239+
)
233240
list_display_links = (
234241
"id",
235242
"name",
236243
"tag",
237244
"city",
245+
"participation_format",
238246
"datetime_created",
239247
)
240248
search_fields = (
241249
"name",
242250
"city",
243251
"tag",
244252
)
245-
list_filter = ("city",)
253+
list_filter = ("city", "participation_format")
246254

247255
autocomplete_fields = ("managers",)
248256
date_hierarchy = "datetime_started"
@@ -279,6 +287,16 @@ class Meta:
279287
)
280288
},
281289
),
290+
(
291+
"Участие и заявки",
292+
{
293+
"fields": (
294+
"participation_format",
295+
("team_min_size", "team_max_size"),
296+
"datetime_application_ends",
297+
)
298+
},
299+
),
282300
("Менеджеры программы", {"fields": ("managers",)}),
283301
("Служебная информация", {"fields": ("datetime_created", "datetime_updated")}),
284302
)

0 commit comments

Comments
 (0)