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

1#!/usr/bin/env python3 

2""" 

3Get JSM service request details. 

4 

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""" 

11 

12import sys 

13import os 

14import argparse 

15import json 

16from pathlib import Path 

17from typing import Optional, Dict, Any, List 

18 

19sys.path.insert(0, str(Path(__file__).parent.parent.parent / 'shared' / 'scripts' / 'lib')) 

20 

21from config_manager import get_jira_client 

22from error_handler import print_error, JiraError, NotFoundError 

23from formatters import print_success 

24 

25 

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. 

31 

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 

37 

38 Returns: 

39 Request data 

40 

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') 

49 

50 with get_jira_client(profile) as client: 

51 return client.get_request(issue_key, expand=expand if expand else None) 

52 

53 

54def format_sla_time(millis: int) -> str: 

55 """Format milliseconds to human-readable time.""" 

56 hours = millis // 3600000 

57 minutes = (millis % 3600000) // 60000 

58 

59 if hours > 0: 

60 return f"{hours}h {minutes}m" 

61 else: 

62 return f"{minutes}m" 

63 

64 

65def format_request_text(request: Dict[str, Any], show_fields: bool = False) -> str: 

66 """Format request as text output.""" 

67 lines = [] 

68 

69 lines.append(f"\nRequest: {request.get('issueKey')}") 

70 lines.append("=" * 60) 

71 lines.append("") 

72 

73 # Request type 

74 req_type = request.get('requestType', {}) 

75 lines.append(f"Request Type: {req_type.get('name', 'N/A')}") 

76 

77 # Service desk 

78 lines.append(f"Service Desk ID: {request.get('serviceDeskId', 'N/A')}") 

79 

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("") 

84 

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("") 

93 

94 # Reporter 

95 reporter = request.get('reporter', {}) 

96 lines.append(f"Reporter: {reporter.get('emailAddress', 'N/A')}") 

97 

98 # Dates 

99 created = request.get('createdDate', {}) 

100 lines.append(f"Created: {created.get('friendly', 'N/A')}") 

101 lines.append("") 

102 

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', {}) 

109 

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" 

118 

119 lines.append(f" {name}: {status_icon}") 

120 lines.append("") 

121 

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']}") 

129 

130 return '\n'.join(lines) 

131 

132 

133def format_request_json(request: Dict[str, Any]) -> str: 

134 """Format request as JSON output.""" 

135 return json.dumps(request, indent=2) 

136 

137 

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 

147 

148 With SLA information: 

149 %(prog)s SD-101 --show-sla 

150 

151 With participants: 

152 %(prog)s SD-101 --show-participants 

153 

154 All details: 

155 %(prog)s SD-101 --full 

156 

157 JSON output: 

158 %(prog)s SD-101 --output json 

159 """ 

160 ) 

161 

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') 

174 

175 args = parser.parse_args() 

176 

177 try: 

178 show_sla = args.show_sla or args.full 

179 show_participants = args.show_participants or args.full 

180 

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 ) 

187 

188 if args.output == 'json': 

189 print(format_request_json(request)) 

190 else: 

191 print(format_request_text(request, show_fields=args.full)) 

192 

193 return 0 

194 

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 

204 

205 

206if __name__ == '__main__': 

207 sys.exit(main())