# Copyright (c) 2026 Patrick Motsch # All rights reserved. """Load ``redmineSnapshot.json`` into in-memory ``RedmineTicketDto`` objects. Used by all stats / orphan unit tests so they do not require any DB, HTTP or live Redmine access. """ from __future__ import annotations import json from pathlib import Path from typing import List, Optional, Tuple from modules.features.redmine.datamodelRedmine import ( RedmineFieldChoiceDto, RedmineFieldSchemaDto, RedmineRelationDto, RedmineTicketDto, ) _SNAPSHOT_PATH = Path(__file__).parent / "redmineSnapshot.json" def loadSnapshot() -> Tuple[RedmineFieldSchemaDto, List[RedmineTicketDto]]: """Return ``(schema, tickets)`` parsed from the JSON fixture.""" with _SNAPSHOT_PATH.open("r", encoding="utf-8") as f: raw = json.load(f) schema_raw = raw.get("schema") or {} trackers_raw = schema_raw.get("trackers") or [] schema = RedmineFieldSchemaDto( projectId=str(schema_raw.get("projectId") or ""), projectName=str(schema_raw.get("projectName") or ""), trackers=[RedmineFieldChoiceDto(**t) for t in trackers_raw], statuses=[RedmineFieldChoiceDto(**s) for s in schema_raw.get("statuses") or []], priorities=[RedmineFieldChoiceDto(**p) for p in schema_raw.get("priorities") or []], users=[RedmineFieldChoiceDto(**u) for u in schema_raw.get("users") or []], customFields=[], rootTrackerName="Userstory", rootTrackerId=_findRootTrackerId(trackers_raw), ) tickets: List[RedmineTicketDto] = [] for issue in raw.get("issues") or []: tickets.append( RedmineTicketDto( id=int(issue["id"]), subject=str(issue.get("subject") or ""), trackerId=issue.get("trackerId"), trackerName=issue.get("trackerName"), statusId=issue.get("statusId"), statusName=issue.get("statusName"), isClosed=bool(issue.get("isClosed")), priorityId=issue.get("priorityId"), priorityName=issue.get("priorityName"), assignedToId=issue.get("assignedToId"), assignedToName=issue.get("assignedToName"), parentId=issue.get("parentId"), createdOn=issue.get("createdOn"), updatedOn=issue.get("updatedOn"), relations=[RedmineRelationDto(**r) for r in issue.get("relations") or []], ) ) return schema, tickets def _findRootTrackerId(trackers) -> Optional[int]: for t in trackers: name = str(t.get("name") or "").strip().lower() if name in ("userstory", "user story", "user-story"): return int(t.get("id")) return None