2026-01-26 11:09:40 -05:00

132 lines
5.7 KiB
Python

from typing import cast
import strawberry
from strawberry.types import Info
from channels.db import database_sync_to_async
from core.graphql.pubsub import pubsub
from core.graphql.inputs.profile import (
CustomerProfileInput,
CustomerProfileUpdateInput,
TeamProfileInput,
TeamProfileUpdateInput,
)
from core.graphql.types.profile import CustomerProfileType, TeamProfileType
from core.models.profile import CustomerProfile, TeamProfile
from core.graphql.utils import create_object, update_object, delete_object
from core.services.events import (
publish_team_profile_created, publish_team_profile_updated, publish_team_profile_deleted,
publish_team_profile_role_changed,
publish_customer_profile_created, publish_customer_profile_updated, publish_customer_profile_deleted,
publish_customer_profile_access_granted, publish_customer_profile_access_revoked,
)
@strawberry.type
class Mutation:
@strawberry.mutation(description="Create a new customer profile")
async def create_customer_profile(
self, input: CustomerProfileInput, info: Info
) -> CustomerProfileType:
m2m_data = {"customers": input.customer_ids} if input.customer_ids else None
instance = await create_object(input, CustomerProfile, m2m_data)
await pubsub.publish(f"customer_profile_created", instance.id)
# Publish event
profile = getattr(info.context.request, 'profile', None)
await publish_customer_profile_created(str(instance.id), triggered_by=profile)
return cast(CustomerProfileType, instance)
@strawberry.mutation(description="Update an existing customer profile")
async def update_customer_profile(
self, input: CustomerProfileUpdateInput, info: Info
) -> CustomerProfileType:
# Get old profile to detect customer access changes
old_profile = await database_sync_to_async(CustomerProfile.objects.get)(pk=input.id.node_id)
old_customer_ids = set(str(cid) for cid in await database_sync_to_async(list)(
old_profile.customers.values_list('id', flat=True)
))
m2m_data = {"customers": input.customer_ids} if input.customer_ids else None
instance = await update_object(input, CustomerProfile, m2m_data)
await pubsub.publish(f"customer_profile_updated", instance.id)
# Publish event
profile = getattr(info.context.request, 'profile', None)
await publish_customer_profile_updated(str(instance.id), triggered_by=profile)
# Detect customer access changes
if input.customer_ids is not None:
new_customer_ids = set(str(cid) for cid in input.customer_ids)
# Newly granted access
for customer_id in new_customer_ids - old_customer_ids:
await publish_customer_profile_access_granted(
str(instance.id), customer_id, triggered_by=profile
)
# Revoked access
for customer_id in old_customer_ids - new_customer_ids:
await publish_customer_profile_access_revoked(
str(instance.id), customer_id, triggered_by=profile
)
return cast(CustomerProfileType, instance)
@strawberry.mutation(description="Delete an existing customer profile")
async def delete_customer_profile(self, id: strawberry.ID, info: Info) -> strawberry.ID:
instance = await delete_object(id, CustomerProfile)
if not instance:
raise ValueError(f"CustomerProfile with ID {id} does not exist")
await pubsub.publish(f"customer_profile_deleted", id)
# Publish event
profile = getattr(info.context.request, 'profile', None)
await publish_customer_profile_deleted(str(id), triggered_by=profile)
return id
@strawberry.mutation(description="Create a new team profile")
async def create_team_profile(self, input: TeamProfileInput, info: Info) -> TeamProfileType:
instance = await create_object(input, TeamProfile)
await pubsub.publish(f"team_profile_created", instance.id)
# Publish event
profile = getattr(info.context.request, 'profile', None)
await publish_team_profile_created(str(instance.id), triggered_by=profile)
return cast(TeamProfileType, instance)
@strawberry.mutation(description="Update an existing team profile")
async def update_team_profile(self, input: TeamProfileUpdateInput, info: Info) -> TeamProfileType:
# Get old profile to detect role changes
old_profile = await database_sync_to_async(TeamProfile.objects.get)(pk=input.id.node_id)
old_role = old_profile.role
instance = await update_object(input, TeamProfile)
await pubsub.publish(f"team_profile_updated", instance.id)
# Publish event
profile = getattr(info.context.request, 'profile', None)
await publish_team_profile_updated(str(instance.id), triggered_by=profile)
# Check for role change
if input.role is not None and input.role != old_role:
await publish_team_profile_role_changed(
str(instance.id), old_role, input.role, triggered_by=profile
)
return cast(TeamProfileType, instance)
@strawberry.mutation(description="Delete an existing team profile")
async def delete_team_profile(self, id: strawberry.ID, info: Info) -> strawberry.ID:
instance = await delete_object(id, TeamProfile)
if not instance:
raise ValueError(f"TeamProfile with ID {id} does not exist")
await pubsub.publish(f"team_profile_deleted", id)
# Publish event
profile = getattr(info.context.request, 'profile', None)
await publish_team_profile_deleted(str(id), triggered_by=profile)
return id