# Copyright (c) 2026 Patrick Motsch # All rights reserved. """Workflow action: create a new Redmine ticket.""" import logging from typing import Any, Dict from modules.datamodels.datamodelChat import ActionResult from modules.features.redmine.datamodelRedmine import RedmineTicketCreateRequest from modules.features.redmine.serviceRedmine import createTicket from ._shared import resolveInstanceContext, ticketToDict logger = logging.getLogger(__name__) async def createTicketAction(self, parameters: Dict[str, Any]) -> ActionResult: """Create a Redmine ticket. ``subject`` and ``trackerId`` are required.""" try: user, mandateId, featureInstanceId = resolveInstanceContext(self.services, parameters) except ValueError as exc: return ActionResult.isFailure(error=str(exc)) subject = parameters.get("subject") trackerId = parameters.get("trackerId") if not subject: return ActionResult.isFailure(error="subject is required") try: trackerId_int = int(trackerId) if trackerId is not None else None except (TypeError, ValueError): return ActionResult.isFailure(error=f"trackerId must be an int, got {trackerId!r}") if trackerId_int is None: return ActionResult.isFailure(error="trackerId is required") try: payload = RedmineTicketCreateRequest( subject=subject, trackerId=trackerId_int, description=parameters.get("description") or "", statusId=_optInt(parameters.get("statusId")), priorityId=_optInt(parameters.get("priorityId")), assignedToId=_optInt(parameters.get("assignedToId")), parentIssueId=_optInt(parameters.get("parentIssueId")), fixedVersionId=_optInt(parameters.get("fixedVersionId")), customFields=parameters.get("customFields") or None, ) except Exception as exc: return ActionResult.isFailure(error=f"Invalid create body: {exc}") try: created = await createTicket(user, mandateId, featureInstanceId, payload) except Exception as exc: logger.exception("redmine.createTicket failed") return ActionResult.isFailure(error=f"Create ticket failed: {exc}") return ActionResult.isSuccess(data={"ticket": ticketToDict(created)}) def _optInt(value: Any): if value is None or value == "": return None try: return int(value) except (TypeError, ValueError): return None