Coverage for scripts / get_request.py: 16%
97 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-25 18:08 -0500
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-25 18:08 -0500
1#!/usr/bin/env python3
2"""
3Get JSM service request details.
5Usage:
6 python get_request.py SD-101
7 python get_request.py SD-101 --show-sla
8 python get_request.py SD-101 --show-participants
9 python get_request.py SD-101 --output json
10"""
12import sys
13import os
14import argparse
15import json
16from pathlib import Path
17from typing import Optional, Dict, Any, List
19sys.path.insert(0, str(Path(__file__).parent.parent.parent / 'shared' / 'scripts' / 'lib'))
21from config_manager import get_jira_client
22from error_handler import print_error, JiraError, NotFoundError
23from formatters import print_success
26def get_service_request(issue_key: str, show_sla: bool = False,
27 show_participants: bool = False,
28 profile: Optional[str] = None) -> Dict[str, Any]:
29 """
30 Get service request details.
32 Args:
33 issue_key: Request key (e.g., 'SD-101')
34 show_sla: Include SLA information
35 show_participants: Include participant list
36 profile: JIRA profile to use
38 Returns:
39 Request data
41 Raises:
42 NotFoundError: If request doesn't exist
43 """
44 expand = []
45 if show_sla:
46 expand.append('sla')
47 if show_participants:
48 expand.append('participant')
50 with get_jira_client(profile) as client:
51 return client.get_request(issue_key, expand=expand if expand else None)
54def format_sla_time(millis: int) -> str:
55 """Format milliseconds to human-readable time."""
56 hours = millis // 3600000
57 minutes = (millis % 3600000) // 60000
59 if hours > 0:
60 return f"{hours}h {minutes}m"
61 else:
62 return f"{minutes}m"
65def format_request_text(request: Dict[str, Any], show_fields: bool = False) -> str:
66 """Format request as text output."""
67 lines = []
69 lines.append(f"\nRequest: {request.get('issueKey')}")
70 lines.append("=" * 60)
71 lines.append("")
73 # Request type
74 req_type = request.get('requestType', {})
75 lines.append(f"Request Type: {req_type.get('name', 'N/A')}")
77 # Service desk
78 lines.append(f"Service Desk ID: {request.get('serviceDeskId', 'N/A')}")
80 # Current status
81 status = request.get('currentStatus', {})
82 lines.append(f"Status: {status.get('status', 'N/A')} ({status.get('statusCategory', 'N/A')})")
83 lines.append("")
85 # Field values
86 if show_fields:
87 lines.append("Fields:")
88 for field in request.get('requestFieldValues', []):
89 label = field.get('label', field.get('fieldId'))
90 value = field.get('value', 'N/A')
91 lines.append(f" {label}: {value}")
92 lines.append("")
94 # Reporter
95 reporter = request.get('reporter', {})
96 lines.append(f"Reporter: {reporter.get('emailAddress', 'N/A')}")
98 # Dates
99 created = request.get('createdDate', {})
100 lines.append(f"Created: {created.get('friendly', 'N/A')}")
101 lines.append("")
103 # SLA information
104 if 'sla' in request:
105 lines.append("SLA Information:")
106 for sla_metric in request['sla'].get('values', []):
107 name = sla_metric.get('name')
108 ongoing = sla_metric.get('ongoingCycle', {})
110 if ongoing.get('breached'):
111 status_icon = "⚠ BREACHED"
112 else:
113 remaining = ongoing.get('remainingTime', {}).get('millis', 0)
114 if remaining > 0:
115 status_icon = f"⏱ {format_sla_time(remaining)} remaining"
116 else:
117 status_icon = "✓ Met"
119 lines.append(f" {name}: {status_icon}")
120 lines.append("")
122 # Links
123 links = request.get('_links', {})
124 lines.append("Links:")
125 if 'web' in links:
126 lines.append(f" Customer Portal: {links['web']}")
127 if 'agent' in links:
128 lines.append(f" Agent View: {links['agent']}")
130 return '\n'.join(lines)
133def format_request_json(request: Dict[str, Any]) -> str:
134 """Format request as JSON output."""
135 return json.dumps(request, indent=2)
138def main():
139 """Main entry point."""
140 parser = argparse.ArgumentParser(
141 description='Get JSM service request details',
142 formatter_class=argparse.RawDescriptionHelpFormatter,
143 epilog="""
144Examples:
145 Basic usage:
146 %(prog)s SD-101
148 With SLA information:
149 %(prog)s SD-101 --show-sla
151 With participants:
152 %(prog)s SD-101 --show-participants
154 All details:
155 %(prog)s SD-101 --full
157 JSON output:
158 %(prog)s SD-101 --output json
159 """
160 )
162 parser.add_argument('request_key',
163 help='Request key (e.g., SD-101)')
164 parser.add_argument('--show-sla', action='store_true',
165 help='Include SLA information')
166 parser.add_argument('--show-participants', action='store_true',
167 help='Include participant list')
168 parser.add_argument('--full', action='store_true',
169 help='Show all details (SLA + participants + fields)')
170 parser.add_argument('--output', choices=['text', 'json'], default='text',
171 help='Output format (default: text)')
172 parser.add_argument('--profile',
173 help='JIRA profile to use from config')
175 args = parser.parse_args()
177 try:
178 show_sla = args.show_sla or args.full
179 show_participants = args.show_participants or args.full
181 request = get_service_request(
182 issue_key=args.request_key,
183 show_sla=show_sla,
184 show_participants=show_participants,
185 profile=args.profile
186 )
188 if args.output == 'json':
189 print(format_request_json(request))
190 else:
191 print(format_request_text(request, show_fields=args.full))
193 return 0
195 except NotFoundError as e:
196 print_error(f"Request not found: {e}")
197 return 1
198 except JiraError as e:
199 print_error(f"Failed to get request: {e}")
200 return 1
201 except Exception as e:
202 print_error(f"Unexpected error: {e}")
203 return 1
206if __name__ == '__main__':
207 sys.exit(main())