cherby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,147 @@
1
+ require 'savon'
2
+
3
+ module Cherby
4
+ # Cherwell SOAP Client wrapper
5
+ class Client < Savon::Client
6
+
7
+ # Create a Cherwell Client for the SOAP API at the given base URL.
8
+ #
9
+ # @param [String] base_url
10
+ # Full URL to the Cherwell web service WSDL, typically something
11
+ # like "http://my.hostname.com/CherwellService/api.asmx?WSDL".
12
+ # The `http://` and `?WSDL` parts are automatically added if missing.
13
+ #
14
+ def initialize(base_url)
15
+ if File.exist?(base_url)
16
+ wsdl_url = base_url
17
+ elsif base_url =~ /^http/
18
+ if base_url.downcase.end_with?('?wsdl')
19
+ wsdl_url = base_url
20
+ else
21
+ wsdl_url = "#{base_url}?WSDL"
22
+ end
23
+ elsif base_url !~ /^http/
24
+ raise ArgumentError, "Client URL must be a local file, or begin with http"
25
+ end
26
+ super(:wsdl => wsdl_url)
27
+ end
28
+
29
+ # Call a given SOAP method with an optional body.
30
+ #
31
+ # @example
32
+ # client.call_wrap(:login, {:userId => 'garak', :pasword => 'fabric'})
33
+ # # => true
34
+ #
35
+ # @param [Symbol] method
36
+ # Cherwell API method name, as a `:snake_case_symbol`.
37
+ # Must be one of the methods returned by `#known_methods`.
38
+ # @param [Hash<String>] body
39
+ # Message body to pass to the method.
40
+ #
41
+ # @return [String]
42
+ # Content found inside the returned XML document's `<[MethodName]Result>`
43
+ # element.
44
+ #
45
+ def call_wrap(method, body={})
46
+ method = method.to_sym
47
+ if !known_methods.include?(method)
48
+ raise ArgumentError, "Unknown Cherwell SOAP API method: #{method}"
49
+ end
50
+ # FIXME: Let Savon handle this snake_case stuff
51
+ # Each request has a *_response containing a *_result
52
+ response_field = (method.to_s + '_response').to_sym
53
+ result_field = (method.to_s + '_result').to_sym
54
+ # Submit the request
55
+ response = self.call(method, :message => body)
56
+ return response.to_hash[response_field][result_field]
57
+ end
58
+
59
+ # If a method in `#known_methods` is called, send it as a request.
60
+ #
61
+ # @param [Symbol] method
62
+ # Cherwell API method name, as a `:snake_case_symbol`.
63
+ # Must be one of the methods returned by `#known_methods`.
64
+ #
65
+ # @param [String, Hash] args
66
+ # Positional arguments (strings) or a hash of arguments
67
+ # (`:symbol => 'String'`) to pass to the method.
68
+ #
69
+ # @example
70
+ # # Login with positional arguments:
71
+ # client.login('sisko', 'baseball')
72
+ # # or a Hash of arguments:
73
+ # client.login(:userId => 'sisko', :password => 'baseball')
74
+ #
75
+ # client.get_business_object_definition(
76
+ # :nameOrId => 'JournalNote')
77
+ #
78
+ def method_missing(method, *args, &block)
79
+ if known_methods.include?(method)
80
+ if args.first.is_a?(Hash)
81
+ call_wrap(method, args.first)
82
+ else
83
+ hash_args = args_to_hash(method, *args)
84
+ call_wrap(method, hash_args)
85
+ end
86
+ else
87
+ super
88
+ end
89
+ end
90
+
91
+ # Valid methods in the Cherwell SOAP API
92
+ #
93
+ # @return [Array<Symbol>]
94
+ #
95
+ def known_methods
96
+ return self.operations.sort
97
+ end
98
+
99
+ # Return parameters for the given Cherwell API method.
100
+ #
101
+ # @param [Symbol] method
102
+ # Cherwell API method name, as a `:snake_case_symbol`.
103
+ # Must be one of the methods returned by `#known_methods`.
104
+ #
105
+ # @return [Hash]
106
+ # Parameter definitions for the given method, or an empty
107
+ # hash if the method is unknown.
108
+ #
109
+ def params_for_method(method)
110
+ if @wsdl.operations.include?(method)
111
+ return @wsdl.operations[method][:parameters] || {}
112
+ else
113
+ return {}
114
+ end
115
+ end
116
+
117
+ # Convert positional parameters into a `:key => value` hash,
118
+ # with parameter names inferred from `#params_for_method`.
119
+ #
120
+ # @example
121
+ # client.args_to_hash(:login, 'odo', 'nerys')
122
+ # # => {:userId => 'odo', :password => 'nerys'}
123
+ #
124
+ # @param [Symbol] method
125
+ # Cherwell API method name, as a `:snake_case_symbol`.
126
+ # Must be one of the methods returned by `#known_methods`.
127
+ # @param [String] args
128
+ # Positional argument values
129
+ #
130
+ # @return [Hash<String>]
131
+ # `:key => value` for each positional argument.
132
+ #
133
+ # @raise [ArgumentError]
134
+ # If the given number of `args` doesn't match the number of parameters
135
+ # expected by `method`.
136
+ #
137
+ def args_to_hash(method, *args)
138
+ params = params_for_method(method)
139
+ if params.count != args.count
140
+ raise ArgumentError.new(
141
+ "Wrong number of arguments (#{args.count} for #{params.count})")
142
+ end
143
+ return Hash[params.keys.zip(args)]
144
+ end
145
+ end
146
+ end
147
+
@@ -0,0 +1,6 @@
1
+ module Cherby
2
+ class CherbyError < RuntimeError; end
3
+ class LoginFailed < CherbyError; end
4
+ class SoapError < CherbyError; end
5
+ end # module Cherby
6
+
@@ -0,0 +1,141 @@
1
+ require 'date'
2
+ require 'mustache'
3
+ require 'cherby/business_object'
4
+ require 'cherby/task'
5
+ require 'cherby/journal_note'
6
+
7
+ module Cherby
8
+ # Wrapper for Cherwell incident objects.
9
+ class Incident < BusinessObject
10
+ @object_name = 'Incident'
11
+ @template = 'incident'
12
+ @default_values = {
13
+ :service => "Auto Generated",
14
+ :service_group => "Auto Generated",
15
+ :category => "Auto Generated",
16
+ :sub_category => "JIRA",
17
+ :impact => "Inconvenience",
18
+ :urgency => "Medium",
19
+ :priority => "3",
20
+ }
21
+
22
+ def id
23
+ self['IncidentID']
24
+ end
25
+
26
+ # Return true if this incident already exists in Cherwell
27
+ # (that is, its id is a nonempty string of digits)
28
+ def exists?
29
+ return id.to_s =~ /\d+/
30
+ end
31
+
32
+ # Mark this incident as complete by filling in relevant fields.
33
+ # FIXME: Parameterize these, instead of assuming Jira relationship.
34
+ #
35
+ def complete!(comments = "Closed in Jira => automated close.")
36
+ self["CloseDescription"] = comments
37
+ self["LastModDateTime"] = DateTime.now.to_s
38
+ self["Stat_NumberOfTouches"] = self["Stat_NumberOfTouches"].to_i + 1
39
+ #self["PhaseInvestigateStatus"] = "Complete"
40
+ self["PhaseResolveStatus"] = "Complete"
41
+ #self["PhaseCloseStatus"] = "Complete"
42
+ self["ClosureCode"] = "Completed"
43
+ self["CMDBUpdate"] = "No"
44
+ self["BusinessService"] = "Not Applicable"
45
+ self["RequestType"] = "Not Applicable"
46
+ self["SubCategory"] = "JIRA"
47
+ self["SubcategoryNonHR"] = "JIRA"
48
+ end
49
+
50
+ # Return Task instances for all tasks associated with this Incident
51
+ #
52
+ # @return [Array<Task>]
53
+ #
54
+ def tasks
55
+ @tasks ||= @dom.css("BusinessObject[@Name=Task]").map do |element|
56
+ Task.new(element.to_xml)
57
+ end
58
+ end
59
+
60
+ # Return all journal notes associated with this Incident.
61
+ #
62
+ # @return [Array<JournalNote>]
63
+ #
64
+ def journal_notes
65
+ css = "Relationship[@Name='Incident has Notes']" +
66
+ " BusinessObject[@Name=JournalNote]"
67
+ @notes ||= @dom.css(css).map do |element|
68
+ JournalNote.new(element.to_xml)
69
+ end
70
+ end
71
+
72
+ # Add a new Task to this incident.
73
+ def add_task(task_description = "", task_notes = "", owned_by = "")
74
+ # Bail out if this incident doesn't actually exist
75
+ return nil if !exists?
76
+ task = Task.create({
77
+ :parent_public_id => self['IncidentID'],
78
+ :parent_type_name => 'Incident',
79
+ :task_type => 'Action',
80
+ :task_description => task_description,
81
+ :notes => task_notes,
82
+ :owned_by => owned_by,
83
+ })
84
+ relationship_xml = Mustache.render_file('task_relationship',
85
+ {:task_business_object => task.dom.css('BusinessObject').to_xml})
86
+ @dom.css('RelationshipList').first.add_child(relationship_xml)
87
+ end
88
+
89
+ # Add a new JournalNote to this incident.
90
+ #
91
+ # @param [JournalNote] journal_note
92
+ # The note to add to the incident
93
+ #
94
+ def add_journal_note(journal_note)
95
+ return nil if !exists?
96
+ relationship_xml = Mustache.render_file('journal_note_relationship',
97
+ {:note_business_object => journal_note.dom.css('BusinessObject').to_xml})
98
+ @dom.css('RelationshipList').first.add_child(relationship_xml)
99
+ end
100
+
101
+ # Return True if this Incident has important fields differing from the
102
+ # given Incident.
103
+ #
104
+ # @param [Incident] incident
105
+ # The Incident to compare this one to.
106
+ #
107
+ # @return [Boolean]
108
+ # `true` if the incidents differn `false` otherwise.
109
+ #
110
+ def differs_from?(incident)
111
+ return true if self['Status'] != incident['Status']
112
+ return true if self['JIRAID'] != incident['JIRAID']
113
+ return false
114
+ end
115
+
116
+ # DO NOT REMOVE: use the follow code for code-gen of Cherwell consts
117
+ =begin
118
+ def extract_lines(css, l)
119
+ lines = []
120
+ @dom.css(css).each do |f|
121
+ lines << " #{('"' + f["Name"] + '"').ljust(l)} => \"#{f["IDREF"]}\""
122
+ end
123
+ lines
124
+ end
125
+
126
+ def extract
127
+ puts "*"*80
128
+ puts "{"
129
+ puts extract_lines("BusinessObject[@Name=Incident] Field", 40).join(",\n")
130
+ puts "}"
131
+ puts "*"*80
132
+ puts "{"
133
+ extract_lines("BusinessObject[@Name=Task] Field", 24).join(",\n")
134
+ puts "}"
135
+ puts "*"*80
136
+ end
137
+ =end
138
+
139
+ end # class Incident
140
+ end # module Cherby
141
+
@@ -0,0 +1,13 @@
1
+ require 'date'
2
+ require 'cherby/business_object'
3
+
4
+ module Cherby
5
+ class JournalNote < BusinessObject
6
+ @object_name = 'JournalNote'
7
+ @template = 'journal_note'
8
+ @default_values = {
9
+ :details => "",
10
+ }
11
+ end
12
+ end
13
+
@@ -0,0 +1,37 @@
1
+ require 'date'
2
+ require 'cherby/business_object'
3
+
4
+ module Cherby
5
+ class Task < BusinessObject
6
+ @object_name = 'Task'
7
+ @template = 'task'
8
+ @default_values = {
9
+ :status => "New",
10
+ }
11
+
12
+ def id
13
+ self['TaskID']
14
+ end
15
+
16
+ def exists?
17
+ return !id.to_s.empty?
18
+ end
19
+
20
+ # Return True if this Task has important fields differing from the given Task.
21
+ def differs_from?(task)
22
+ return true if self['Status'] != task['Status']
23
+ return false
24
+ end
25
+
26
+ # Add a JournalNote to this Task. Since Tasks cannot directly have JournalNotes
27
+ # associated with them, this just appends the note's content to the Technician Notes
28
+ # field (aka 'CompletionDetails') in the Task.
29
+ def add_journal_note(journal_note)
30
+ message = "\n============================\n" + \
31
+ "Comment added #{journal_note.mod_s} by #{journal_note['CreatedBy']}: " + \
32
+ journal_note['Details'] + "\n\n"
33
+ self['CompletionDetails'] = self['CompletionDetails'] + message
34
+ end
35
+ end
36
+ end # module Cherby
37
+
@@ -0,0 +1,226 @@
1
+ <?xml version="1.0"?>
2
+ <BusinessObject Name="Incident" RecID="{{incident_id}}">
3
+ <FieldList>
4
+ <!-- Fields common to all BusinessObjects -->
5
+ <Field Name="RecID">{{rec_id}}</Field>
6
+ <Field Name="CreatedDateTime">{{created_date_time}}</Field>
7
+ <Field Name="CreatedBy">{{created_by}}</Field>
8
+ <Field Name="CreatedByID"></Field>
9
+ <Field Name="LastModDateTime">{{last_mod_date_time}}</Field>
10
+ <Field Name="LastModBy">{{last_mod_by}}</Field>
11
+ <Field Name="LastModByID"></Field>
12
+ <Field Name="OwnedBy">{{owned_by}}</Field>
13
+ <Field Name="OwnedByTeam">{{owned_by_team}}</Field>
14
+ <Field Name="OwnerID"></Field>
15
+ <Field Name="OwnerTeamID"></Field>
16
+
17
+ <!-- Unused fields? -->
18
+ <Field Name="LastModTimeStamp"/>
19
+
20
+ <Field Name="IncidentID">{{incident_id}}</Field>
21
+ <Field Name="Status">{{status}}</Field>
22
+ <Field Name="StatusDesc"/>
23
+ <Field Name="Service">{{service}}</Field>
24
+ <Field Name="Category">{{category}}</Field>
25
+ <Field Name="SubCategory">{{sub_category}}</Field>
26
+ <Field Name="SpecificsTypeId"/>
27
+ <Field Name="Description">{{description}}</Field>
28
+ <Field Name="Impact">{{impact}}</Field>
29
+ <Field Name="Urgency">{{urgency}}</Field>
30
+ <Field Name="Priority">{{priority}}</Field>
31
+ <Field Name="ClosedDateTime"/>
32
+ <Field Name="ClosedBy"/>
33
+ <Field Name="ClosedByID"/>
34
+ <Field Name="CauseCode"/>
35
+ <Field Name="IsPrivate">FALSE</Field>
36
+ <Field Name="Cost">0</Field>
37
+ <Field Name="CustomerTypeID">{{customer_type_id}}</Field>
38
+ <Field Name="CustomerRecID">{{customer_rec_id}}</Field>
39
+ <Field Name="CloseDescription"/>
40
+ <Field Name="LinkedProblem"/>
41
+ <Field Name="ConfigItemTypeID"/>
42
+ <Field Name="ConfigItemRecID"/>
43
+ <Field Name="IncidentDurationInDays">0.00</Field>
44
+ <Field Name="IncidentType">Service Request</Field>
45
+ <Field Name="RespondBy"/>
46
+ <Field Name="SLAID">93aec497070aea63541fae4004988811547a5a70b9</Field>
47
+ <Field Name="SLAName">Technology Services</Field>
48
+ <Field Name="ResolveBy"/>
49
+ <Field Name="ClosedOn1stCall">FALSE</Field>
50
+ <Field Name="CallSource">e-mail</Field>
51
+ <Field Name="Detail"/>
52
+ <Field Name="ChangeID"/>
53
+ <Field Name="MultipleConfig">FALSE</Field>
54
+ <Field Name="OwnedByEmail"/>
55
+ <Field Name="IncidentDurationInHours">0</Field>
56
+ <Field Name="CustomerDisplayName">{{created_by}}</Field>
57
+ <Field Name="EMailTemplate"/>
58
+ <Field Name="OwnedByManager"/>
59
+ <Field Name="OwnedByManagerEmail"/>
60
+ <Field Name="CreatedByEmail">{{created_by_email}}</Field>
61
+ <Field Name="InitialITContact">{{created_by}}</Field>
62
+ <Field Name="InitialITContactEmail">{{created_by_email}}</Field>
63
+ <Field Name="PendingReason"/>
64
+ <Field Name="ReviewByDate"/>
65
+ <Field Name="ProjectCode"/>
66
+ <Field Name="Task"/>
67
+ <Field Name="PhaseRecordStatus">Complete</Field>
68
+ <Field Name="PhaseClassifyStatus">Complete</Field>
69
+ <Field Name="PhaseInvestigateStatus">In Progress</Field>
70
+ <Field Name="PhaseRFWStatus">Not Required</Field>
71
+ <Field Name="PhaseResolveStatus">Required</Field>
72
+ <Field Name="PhaseCloseStatus">Required</Field>
73
+ <Field Name="PhaseApprovalsStatus">Not Required</Field>
74
+ <Field Name="WrkflwCurrentPhase"/>
75
+ <Field Name="OutsourcedService">FALSE</Field>
76
+ <Field Name="OutsourcedVendorID"/>
77
+ <Field Name="OutsourcedVendorName"/>
78
+ <Field Name="Stat_NumberOfTouches">2</Field>
79
+ <Field Name="Stat_FirstCallResolution">TRUE</Field>
80
+ <Field Name="Stat_IncidentEscalated">FALSE</Field>
81
+ <Field Name="Stat_NumberOfEscalations">0</Field>
82
+ <Field Name="Stat_24x7ElapsedTime">0</Field>
83
+ <Field Name="Stat_IncidentReopened">FALSE</Field>
84
+ <Field Name="Stat_DateTimeResponded">0001-01-01T00:00:00</Field>
85
+ <Field Name="Stat_ResponseTime">0</Field>
86
+ <Field Name="Stat_SLAResponseBreached">FALSE</Field>
87
+ <Field Name="Stat_SLAResolutionBreached">FALSE</Field>
88
+ <Field Name="Stat_TotalDLHOfIncident">0</Field>
89
+ <Field Name="Test_embeddedFormPicker"/>
90
+ <Field Name="LastModByEmail">{{last_mod_by_email}}</Field>
91
+ <Field Name="Temp_reopen">FALSE</Field>
92
+ <Field Name="Temp_pending">FALSE</Field>
93
+ <Field Name="Temp_open">FALSE</Field>
94
+ <Field Name="Temp_status_set">FALSE</Field>
95
+ <Field Name="Temp_Active">FALSE</Field>
96
+ <Field Name="Temp_Accepted">FALSE</Field>
97
+ <Field Name="Temp_Resolved">FALSE</Field>
98
+ <Field Name="Temp_Assigned">FALSE</Field>
99
+ <Field Name="ServiceID">8D71BF81-EBA3-4152-BF34-DDF4931D0A0D</Field>
100
+ <Field Name="PendingPreviousStatus"/>
101
+ <Field Name="SelfServiceUrgent"/>
102
+ <Field Name="SelfServiceMultipleUsers"/>
103
+ <Field Name="SelfServiceAltContactInfo"/>
104
+ <Field Name="SelfServiceContactInfoCorrect">FALSE</Field>
105
+ <Field Name="MatchingText">SHRM Store Conference Setup</Field>
106
+ <Field Name="Notes"/>
107
+ <Field Name="NoteEntry"/>
108
+ <Field Name="AutomateAvailable">FALSE</Field>
109
+ <Field Name="SLAIDForCustomer"/>
110
+ <Field Name="SLAIDForService">93aec497070aea63541fae4004988811547a5a70b9</Field>
111
+ <Field Name="SLAIDForCI"/>
112
+ <Field Name="LinkedSLAs"> , 93aec497070aea63541fae4004988811547a5a70b9 , </Field>
113
+ <Field Name="SLANameForCI"/>
114
+ <Field Name="SLANameForCustomer"/>
115
+ <Field Name="SLANameForService">Technology Services</Field>
116
+ <Field Name="TEMP_showSLAStuff">FALSE</Field>
117
+ <Field Name="VendorName"/>
118
+ <Field Name="VendorID"/>
119
+ <Field Name="ReasonForResolveByBreach"/>
120
+ <Field Name="ConfigItemDisplayName"/>
121
+ <Field Name="CICritical">FALSE</Field>
122
+ <Field Name="ResolveByBreachNotes"/>
123
+ <Field Name="OneStepPicker"/>
124
+ <Field Name="ShowAllServices">FALSE</Field>
125
+ <Field Name="ShowContactInformation">FALSE</Field>
126
+ <Field Name="ServiceEntitlements"/>
127
+ <Field Name="ServiceCustomerIsEntitled">FALSE</Field>
128
+ <Field Name="ServiceGroup">{{service_group}}</Field>
129
+ <Field Name="Environment">PRD</Field>
130
+ <Field Name="Temp_EscalationTeam">Network and Systems Operations</Field>
131
+ <Field Name="PriorityGroup">Less Critical</Field>
132
+ <Field Name="BlockID"/>
133
+ <Field Name="ApprovalRequired">No</Field>
134
+ <Field Name="Approved">FALSE</Field>
135
+ <Field Name="OwnedByNonCherwellUser">FALSE</Field>
136
+ <Field Name="Temp_SurveyCreated">FALSE</Field>
137
+ <Field Name="RespondByWarning">2011-10-24T08:12:00</Field>
138
+ <Field Name="ResolveByWarning">2011-10-27T13:11:52</Field>
139
+ <Field Name="Stat_SLAResolutionBreachedWarning">FALSE</Field>
140
+ <Field Name="Stat_SLAResponseBreachedWarning">FALSE</Field>
141
+ <Field Name="ReasonForRespondByBreach"/>
142
+ <Field Name="RespondByBreachNotes"/>
143
+ <Field Name="HRAuthorized">FALSE</Field>
144
+ <Field Name="CMDBUpdate"/>
145
+ <Field Name="ServiceOutageStart">0001-01-01T00:00:00</Field>
146
+ <Field Name="ServiceOutageEnd">0001-01-01T00:00:00</Field>
147
+ <Field Name="Temp_ServiceGroup">{{service_group}}</Field>
148
+ <Field Name="ClosureCode"/>
149
+ <Field Name="Temp_responded"/>
150
+ <Field Name="TasksExist">FALSE</Field>
151
+ <Field Name="ResolvedDate">0001-01-01T00:00:00</Field>
152
+ <Field Name="CustomerDept">Strategy and Architecture</Field>
153
+ <Field Name="Temp_DefaultTeam">Service Desk</Field>
154
+ <Field Name="SubcategoryNonHR">{{sub_category_non_hr}}</Field>
155
+ <Field Name="ParatureTicketID"/>
156
+ <Field Name="CustomerEmail">{{customer_email}}</Field>
157
+ <Field Name="JIRAID">{{jira_id}}</Field>
158
+ </FieldList>
159
+ <RelationshipList>
160
+ <!--
161
+ <Relationship Name="IncidentLinkedToCustomer" TargetObjectName="Customer" Type="Linked">
162
+ <BusinessObject Name="ADCustomers">Yudkovsky, Sergey</BusinessObject>
163
+ </Relationship>
164
+
165
+ <Relationship Name="IncidentLinkedToCustomer" TargetObjectID="9337c2311b8e8044aa3e2a48c4a95a9f5555815126" TargetObjectName="Customer" Type="Linked">
166
+ <BusinessObject Name="ADCustomers" RecID="93bddda849f81c4ad9ed8d4e158523372c31f24072">Moelk, Brian</BusinessObject>
167
+ </Relationship>
168
+
169
+ <Relationship Name="Incident Links SLA" TargetObjectID="933c73c2163058a1ca063b4a879ae21e1e5133f57c" TargetObjectName="SLA" Type="Linked">
170
+ <BusinessObject Name="SLA" RecID="93aec497070aea63541fae4004988811547a5a70b9">Technology Services</BusinessObject>
171
+ </Relationship>
172
+
173
+ <Relationship Name="Incident Has Tasks" TargetObjectID="9355d5ed41e384ff345b014b6cb1c6e748594aea5b" TargetObjectName="Task" Type="Owns">
174
+ <BusinessObject Name="Task" RecID="93be05329e0fcf411b5e574030a626b90bd297469f"></BusinessObject>
175
+ </Relationship>
176
+
177
+ <Relationship Name="Incident has Service" TargetObjectID="9366b3bb9e94d86b5d5f434ff3b657c4ec5bfa3bb3" TargetObjectName="Service" Type="Linked">
178
+ <BusinessObject Name="Service" RecID="8D71BF81-EBA3-4152-BF34-DDF4931D0A0D">SHRM Store</BusinessObject>
179
+ </Relationship>
180
+
181
+ <Relationship Name="Incident has Service SLA" TargetObjectID="933c73c2163058a1ca063b4a879ae21e1e5133f57c" TargetObjectName="SLA" Type="Linked">
182
+ <BusinessObject Name="SLA" RecID="93aec497070aea63541fae4004988811547a5a70b9">Technology Services</BusinessObject>
183
+ </Relationship>
184
+
185
+ <Relationship Name="Incident Links Service Group" TargetObjectID="93ae4fd3af6355802e542349ebafd6deab1dca3cfb" TargetObjectName="ServiceGroup" Type="Linked">
186
+ <BusinessObject Name="ServiceGroup" RecID="93ae5021c82196035ca3374845956ce9a66eeb08cc">Technology Services</BusinessObject>
187
+ </Relationship>
188
+ -->
189
+
190
+ <!-- Include this only if there's a related object to link to
191
+ <Relationship Name="Incident related to other similar incidents" TargetObjectID="6dd53665c0c24cab86870a21cf6434ae" TargetObjectName="Incident" Type="Linked">
192
+ <BusinessObject Name="Incident" RecID="{{parent_id}}">{{parent_id}}</BusinessObject>
193
+ </Relationship>
194
+ -->
195
+
196
+ <!-- This chunk including WebsiteForm is required when using Service = "Websites (SHRM)".
197
+ Unfortunately, it seems to require that the WebsiteForm object be created first.
198
+ -->
199
+ <!--
200
+ <Relationship Name="IncidentHasSpecifics" TargetObjectID="" TargetObjectName="Specifics" Type="Owns">
201
+ <BusinessObject Name="WebsiteForm" RecID="">
202
+ <FieldList>
203
+ <Field Name="RecID"></Field>
204
+ <Field Name="CreatedDateTime">{{now}}</Field>
205
+ <Field Name="CreatedBy">Yudkovsky, Sergey</Field>
206
+ <Field Name="CreatedByID">93b10b33b94d800e69d2294942a6fc764cbfa82940</Field>
207
+ <Field Name="SpecificTypeID"></Field>
208
+ <Field Name="SpecificTypeName">Website Form</Field>
209
+ <Field Name="ParentId">{{parent_id}}</Field>
210
+ <Field Name="LastModDateTime">{{now}}</Field>
211
+ <Field Name="LastModBy">Yudkovsky, Sergey</Field>
212
+ <Field Name="LastModByID">93b10b33b94d800e69d2294942a6fc764cbfa82940</Field>
213
+ <Field Name="ADCustomersID"/>
214
+ <Field Name="NeedByDate">0001-01-01T00:00:00</Field>
215
+ <Field Name="URLInfo">jira.shrm.org</Field>
216
+ <Field Name="EstimatedTime"/>
217
+ <Field Name="SprintTime"/>
218
+ </FieldList>
219
+ </BusinessObject>
220
+ </Relationship>
221
+ -->
222
+
223
+ </RelationshipList>
224
+ </BusinessObject>
225
+
226
+