|
1 | 1 | from random import sample |
2 | 2 |
|
| 3 | +from django.db import transaction |
| 4 | +from django.utils import timezone |
3 | 5 | from django.contrib.auth import get_user_model |
4 | 6 |
|
| 7 | +from rest_framework.exceptions import ValidationError |
| 8 | + |
5 | 9 | from partner_programs.models import PartnerProgram, PartnerProgramUserProfile |
6 | 10 | from projects.constants import RECOMMENDATIONS_COUNT |
7 | 11 | from projects.models import Project, ProjectLink, Achievement |
| 12 | +from users.models import CustomUser |
8 | 13 |
|
9 | 14 | User = get_user_model() |
10 | 15 |
|
@@ -87,14 +92,49 @@ def update_links(links, pk): |
87 | 92 | ) |
88 | 93 |
|
89 | 94 |
|
| 95 | +@transaction.atomic |
90 | 96 | def update_partner_program( |
91 | | - partner_program_id: int, user: "User", instance: "Project" |
| 97 | + program_id: int, |
| 98 | + user: CustomUser, |
| 99 | + instance: Project, |
92 | 100 | ) -> None: |
93 | | - if partner_program_id: |
94 | | - partner_program = PartnerProgram.objects.get(pk=partner_program_id) |
95 | | - partner_program_profile = PartnerProgramUserProfile.objects.get( |
96 | | - user=user, |
97 | | - partner_program=partner_program, |
98 | | - ) |
99 | | - partner_program_profile.project = instance |
100 | | - partner_program_profile.save() |
| 101 | + """ |
| 102 | + According to the current logic, 1 user project can be linked to only 1 program. |
| 103 | + The user cannot select a ready program, but can edit a project with a ready program |
| 104 | + (if the time period allows access). |
| 105 | + If he changes the program (completed), he will not be able to return it. |
| 106 | + """ |
| 107 | + if program_id is not None: |
| 108 | + # If the user removes the tag, frontend sends `int -> 0` (id == 0 cannot exist). |
| 109 | + if program_id == 0: |
| 110 | + clear_project_existing_from_profile(user, instance) |
| 111 | + else: |
| 112 | + partner_program = PartnerProgram.objects.get(pk=program_id) |
| 113 | + existing_program_id: int | None = clear_project_existing_from_profile(user, instance) |
| 114 | + |
| 115 | + if ( |
| 116 | + partner_program.datetime_finished < timezone.now() |
| 117 | + and (existing_program_id != program_id) |
| 118 | + ): |
| 119 | + raise ValidationError({"error": "Cannot select a completed program."}) |
| 120 | + |
| 121 | + partner_program_profile = PartnerProgramUserProfile.objects.get( |
| 122 | + user=user, |
| 123 | + partner_program=partner_program, |
| 124 | + ) |
| 125 | + partner_program_profile.project = instance |
| 126 | + partner_program_profile.save() |
| 127 | + |
| 128 | + |
| 129 | +def clear_project_existing_from_profile(user, instance) -> None | int: |
| 130 | + """Remove project from `PartnerProgramUserProfile` instance.""" |
| 131 | + existing_program_profile = ( |
| 132 | + PartnerProgramUserProfile.objects |
| 133 | + .select_related("partner_program") |
| 134 | + .filter(user=user, project=instance) |
| 135 | + .first() |
| 136 | + ) |
| 137 | + if existing_program_profile: |
| 138 | + existing_program_profile.project = None |
| 139 | + existing_program_profile.save() |
| 140 | + return existing_program_profile.partner_program.id |
0 commit comments