gateway/modules/workflows/methods/methodRedmine/actions/updateTicket.py
2026-04-21 21:30:11 +02:00

68 lines
2.6 KiB
Python

# Copyright (c) 2026 Patrick Motsch
# All rights reserved.
"""Workflow action: update a single Redmine ticket and refresh the mirror."""
import logging
from typing import Any, Dict
from modules.datamodels.datamodelChat import ActionResult
from modules.features.redmine.datamodelRedmine import RedmineTicketUpdateRequest
from modules.features.redmine.serviceRedmine import updateTicket
from ._shared import resolveInstanceContext, ticketToDict
logger = logging.getLogger(__name__)
async def updateTicketAction(self, parameters: Dict[str, Any]) -> ActionResult:
"""Update ``parameters['ticketId']`` with the given fields.
Only fields that are not ``None`` (and different from the current
Redmine state, enforced by the service) are sent to Redmine. An
optional ``notes`` string is appended as a journal entry.
"""
try:
user, mandateId, featureInstanceId = resolveInstanceContext(self.services, parameters)
except ValueError as exc:
return ActionResult.isFailure(error=str(exc))
raw_id = parameters.get("ticketId") or parameters.get("issueId")
if raw_id is None:
return ActionResult.isFailure(error="ticketId is required")
try:
ticketId = int(raw_id)
except (TypeError, ValueError):
return ActionResult.isFailure(error=f"ticketId must be an int, got {raw_id!r}")
try:
update = RedmineTicketUpdateRequest(
subject=parameters.get("subject"),
description=parameters.get("description"),
trackerId=_optInt(parameters.get("trackerId")),
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")),
notes=parameters.get("notes"),
customFields=parameters.get("customFields") or None,
)
except Exception as exc:
return ActionResult.isFailure(error=f"Invalid update body: {exc}")
try:
updated = await updateTicket(user, mandateId, featureInstanceId, ticketId, update)
except Exception as exc:
logger.exception("redmine.updateTicket failed for ticket %s", ticketId)
return ActionResult.isFailure(error=f"Update ticket failed: {exc}")
return ActionResult.isSuccess(data={"ticket": ticketToDict(updated)})
def _optInt(value: Any):
if value is None or value == "":
return None
try:
return int(value)
except (TypeError, ValueError):
return None