Coverage for scripts / list_requests.py: 20%

71 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-25 18:08 -0500

1#!/usr/bin/env python3 

2""" 

3List JSM service requests with filtering. 

4 

5Usage: 

6 python list_requests.py --service-desk 1 

7 python list_requests.py --service-desk "IT Support" --status "In Progress" 

8 python list_requests.py --service-desk 1 --jql 'reporter=currentUser()' 

9 python list_requests.py --service-desk 1 --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 

23 

24 

25def list_service_requests(service_desk_id: str, status: Optional[str] = None, 

26 request_type: Optional[str] = None, 

27 jql: Optional[str] = None, 

28 max_results: int = 50, start_at: int = 0, 

29 profile: Optional[str] = None) -> Dict[str, Any]: 

30 """ 

31 List service requests. 

32 

33 Args: 

34 service_desk_id: Service desk ID or project key 

35 status: Filter by status 

36 request_type: Filter by request type name 

37 jql: Custom JQL filter 

38 max_results: Maximum results to return 

39 start_at: Pagination offset 

40 profile: JIRA profile to use 

41 

42 Returns: 

43 Search results with issues and total count 

44 """ 

45 # Build JQL query 

46 jql_parts = [] 

47 

48 # Add service desk filter 

49 jql_parts.append(f'project="{service_desk_id}"') 

50 

51 # Add status filter 

52 if status: 

53 jql_parts.append(f'status="{status}"') 

54 

55 # Add custom JQL 

56 if jql: 

57 jql_parts.append(f'({jql})') 

58 

59 final_jql = ' AND '.join(jql_parts) 

60 

61 with get_jira_client(profile) as client: 

62 return client.search_issues( 

63 jql=final_jql, 

64 max_results=max_results, 

65 start_at=start_at 

66 ) 

67 

68 

69def format_table(issues: List[Dict[str, Any]]) -> str: 

70 """Format issues as table.""" 

71 if not issues: 

72 return "No requests found." 

73 

74 lines = [] 

75 lines.append(f"\n{'Key':<12} {'Summary':<40} {'Status':<20} {'Reporter'}") 

76 lines.append("-" * 100) 

77 

78 for issue in issues: 

79 key = issue.get('key', 'N/A') 

80 fields = issue.get('fields', {}) 

81 

82 summary = fields.get('summary', 'N/A') 

83 if len(summary) > 37: 

84 summary = summary[:37] + '...' 

85 

86 status = fields.get('status', {}).get('name', 'N/A') 

87 

88 reporter = fields.get('reporter', {}) 

89 reporter_email = reporter.get('emailAddress', 'N/A') 

90 

91 lines.append(f"{key:<12} {summary:<40} {status:<20} {reporter_email}") 

92 

93 return '\n'.join(lines) 

94 

95 

96def format_json(issues: List[Dict[str, Any]]) -> str: 

97 """Format issues as JSON.""" 

98 return json.dumps(issues, indent=2) 

99 

100 

101def main(): 

102 """Main entry point.""" 

103 parser = argparse.ArgumentParser( 

104 description='List JSM service requests', 

105 formatter_class=argparse.RawDescriptionHelpFormatter, 

106 epilog=""" 

107Examples: 

108 List all requests: 

109 %(prog)s --service-desk 1 

110 

111 Filter by status: 

112 %(prog)s --service-desk 1 --status "In Progress" 

113 

114 Multiple statuses: 

115 %(prog)s --service-desk 1 --jql 'status in ("In Progress", "Waiting for support")' 

116 

117 Current user's requests: 

118 %(prog)s --service-desk 1 --jql 'reporter=currentUser()' 

119 

120 Pagination: 

121 %(prog)s --service-desk 1 --max-results 50 --start-at 50 

122 

123 JSON output: 

124 %(prog)s --service-desk 1 --output json 

125 """ 

126 ) 

127 

128 parser.add_argument('--service-desk', required=True, 

129 help='Service desk ID or project key') 

130 parser.add_argument('--status', 

131 help='Filter by status') 

132 parser.add_argument('--request-type', 

133 help='Filter by request type name') 

134 parser.add_argument('--jql', 

135 help='Additional JQL filter') 

136 parser.add_argument('--max-results', type=int, default=50, 

137 help='Maximum results to return (default: 50)') 

138 parser.add_argument('--start-at', type=int, default=0, 

139 help='Pagination offset (default: 0)') 

140 parser.add_argument('--output', choices=['text', 'json'], default='text', 

141 help='Output format (default: text)') 

142 parser.add_argument('--profile', 

143 help='JIRA profile to use from config') 

144 

145 args = parser.parse_args() 

146 

147 try: 

148 result = list_service_requests( 

149 service_desk_id=args.service_desk, 

150 status=args.status, 

151 request_type=args.request_type, 

152 jql=args.jql, 

153 max_results=args.max_results, 

154 start_at=args.start_at, 

155 profile=args.profile 

156 ) 

157 

158 issues = result.get('issues', []) 

159 total = result.get('total', 0) 

160 

161 if args.output == 'json': 

162 print(format_json(issues)) 

163 else: 

164 print(format_table(issues)) 

165 print(f"\nTotal: {total} requests") 

166 

167 if total > len(issues): 

168 shown = len(issues) 

169 remaining = total - shown - args.start_at 

170 if remaining > 0: 

171 print(f"Showing {shown} of {total} (use --start-at {args.start_at + shown} for next page)") 

172 

173 return 0 

174 

175 except JiraError as e: 

176 print_error(f"Failed to list requests: {e}") 

177 return 1 

178 except Exception as e: 

179 print_error(f"Unexpected error: {e}") 

180 return 1 

181 

182 

183if __name__ == '__main__': 

184 sys.exit(main())