Coverage for scripts / create_request.py: 15%
92 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"""
3Create a JSM service request.
5Usage:
6 python create_request.py --service-desk 1 --request-type 10 --summary "Email not working" --description "Cannot send emails"
7 python create_request.py --service-desk "IT Support" --request-type "Incident" --summary "Server down"
8 python create_request.py --service-desk 1 --request-type 10 --summary "Test" --field priority=High --dry-run
9"""
11import sys
12import os
13import argparse
14import json
15from pathlib import Path
16from typing import Optional, Dict, Any, List
18sys.path.insert(0, str(Path(__file__).parent.parent.parent / 'shared' / 'scripts' / 'lib'))
20from config_manager import get_jira_client
21from error_handler import print_error, JiraError, NotFoundError
22from formatters import print_success
25def create_service_request(service_desk_id: str, request_type_id: str,
26 summary: str, description: str,
27 custom_fields: Optional[Dict[str, Any]] = None,
28 participants: Optional[List[str]] = None,
29 on_behalf_of: Optional[str] = None,
30 profile: Optional[str] = None) -> Dict[str, Any]:
31 """
32 Create a service request.
34 Args:
35 service_desk_id: Service desk ID or key
36 request_type_id: Request type ID
37 summary: Request summary
38 description: Request description
39 custom_fields: Additional custom fields
40 participants: List of participant email addresses
41 on_behalf_of: Create on behalf of user email
42 profile: JIRA profile to use
44 Returns:
45 Created request data
47 Raises:
48 ValueError: If required fields are missing
49 NotFoundError: If service desk or request type not found
50 """
51 if not summary or not summary.strip():
52 raise ValueError("summary is required")
54 if not description or not description.strip():
55 raise ValueError("description is required")
57 # Build request field values
58 fields = {
59 'summary': summary,
60 'description': description
61 }
63 # Add custom fields
64 if custom_fields:
65 fields.update(custom_fields)
67 with get_jira_client(profile) as client:
68 return client.create_request(
69 service_desk_id=service_desk_id,
70 request_type_id=request_type_id,
71 fields=fields,
72 participants=participants,
73 on_behalf_of=on_behalf_of
74 )
77def parse_custom_fields(field_args: List[str]) -> Dict[str, Any]:
78 """
79 Parse custom field arguments from command line.
81 Args:
82 field_args: List of field=value strings
84 Returns:
85 Dictionary of field values
86 """
87 fields = {}
88 for arg in field_args:
89 if '=' not in arg:
90 raise ValueError(f"Invalid field format: {arg}. Use field=value")
92 key, value = arg.split('=', 1)
93 fields[key.strip()] = value.strip()
95 return fields
98def main():
99 """Main entry point."""
100 parser = argparse.ArgumentParser(
101 description='Create a JSM service request',
102 formatter_class=argparse.RawDescriptionHelpFormatter,
103 epilog="""
104Examples:
105 Basic usage:
106 %(prog)s --service-desk 1 --request-type 10 --summary "Email not working" --description "Cannot send emails"
108 With custom fields:
109 %(prog)s --service-desk 1 --request-type 10 --summary "Server down" --description "Production server not responding" --field priority=High --field impact="Multiple Users"
111 With participants:
112 %(prog)s --service-desk 1 --request-type 10 --summary "Team access" --description "Need access for team" --participants "alice@example.com,bob@example.com"
114 On behalf of customer:
115 %(prog)s --service-desk 1 --request-type 10 --summary "Password reset" --description "User needs reset" --on-behalf-of "customer@example.com"
117 Dry-run:
118 %(prog)s --service-desk 1 --request-type 10 --summary "Test" --description "Test" --dry-run
119 """
120 )
122 parser.add_argument('--service-desk', required=True,
123 help='Service desk ID or key')
124 parser.add_argument('--request-type', required=True,
125 help='Request type ID')
126 parser.add_argument('--summary', required=True,
127 help='Request summary')
128 parser.add_argument('--description', required=True,
129 help='Request description')
130 parser.add_argument('--field', action='append', default=[],
131 help='Custom field (format: field=value)')
132 parser.add_argument('--participants',
133 help='Comma-separated list of participant emails')
134 parser.add_argument('--on-behalf-of',
135 help='Create request on behalf of user email')
136 parser.add_argument('--output', choices=['text', 'json'], default='text',
137 help='Output format (default: text)')
138 parser.add_argument('--dry-run', action='store_true',
139 help='Show what would be created without creating')
140 parser.add_argument('--profile',
141 help='JIRA profile to use from config')
143 args = parser.parse_args()
145 try:
146 # Parse custom fields
147 custom_fields = parse_custom_fields(args.field) if args.field else None
149 # Parse participants
150 participants = None
151 if args.participants:
152 participants = [p.strip() for p in args.participants.split(',')]
154 if args.dry_run:
155 print("DRY RUN MODE - No changes will be made\n")
156 print("Would create request:")
157 print(f" Service Desk: {args.service_desk}")
158 print(f" Request Type: {args.request_type}")
159 print(f" Summary: {args.summary}")
160 print(f" Description: {args.description}")
161 if custom_fields:
162 print(f" Custom Fields: {json.dumps(custom_fields, indent=2)}")
163 if participants:
164 print(f" Participants: {', '.join(participants)}")
165 if args.on_behalf_of:
166 print(f" On Behalf Of: {args.on_behalf_of}")
167 return 0
169 request = create_service_request(
170 service_desk_id=args.service_desk,
171 request_type_id=args.request_type,
172 summary=args.summary,
173 description=args.description,
174 custom_fields=custom_fields,
175 participants=participants,
176 on_behalf_of=args.on_behalf_of,
177 profile=args.profile
178 )
180 if args.output == 'json':
181 print(json.dumps(request, indent=2))
182 else:
183 print_success("Service request created successfully!\n")
184 print(f"Request Key: {request.get('issueKey')}")
186 req_type = request.get('requestType', {})
187 print(f"Request Type: {req_type.get('name', 'N/A')}")
189 status = request.get('currentStatus', {})
190 print(f"Status: {status.get('status', 'N/A')}")
192 print(f"\nSummary: {args.summary}")
193 print(f"Description: {args.description}")
195 reporter = request.get('reporter', {})
196 print(f"\nReporter: {reporter.get('emailAddress', 'N/A')}")
198 created = request.get('createdDate', {})
199 print(f"Created: {created.get('friendly', 'N/A')}")
201 links = request.get('_links', {})
202 if 'web' in links:
203 print(f"\nCustomer Portal: {links['web']}")
204 if 'agent' in links:
205 print(f"Agent View: {links['agent']}")
207 return 0
209 except ValueError as e:
210 print_error(str(e))
211 return 1
212 except (JiraError, NotFoundError) as e:
213 print_error(f"Failed to create request: {e}")
214 return 1
215 except Exception as e:
216 print_error(f"Unexpected error: {e}")
217 return 1
220if __name__ == '__main__':
221 sys.exit(main())