diff --git a/taiga/projects/serializers.py b/taiga/projects/serializers.py index 28e3593c..3c649ece 100644 --- a/taiga/projects/serializers.py +++ b/taiga/projects/serializers.py @@ -76,7 +76,6 @@ class TaskStatusSerializer(ValidateDuplicatedNameInProjectMixin): class BasicTaskStatusSerializerSerializer(serializers.ModelSerializer): - class Meta: model = models.TaskStatus i18n_fields = ("name",) @@ -352,23 +351,24 @@ class ProjectDetailSerializer(ProjectSerializer): class ProjectDetailAdminSerializer(ProjectDetailSerializer): + is_private_extra_info = serializers.SerializerMethodField(method_name="get_is_private_extra_info") max_memberships = serializers.SerializerMethodField(method_name="get_max_memberships") total_memberships = serializers.SerializerMethodField(method_name="get_total_memberships") - can_is_private_be_updated = serializers.SerializerMethodField(method_name="get_can_is_private_be_updated") class Meta: model = models.Project read_only_fields = ("created_date", "modified_date", "slug", "blocked_code") exclude = ("logo", "last_us_ref", "last_task_ref", "last_issue_ref") + def get_is_private_extra_info(self, obj): + return services.check_if_project_privacity_can_be_changed(obj) + def get_max_memberships(self, obj): return services.get_max_memberships_for_project(obj) def get_total_memberships(self, obj): return services.get_total_project_memberships(obj) - def get_can_is_private_be_updated(self, obj): - return services.check_if_project_privacity_can_be_changed(obj) ###################################################### diff --git a/taiga/projects/services/members.py b/taiga/projects/services/members.py index a141f8e7..3c9d0242 100644 --- a/taiga/projects/services/members.py +++ b/taiga/projects/services/members.py @@ -84,6 +84,11 @@ def get_total_project_memberships(project): return project.memberships.count() +ERROR_MAX_PUBLIC_PROJECTS_MEMBERSHIPS = 'max_public_projects_memberships' +ERROR_MAX_PRIVATE_PROJECTS_MEMBERSHIPS = 'max_private_projects_memberships' +ERROR_MAX_PUBLIC_PROJECTS = 'max_public_projects' +ERROR_MAX_PRIVATE_PROJECTS = 'max_private_projects' + def check_if_project_privacity_can_be_changed(project): """Return if the project privacity can be changed from private to public or viceversa. @@ -92,20 +97,26 @@ def check_if_project_privacity_can_be_changed(project): :return: True if it can be changed or False if can't. """ if project.is_private: + current_memberships = project.memberships.count() + max_memberships = project.owner.max_memberships_public_projects + error_members_exceeded = ERROR_MAX_PRIVATE_PROJECTS_MEMBERSHIPS + current_projects = project.owner.owned_projects.filter(is_private=False).count() max_projects = project.owner.max_public_projects - max_memberships = project.owner.max_memberships_public_projects + error_project_exceeded = ERROR_MAX_PRIVATE_PROJECTS else: + current_memberships = project.memberships.count() + max_memberships = project.owner.max_memberships_private_projects + error_members_exceeded = ERROR_MAX_PUBLIC_PROJECTS_MEMBERSHIPS + current_projects = project.owner.owned_projects.filter(is_private=True).count() max_projects = project.owner.max_private_projects - max_memberships = project.owner.max_memberships_private_projects - - if max_projects is not None and current_projects >= max_projects: - return False - - current_memberships = project.memberships.count() + error_project_exceeded = ERROR_MAX_PUBLIC_PROJECTS if max_memberships is not None and current_memberships > max_memberships: - return False + return {'can_be_updated': False, 'reason': error_members_exceeded} - return True + if max_projects is not None and current_projects >= max_projects: + return {'can_be_updated': False, 'reason': error_project_exceeded} + + return {'can_be_updated': True, 'reason': None} diff --git a/tests/integration/test_projects.py b/tests/integration/test_projects.py index 77592abc..0a0be800 100644 --- a/tests/integration/test_projects.py +++ b/tests/integration/test_projects.py @@ -1399,7 +1399,13 @@ def test_project_transfer_validate_token_from_admin_member_with_valid_token(clie # Test taiga.projects.services.members.check_if_project_privacity_can_be_changed #################################################################################### -from taiga.projects.services import check_if_project_privacity_can_be_changed +from taiga.projects.services.members import ( + check_if_project_privacity_can_be_changed, + ERROR_MAX_PUBLIC_PROJECTS_MEMBERSHIPS, + ERROR_MAX_PUBLIC_PROJECTS, + ERROR_MAX_PRIVATE_PROJECTS_MEMBERSHIPS, + ERROR_MAX_PRIVATE_PROJECTS +) # private to public @@ -1413,7 +1419,8 @@ def test_private_project_cant_be_public_because_owner_doesnt_have_enought_slot_a project.owner.max_public_projects = 0 project.owner.max_memberships_public_projects = 3 - assert check_if_project_privacity_can_be_changed(project) == False + assert (check_if_project_privacity_can_be_changed(project) == + {'can_be_updated': False, 'reason': ERROR_MAX_PRIVATE_PROJECTS_MEMBERSHIPS}) def test_private_project_cant_be_public_because_owner_doesnt_have_enought_slot(client): @@ -1426,7 +1433,8 @@ def test_private_project_cant_be_public_because_owner_doesnt_have_enought_slot(c project.owner.max_public_projects = 0 project.owner.max_memberships_public_projects = 6 - assert check_if_project_privacity_can_be_changed(project) == False + assert (check_if_project_privacity_can_be_changed(project) == + {'can_be_updated': False, 'reason': ERROR_MAX_PRIVATE_PROJECTS}) def test_private_project_cant_be_public_because_too_much_members(client): @@ -1439,7 +1447,8 @@ def test_private_project_cant_be_public_because_too_much_members(client): project.owner.max_public_projects = 2 project.owner.max_memberships_public_projects = 3 - assert check_if_project_privacity_can_be_changed(project) == False + assert (check_if_project_privacity_can_be_changed(project) == + {'can_be_updated': False, 'reason': ERROR_MAX_PRIVATE_PROJECTS_MEMBERSHIPS}) def test_private_project_can_be_public_because_owner_has_enought_slot_and_project_has_enought_members(client): @@ -1452,7 +1461,7 @@ def test_private_project_can_be_public_because_owner_has_enought_slot_and_projec project.owner.max_public_projects = 2 project.owner.max_memberships_public_projects = 6 - assert check_if_project_privacity_can_be_changed(project) == True + assert (check_if_project_privacity_can_be_changed(project) == {'can_be_updated': True, 'reason': None}) def test_private_project_can_be_public_because_owner_has_unlimited_slot_and_project_has_unlimited_members(client): @@ -1465,7 +1474,7 @@ def test_private_project_can_be_public_because_owner_has_unlimited_slot_and_proj project.owner.max_public_projects = None project.owner.max_memberships_public_projects = None - assert check_if_project_privacity_can_be_changed(project) == True + assert (check_if_project_privacity_can_be_changed(project) == {'can_be_updated': True, 'reason': None}) def test_private_project_can_be_public_because_owner_has_unlimited_slot(client): @@ -1478,7 +1487,7 @@ def test_private_project_can_be_public_because_owner_has_unlimited_slot(client): project.owner.max_public_projects = None project.owner.max_memberships_public_projects = 6 - assert check_if_project_privacity_can_be_changed(project) == True + assert (check_if_project_privacity_can_be_changed(project) == {'can_be_updated': True, 'reason': None}) def test_private_project_can_be_public_because_project_has_unlimited_members(client): @@ -1491,7 +1500,7 @@ def test_private_project_can_be_public_because_project_has_unlimited_members(cli project.owner.max_public_projects = 2 project.owner.max_memberships_public_projects = None - assert check_if_project_privacity_can_be_changed(project) == True + assert (check_if_project_privacity_can_be_changed(project) == {'can_be_updated': True, 'reason': None}) # public to private @@ -1506,7 +1515,8 @@ def test_public_project_cant_be_private_because_owner_doesnt_have_enought_slot_a project.owner.max_private_projects = 0 project.owner.max_memberships_private_projects = 3 - assert check_if_project_privacity_can_be_changed(project) == False + assert (check_if_project_privacity_can_be_changed(project) == + {'can_be_updated': False, 'reason': ERROR_MAX_PUBLIC_PROJECTS_MEMBERSHIPS}) def test_public_project_cant_be_private_because_owner_doesnt_have_enought_slot(client): @@ -1519,7 +1529,8 @@ def test_public_project_cant_be_private_because_owner_doesnt_have_enought_slot(c project.owner.max_private_projects = 0 project.owner.max_memberships_private_projects = 6 - assert check_if_project_privacity_can_be_changed(project) == False + assert (check_if_project_privacity_can_be_changed(project) == + {'can_be_updated': False, 'reason': ERROR_MAX_PUBLIC_PROJECTS}) def test_public_project_cant_be_private_because_too_much_members(client): @@ -1532,7 +1543,8 @@ def test_public_project_cant_be_private_because_too_much_members(client): project.owner.max_private_projects = 2 project.owner.max_memberships_private_projects = 3 - assert check_if_project_privacity_can_be_changed(project) == False + assert (check_if_project_privacity_can_be_changed(project) == + {'can_be_updated': False, 'reason': ERROR_MAX_PUBLIC_PROJECTS_MEMBERSHIPS}) def test_public_project_can_be_private_because_owner_has_enought_slot_and_project_has_enought_members(client): @@ -1545,7 +1557,7 @@ def test_public_project_can_be_private_because_owner_has_enought_slot_and_projec project.owner.max_private_projects = 2 project.owner.max_memberships_private_projects = 6 - assert check_if_project_privacity_can_be_changed(project) == True + assert (check_if_project_privacity_can_be_changed(project) == {'can_be_updated': True, 'reason': None}) def test_public_project_can_be_private_because_owner_has_unlimited_slot_and_project_has_unlimited_members(client): @@ -1558,7 +1570,7 @@ def test_public_project_can_be_private_because_owner_has_unlimited_slot_and_proj project.owner.max_private_projects = None project.owner.max_memberships_private_projects = None - assert check_if_project_privacity_can_be_changed(project) == True + assert (check_if_project_privacity_can_be_changed(project) == {'can_be_updated': True, 'reason': None}) def test_public_project_can_be_private_because_owner_has_unlimited_slot(client): @@ -1571,7 +1583,7 @@ def test_public_project_can_be_private_because_owner_has_unlimited_slot(client): project.owner.max_private_projects = None project.owner.max_memberships_private_projects = 6 - assert check_if_project_privacity_can_be_changed(project) == True + assert (check_if_project_privacity_can_be_changed(project) == {'can_be_updated': True, 'reason': None}) def test_public_project_can_be_private_because_project_has_unlimited_members(client): @@ -1584,4 +1596,4 @@ def test_public_project_can_be_private_because_project_has_unlimited_members(cli project.owner.max_private_projects = 2 project.owner.max_memberships_private_projects = None - assert check_if_project_privacity_can_be_changed(project) == True + assert (check_if_project_privacity_can_be_changed(project) == {'can_be_updated': True, 'reason': None})