142 lines
7.0 KiB
Python
142 lines
7.0 KiB
Python
from typing import cast
|
|
import strawberry
|
|
from strawberry.types import Info
|
|
from strawberry.scalars import JSON
|
|
from asgiref.sync import sync_to_async
|
|
from core.graphql.inputs.project_scope_template import (
|
|
ProjectScopeTemplateInput,
|
|
ProjectScopeTemplateUpdateInput,
|
|
ProjectAreaTemplateInput,
|
|
ProjectAreaTemplateUpdateInput,
|
|
ProjectTaskTemplateInput,
|
|
ProjectTaskTemplateUpdateInput,
|
|
)
|
|
from core.graphql.pubsub import pubsub
|
|
from core.graphql.types.project_scope_template import (
|
|
ProjectScopeTemplateType,
|
|
ProjectAreaTemplateType,
|
|
ProjectTaskTemplateType,
|
|
)
|
|
from core.graphql.utils import create_object, update_object, delete_object
|
|
from core.models.project_scope_template import (
|
|
ProjectScopeTemplate,
|
|
ProjectAreaTemplate,
|
|
ProjectTaskTemplate,
|
|
)
|
|
from core.services.scope_builder import build_project_scope_template
|
|
|
|
|
|
@strawberry.type
|
|
class Mutation:
|
|
@strawberry.mutation(description="Create a new Project Scope Template")
|
|
async def create_project_scope_template(self, input: ProjectScopeTemplateInput, info: Info) -> ProjectScopeTemplateType:
|
|
instance = await create_object(input, ProjectScopeTemplate)
|
|
await pubsub.publish("project_scope_template_created", instance.id)
|
|
# Note: No event publisher exists for project scope template CRUD operations yet
|
|
return cast(ProjectScopeTemplateType, instance)
|
|
|
|
@strawberry.mutation(description="Update an existing Project Scope Template")
|
|
async def update_project_scope_template(self, input: ProjectScopeTemplateUpdateInput, info: Info) -> ProjectScopeTemplateType:
|
|
instance = await update_object(input, ProjectScopeTemplate)
|
|
await pubsub.publish("project_scope_template_updated", instance.id)
|
|
# Note: No event publisher exists for project scope template CRUD operations yet
|
|
return cast(ProjectScopeTemplateType, instance)
|
|
|
|
@strawberry.mutation(description="Delete a Project Scope Template")
|
|
async def delete_project_scope_template(self, id: strawberry.ID, info: Info) -> strawberry.ID:
|
|
instance = await delete_object(id, ProjectScopeTemplate)
|
|
if not instance:
|
|
raise ValueError(f"ProjectScopeTemplate with ID {id} does not exist")
|
|
await pubsub.publish("project_scope_template_deleted", id)
|
|
# Note: No event publisher exists for project scope template CRUD operations yet
|
|
return id
|
|
|
|
@strawberry.mutation(description="Create a Project Area Template")
|
|
async def create_project_area_template(self, input: ProjectAreaTemplateInput, info: Info) -> ProjectAreaTemplateType:
|
|
instance = await create_object(input, ProjectAreaTemplate)
|
|
await pubsub.publish("project_area_template_created", instance.id)
|
|
# Note: No event publisher exists for project area template CRUD operations yet
|
|
return cast(ProjectAreaTemplateType, instance)
|
|
|
|
@strawberry.mutation(description="Update a Project Area Template")
|
|
async def update_project_area_template(self, input: ProjectAreaTemplateUpdateInput, info: Info) -> ProjectAreaTemplateType:
|
|
instance = await update_object(input, ProjectAreaTemplate)
|
|
await pubsub.publish("project_area_template_updated", instance.id)
|
|
# Note: No event publisher exists for project area template CRUD operations yet
|
|
return cast(ProjectAreaTemplateType, instance)
|
|
|
|
@strawberry.mutation(description="Delete a Project Area Template")
|
|
async def delete_project_area_template(self, id: strawberry.ID, info: Info) -> strawberry.ID:
|
|
instance = await delete_object(id, ProjectAreaTemplate)
|
|
if not instance:
|
|
raise ValueError(f"ProjectAreaTemplate with ID {id} does not exist")
|
|
await pubsub.publish("project_area_template_deleted", id)
|
|
# Note: No event publisher exists for project area template CRUD operations yet
|
|
return id
|
|
|
|
@strawberry.mutation(description="Create a Project Task Template")
|
|
async def create_project_task_template(self, input: ProjectTaskTemplateInput, info: Info) -> ProjectTaskTemplateType:
|
|
instance = await create_object(input, ProjectTaskTemplate)
|
|
await pubsub.publish("project_task_template_created", instance.id)
|
|
# Note: No event publisher exists for project task template CRUD operations yet
|
|
return cast(ProjectTaskTemplateType, instance)
|
|
|
|
@strawberry.mutation(description="Update a Project Task Template")
|
|
async def update_project_task_template(self, input: ProjectTaskTemplateUpdateInput, info: Info) -> ProjectTaskTemplateType:
|
|
instance = await update_object(input, ProjectTaskTemplate)
|
|
await pubsub.publish("project_task_template_updated", instance.id)
|
|
# Note: No event publisher exists for project task template CRUD operations yet
|
|
return cast(ProjectTaskTemplateType, instance)
|
|
|
|
@strawberry.mutation(description="Delete a Project Task Template")
|
|
async def delete_project_task_template(self, id: strawberry.ID, info: Info) -> strawberry.ID:
|
|
instance = await delete_object(id, ProjectTaskTemplate)
|
|
if not instance:
|
|
raise ValueError(f"ProjectTaskTemplate with ID {id} does not exist")
|
|
await pubsub.publish("project_task_template_deleted", id)
|
|
# Note: No event publisher exists for project task template CRUD operations yet
|
|
return id
|
|
|
|
@strawberry.mutation(description="Create a ProjectScopeTemplate (and nested Categories/Tasks) from a JSON payload")
|
|
async def create_project_scope_template_from_json(
|
|
self,
|
|
payload: JSON,
|
|
replace: bool = False,
|
|
info: Info | None = None,
|
|
) -> ProjectScopeTemplateType:
|
|
"""
|
|
Accepts a JSON object matching the builder payload shape:
|
|
{
|
|
"name": str, "description": str, "is_active": bool,
|
|
"categories": [
|
|
{"name": str, "order": int, "tasks": [
|
|
{"description": str, "checklist_description": str, "order": int, "estimated_minutes": int}
|
|
]}
|
|
]
|
|
}
|
|
If replace=True and a template with the same name exists, it will be deleted first.
|
|
"""
|
|
|
|
def _do_create_sync():
|
|
if not isinstance(payload, dict):
|
|
raise ValueError("payload must be a JSON object")
|
|
|
|
name = payload.get("name")
|
|
if not name or not isinstance(name, str):
|
|
raise ValueError("payload.name is required and must be a string")
|
|
|
|
if replace:
|
|
ProjectScopeTemplate.objects.filter(name=name).delete()
|
|
elif ProjectScopeTemplate.objects.filter(name=name).exists():
|
|
raise ValueError(
|
|
f"A ProjectScopeTemplate named '{name}' already exists (use replace=true to overwrite)"
|
|
)
|
|
|
|
tpl = build_project_scope_template(payload)
|
|
return tpl
|
|
|
|
instance = await sync_to_async(_do_create_sync)()
|
|
await pubsub.publish("project_scope_template_created", instance.id)
|
|
# Note: No event publisher exists for project scope template CRUD operations yet
|
|
return cast(ProjectScopeTemplateType, instance)
|