Skip to content

Commit

Permalink
Add delete tenant validation and subscription cancellation to mutation
Browse files Browse the repository at this point in the history
  • Loading branch information
wojcikmat committed May 8, 2024
1 parent 091183a commit e45be3e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 3 deletions.
32 changes: 31 additions & 1 deletion packages/backend/apps/multitenancy/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
from common.graphql import mutations, exceptions
from common.graphql.acl.decorators import permission_classes
from common.graphql.acl.wrappers import PERMISSION_DENIED_MESSAGE
from apps.finances.services import subscriptions
from apps.finances.serializers import CancelTenantActiveSubscriptionSerializer
from . import models
from . import serializers
from .tokens import tenant_invitation_token
from .constants import TenantUserRole
from .constants import TenantUserRole, TenantType as ConstantsTenantType


TenantUserRoleType = graphene.Enum.from_enum(TenantUserRole)
Expand Down Expand Up @@ -128,9 +130,37 @@ def get_object(cls, model_class, root, info, **input):


class DeleteTenantMutation(mutations.DeleteModelMutation):
"""
Mutation to delete a tenant from the system.
"""

class Meta:
model = models.Tenant

@classmethod
def mutate_and_get_payload(cls, root, info, id, **kwargs):
"""
Perform deletion of a tenant and subscription cancellation.
Returns:
DeleteTenantMutation: The mutation object with list of deleted_ids.
Raises:
GraphQlValidationError: If deletion encounters validation errors.
"""
tenant = info.context.tenant

if tenant.type == ConstantsTenantType.DEFAULT:
raise exceptions.GraphQlValidationError("Cannot delete default type tenant.")

schedule = subscriptions.get_schedule(tenant)
cancel_subscription_serializer = CancelTenantActiveSubscriptionSerializer(instance=schedule, data={})
if cancel_subscription_serializer.is_valid():
cancel_subscription_serializer.save()

tenant.delete()
return cls(deleted_ids=[id])


class CreateTenantInvitationMutation(mutations.SerializerMutation):
ok = graphene.Boolean()
Expand Down
24 changes: 22 additions & 2 deletions packages/backend/apps/multitenancy/tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,34 @@ class TestDeleteTenantMutation:
}
'''

def test_delete_tenant(self, graphene_client, user, tenant_factory, tenant_membership_factory):
def test_delete_tenant(
self,
graphene_client,
user,
tenant_factory,
tenant_membership_factory,
subscription_schedule_factory,
monthly_plan_price,
):
tenant = tenant_factory(name="Tenant 1", type=TenantType.ORGANIZATION)
tenant_id = tenant.id
tenant_membership_factory(tenant=tenant, user=user, role=TenantUserRole.OWNER)
subscription_schedule_factory(
phases=[{'items': [{'price': monthly_plan_price.id}], 'trialing': True}], customer__subscriber=tenant
)
graphene_client.force_authenticate(user)
graphene_client.set_tenant_dependent_context(tenant, TenantUserRole.OWNER)
executed = self.mutate(graphene_client, {"id": to_global_id("TenantType", tenant.id)})
response_data = executed["data"]["deleteTenant"]["deletedIds"]
assert response_data[0] == to_global_id("TenantType", tenant.id)
assert response_data[0] == to_global_id("TenantType", tenant_id)

def test_delete_default_tenant(self, graphene_client, user, tenant_factory, tenant_membership_factory):
tenant = tenant_factory(name="Tenant 1", type=TenantType.DEFAULT)
tenant_membership_factory(tenant=tenant, user=user, role=TenantUserRole.OWNER)
graphene_client.force_authenticate(user)
graphene_client.set_tenant_dependent_context(tenant, TenantUserRole.OWNER)
executed = self.mutate(graphene_client, {"id": to_global_id("TenantType", tenant.id)})
assert executed["errors"][0]["message"] == "GraphQlValidationError"

def test_user_without_membership(self, graphene_client, user, tenant_factory):
tenant = tenant_factory(name="Tenant 1", type=TenantType.ORGANIZATION)
Expand Down

0 comments on commit e45be3e

Please sign in to comment.