restful-trades 0.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,175 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ # File: razor_risk/cassini/applications/route_verb_adaptors/trades/item_get.rb
5
+ #
6
+ # Purpose: Adaptor for Trades microservice's item GET verb
7
+ #
8
+ # Author: Matthew Wilson
9
+ #
10
+ # Copyright (c) 2018, Razor Risk Technologies Pty Ltd
11
+ # All rights reserved.
12
+ #
13
+ # ######################################################################## #
14
+
15
+
16
+ # ##########################################################################
17
+ # requires
18
+
19
+ require 'razor_risk/cassini/applications/rest_framework/verb_handler'
20
+
21
+ require 'razor_risk/razor/connectivity/razor_3/entity_connectors/trades_connector'
22
+
23
+ require 'razor_risk/core/diagnostics/logger'
24
+
25
+ require 'pantheios'
26
+
27
+ # ##########################################################################
28
+ # module
29
+
30
+ module RazorRisk
31
+ module Cassini
32
+ module Applications
33
+ module RouteVerbAdaptors
34
+ module Trades
35
+
36
+ # ##########################################################################
37
+ # classes
38
+
39
+ class ItemGet < RESTFramework::VerbHandler
40
+
41
+ include ::RazorRisk::Razor::Connectivity::Razor3::EntityConnectors
42
+
43
+ include ::RazorRisk::Core::Diagnostics::Logger
44
+
45
+ include ::Pantheios
46
+
47
+ HTTP_VERB = :get
48
+
49
+ HTTP_ACCEPTS = %w{ application/xml application/json text/xml }
50
+
51
+ ROUTE_VARIABLES = %w{
52
+
53
+ id
54
+ }
55
+
56
+ QUERY_PARAMETERS = %w{
57
+
58
+ result-form
59
+ }
60
+
61
+ def handle env, params, request, response
62
+
63
+ trace ParamNames[ :env, :params, :request, :response ], env, params, request, response
64
+
65
+ # params
66
+
67
+ id = params['id']
68
+ rf = case rf = (params['result-form'] || '').to_s
69
+ when '', 'default'
70
+ :body
71
+ when 'contexts'
72
+ :contexts
73
+ when 'summary'
74
+ :trade_summary
75
+ when 'trade'
76
+ :trade
77
+ else
78
+ log(:warning) { "unrecognised result-form '#{rf}'" }
79
+ :body
80
+ end
81
+
82
+ # get credentials
83
+
84
+ cr = get_required_credentials
85
+
86
+ # get requester
87
+
88
+ rr = settings.razor_requester
89
+
90
+ # get connector
91
+
92
+ ec = TradesConnector.new(rr, credentials: cr)
93
+
94
+ # issue request
95
+
96
+ qr = ec.get_trade id, indicate_result_by: :qualified_result, result_form: rf
97
+
98
+ log :debug1, "qr(#{qr.class})='#{qr}'"
99
+
100
+ unless qr.succeeded?
101
+
102
+ if false
103
+
104
+ ;
105
+ elsif qr.result.nil?
106
+
107
+ log :debug1, 'failed to retrieve trade'
108
+
109
+ halt *[ 404, {}, "trade with id '#{id}' does not exist" ]
110
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0011')
111
+
112
+ log :debug1, 'failed to retrieve trade'
113
+
114
+ halt *[ 404, {}, "#{r.message}: #{r.details}" ]
115
+ else
116
+
117
+ log :warning, 'failed to retrieve trade'
118
+
119
+ halt *[ 500, {}, qr.failure_qualifier.reasons.join("\n") ]
120
+ end
121
+ end
122
+
123
+ r = qr.result.to_s
124
+
125
+ # return result
126
+
127
+ status 200
128
+
129
+ if false
130
+ elsif request.accept?('application/xml')
131
+
132
+ log :debug1, 'application/xml'
133
+
134
+ content_type 'application/xml'
135
+
136
+ r
137
+ elsif request.accept?('application/json')
138
+
139
+ log :debug1, 'application/json'
140
+
141
+ content_type 'application/json'
142
+
143
+ resp_hash = Hash.from_xml r
144
+
145
+ resp_json = resp_hash
146
+
147
+ JSON.generate resp_json
148
+ elsif request.accept?('text/xml')
149
+
150
+ log :debug1, 'text/xml'
151
+
152
+ content_type 'text/xml'
153
+
154
+ r
155
+ else
156
+
157
+ log :violation, "unexpected failure to match given 'Accept' header '#{request.accept}'"
158
+
159
+ status 500
160
+ end
161
+ end
162
+ end # class ItemGet
163
+
164
+ # ##########################################################################
165
+ # module
166
+
167
+ end # module Trades
168
+ end # module RouteVerbAdaptors
169
+ end # module Applications
170
+ end # module Cassini
171
+ end # module RazorRisk
172
+
173
+ # ############################## end of file ############################# #
174
+
175
+
@@ -0,0 +1,271 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ # File: razor_risk/cassini/applications/route_verb_adaptors/trades/item_post.rb
5
+ #
6
+ # Purpose: Adaptor for Trades microservice's item POST verb
7
+ #
8
+ # Copyright (c) 2018, Razor Risk Technologies Pty Ltd
9
+ # All rights reserved.
10
+ #
11
+ # ######################################################################## #
12
+
13
+
14
+ # ##########################################################################
15
+ # requires
16
+
17
+ require 'razor_risk/cassini/applications/rest_framework/verb_handler'
18
+
19
+ require 'razor_risk/razor/connectivity/entity_connectors/exceptions'
20
+
21
+ require 'razor_risk/razor/connectivity/razor_3/entity_connectors/trades_connector'
22
+
23
+ require 'razor_risk/core/diagnostics/logger'
24
+
25
+ require 'pantheios'
26
+
27
+ require 'xqsr3/conversion/integer_parser'
28
+
29
+ # ##########################################################################
30
+ # module
31
+
32
+ module RazorRisk
33
+ module Cassini
34
+ module Applications
35
+ module RouteVerbAdaptors
36
+ module Trades
37
+
38
+ # ##########################################################################
39
+ # classes
40
+
41
+ class ItemPost < RESTFramework::VerbHandler
42
+
43
+ include ::RazorRisk::Razor::Connectivity::Razor3::EntityConnectors
44
+ include ::RazorRisk::Razor::Connectivity::Razor3
45
+
46
+ include ::RazorRisk::Razor::Connectivity::EntityConnectors::Exceptions
47
+
48
+ include ::RazorRisk::Core::Diagnostics::Logger
49
+
50
+ include ::Pantheios
51
+
52
+ include ::Xqsr3::Conversion
53
+
54
+ HTTP_VERB = :post
55
+
56
+ HTTP_ACCEPTS = %w{ application/xml application/json text/xml }
57
+
58
+ ROUTE_VARIABLES = %w{ }
59
+
60
+ QUERY_PARAMETERS = %w{
61
+
62
+ result-form
63
+ }
64
+
65
+ def handle env, params, request, response
66
+
67
+ trace ParamNames[ :env, :params, :request, :response ], env, params, request, response
68
+
69
+ rf = case rf = (params['result-form'] || '').to_s
70
+ when '', 'id'
71
+ :id
72
+ when 'body'
73
+ :body
74
+ else
75
+ log(:warning) { "unrecognised result-form '#{rf}'" }
76
+ :id
77
+ end
78
+
79
+ # read request body (XML)
80
+ #
81
+ # NOTE: For this handler, the input is required to be XML, and it
82
+ # is required that the document has a single top-level node
83
+ # 'portfolios'
84
+
85
+ request.body.rewind
86
+
87
+ body_text = request.body.read
88
+ rq_body = nil
89
+
90
+ case request.content_type
91
+ when 'application/xml', 'text/xml'
92
+
93
+ rq_body = ::Nokogiri.XML body_text
94
+ else
95
+
96
+ log :violation, "unexpected content-type '#{request.content_type}'"
97
+ end
98
+
99
+ # get credentials
100
+
101
+ cr = get_required_credentials
102
+
103
+ # get requester
104
+
105
+ rr = settings.razor_requester
106
+
107
+ # get connector
108
+
109
+ ec = TradesConnector.new(rr, credentials: cr)
110
+
111
+ # issue request
112
+
113
+ begin
114
+
115
+ qr = ec.insert_trade rq_body, indicate_result_by: :qualified_result, result_form: rf
116
+ rescue InvalidRequestContentException => x
117
+
118
+ log :failure, "exception (#{x.class}): #{x}"
119
+
120
+ headers = {
121
+
122
+ 'Content-Type' => 'text/plain',
123
+ }
124
+
125
+ halt 422, headers, x.message
126
+ rescue RazorRequester::InvalidCredentialsException => x
127
+
128
+ log :failure, "exception (#{x.class}): #{x}"
129
+
130
+ headers = {
131
+
132
+ 'Content-Type' => 'text/plain',
133
+ }
134
+
135
+ halt 401, headers, 'Invalid credentials'
136
+ rescue RazorRequester::Exception => x
137
+
138
+ log :failure, "exception (#{x.class}): #{x}"
139
+
140
+ headers = {
141
+
142
+ 'Content-Type' => 'text/plain',
143
+ }
144
+
145
+ halt 500, headers, x.message
146
+ end
147
+
148
+ log :debug1, "qr(#{qr.class})='#{qr}'"
149
+
150
+ unless qr.succeeded?
151
+
152
+ if qr.result.nil?
153
+
154
+ if r = qr.failure_qualifier.reasons.lookup?('RZ0010')
155
+
156
+ log :debug1, 'failed to insert trade: duplicate record'
157
+
158
+ halt 422, {}, "#{r.message}: #{r.details}"
159
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0014')
160
+
161
+ log :debug1, 'failed to insert trade: invalid data'
162
+
163
+ halt 422, {}, "#{r.message}: #{r.details}"
164
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0022')
165
+
166
+ log :debug1, 'failed to insert trade: invalid trade'
167
+
168
+ halt 422, {}, "#{r.message}: #{r.details}"
169
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0027')
170
+
171
+ log :debug1, 'failed to insert trade: invalid netting agreement'
172
+
173
+ halt 422, {}, "#{r.message}: #{r.details}"
174
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0028')
175
+
176
+ log :debug1, 'failed to insert trade: invalid What-if batch number'
177
+
178
+ halt 422, {}, "#{r.message}: #{r.details}"
179
+ else
180
+
181
+ log :warning, 'failed to insert trade'
182
+
183
+ halt 500, {}, qr.failure_qualifier.reasons.join("\n")
184
+ end
185
+ else
186
+
187
+ log :warning, 'trade inserted with mixed success'
188
+
189
+ body = ::Nokogiri.XML(qr.result)
190
+
191
+ builder = ::Nokogiri::XML::Builder.new({}, body.root) do |xml|
192
+
193
+ xml.reasons do
194
+
195
+ qr.failure_qualifier.reasons.each do |reason|
196
+
197
+ xml.reason do
198
+
199
+ details = reason.details
200
+ details &&= details.split("\n").map { |detail| detail.strip }.reject { |detail| detail.empty? }.join("\n")
201
+
202
+ xml.code reason.code if reason.code
203
+ xml.message reason.message if reason.message
204
+ xml.details details if details
205
+ end
206
+ end
207
+ end
208
+ end
209
+
210
+ halt 422, { 'Content-Type' => 'application/xml' }, body.to_xml
211
+ end
212
+ end
213
+
214
+ status 201
215
+
216
+ r = qr.result.to_s
217
+
218
+ if rf == :id
219
+
220
+ r
221
+ else
222
+
223
+ if false
224
+ elsif request.accept?('application/xml')
225
+
226
+ log :debug1, 'application/xml'
227
+
228
+ content_type 'application/xml'
229
+
230
+ r
231
+ elsif request.accept?('application/json')
232
+
233
+ log :debug1, 'application/json'
234
+
235
+ content_type 'application/json'
236
+
237
+ resp_hash = Hash.from_xml r
238
+
239
+ resp_json = resp_hash
240
+
241
+ JSON.generate resp_json
242
+ elsif request.accept?('text/xml')
243
+
244
+ log :debug1, 'text/xml'
245
+
246
+ content_type 'text/xml'
247
+
248
+ r
249
+ else
250
+
251
+ log :violation, "unexpected failure to match given 'Accept' header '#{request.accept}'"
252
+
253
+ status 500
254
+ end
255
+ end
256
+ end
257
+ end # class ItemDelete
258
+
259
+ # ##########################################################################
260
+ # module
261
+
262
+ end # module Trades
263
+ end # module RouteVerbAdaptors
264
+ end # module Applications
265
+ end # module Cassini
266
+ end # module RazorRisk
267
+
268
+ # ############################## end of file ############################# #
269
+
270
+
271
+
@@ -0,0 +1,249 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ # File: razor_risk/cassini/applications/route_verb_adaptors/trades/item_put.rb
5
+ #
6
+ # Purpose: Adaptor for Trades microservice's item PUT verb
7
+ #
8
+ # Copyright (c) 2018, Razor Risk Technologies Pty Ltd
9
+ # All rights reserved.
10
+ #
11
+ # ######################################################################## #
12
+
13
+
14
+ # ##########################################################################
15
+ # requires
16
+
17
+ require 'razor_risk/cassini/applications/rest_framework/verb_handler'
18
+ require 'razor_risk/razor/connectivity/entity_connectors/exceptions'
19
+ require 'razor_risk/razor/connectivity/razor_3/entity_connectors/trades_connector'
20
+
21
+ require 'razor_risk/cassini/util/conversion_util'
22
+
23
+ require 'razor_risk/core/diagnostics/logger'
24
+
25
+ require 'pantheios'
26
+
27
+ require 'xqsr3/conversion/integer_parser'
28
+
29
+ # ##########################################################################
30
+ # module
31
+
32
+ module RazorRisk
33
+ module Cassini
34
+ module Applications
35
+ module RouteVerbAdaptors
36
+ module Trades
37
+
38
+ # ##########################################################################
39
+ # classes
40
+
41
+ class ItemPut < RESTFramework::VerbHandler
42
+
43
+ include ::RazorRisk::Razor::Connectivity::Razor3::EntityConnectors
44
+ include ::RazorRisk::Razor::Connectivity::Razor3
45
+ include ::RazorRisk::Razor::Connectivity::EntityConnectors::Exceptions
46
+
47
+ include ::RazorRisk::Cassini::Util::ConversionUtil
48
+
49
+ include ::RazorRisk::Core::Diagnostics::Logger
50
+
51
+ include ::Pantheios
52
+
53
+ include ::Xqsr3::Conversion
54
+
55
+ HTTP_VERB = :put
56
+ HTTP_ACCEPTS = %w{
57
+ application/xml
58
+ application/json
59
+ text/xml
60
+ }
61
+ ROUTE_VARIABLES = %w{
62
+ id
63
+ }
64
+ QUERY_PARAMETERS = %w{}
65
+
66
+ def handle env, params, request, response
67
+
68
+ trace ParamNames[ :env, :params, :request, :response ], env, params, request, response
69
+
70
+ id = params['id']
71
+
72
+ # read request body (XML)
73
+ #
74
+ # NOTE: For this handler, the input is required to be XML, and it
75
+ # is required that the document has a single top-level node 'portfolios'
76
+
77
+ request.body.rewind
78
+
79
+ body_text = request.body.read
80
+ rq_body = nil
81
+
82
+ case request.content_type
83
+ when 'application/xml', 'text/xml'
84
+
85
+ rq_body = ::Nokogiri.XML body_text
86
+ else
87
+
88
+ log :violation, "unexpected content-type '#{request.content_type}'"
89
+ end
90
+
91
+ # get credentials
92
+
93
+ cr = get_required_credentials
94
+
95
+ # get requester
96
+
97
+ rr = settings.razor_requester
98
+
99
+ # get connector
100
+
101
+ ec = TradesConnector.new(rr, credentials: cr)
102
+
103
+ # issue request
104
+
105
+ begin
106
+
107
+ qr = ec.update_or_insert_trade(
108
+ id,
109
+ rq_body,
110
+ indicate_result_by: :qualified_result
111
+ )
112
+ rescue InvalidRequestContentException => x
113
+
114
+ log :failure, "exception (#{x.class}): #{x}"
115
+
116
+ headers = {
117
+
118
+ 'Content-Type' => 'text/plain',
119
+ }
120
+
121
+ halt 422, headers, x.message
122
+ rescue RazorRequester::InvalidCredentialsException => x
123
+
124
+ log :failure, "exception (#{x.class}): #{x}"
125
+
126
+ headers = {
127
+
128
+ 'Content-Type' => 'text/plain',
129
+ }
130
+
131
+ halt 401, headers, 'Invalid credentials'
132
+ rescue RazorRequester::Exception => x
133
+
134
+ log :failure, "exception (#{x.class}): #{x}"
135
+
136
+ headers = {
137
+
138
+ 'Content-Type' => 'text/plain',
139
+ }
140
+
141
+ halt 500, headers, x.message
142
+ end
143
+
144
+ log :debug1, "qr(#{qr.class})='#{qr}'"
145
+
146
+ unless qr.succeeded?
147
+
148
+ if qr.result.nil?
149
+
150
+ if r = qr.failure_qualifier.reasons.lookup?('RZ0010')
151
+
152
+ log :debug1, 'failed to update trade: duplicate record'
153
+
154
+ halt 422, {}, "#{r.message}: #{r.details}"
155
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0014')
156
+
157
+ log :debug1, 'failed to update trade: invalid data'
158
+
159
+ halt 422, {}, "#{r.message}: #{r.details}"
160
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0022')
161
+
162
+ log :debug1, 'failed to update trade: invalid trade'
163
+
164
+ halt 422, {}, "#{r.message}: #{r.details}"
165
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0027')
166
+
167
+ log :debug1, 'failed to update trade: invalid netting agreement'
168
+
169
+ halt 422, {}, "#{r.message}: #{r.details}"
170
+ elsif r = qr.failure_qualifier.reasons.lookup?('RZ0028')
171
+
172
+ log :debug1, 'failed to update trade: invalid What-if batch number'
173
+
174
+ halt 422, {}, "#{r.message}: #{r.details}"
175
+ else
176
+
177
+ log :warning, 'failed to update trade'
178
+
179
+ halt 500, {}, qr.failure_qualifier.reasons.join("\n")
180
+ end
181
+ else
182
+
183
+ log :warning, 'trade updated with mixed success'
184
+
185
+ resp_body = ::Nokogiri.XML(qr.result)
186
+
187
+ ::Nokogiri::XML::Builder.new({}, resp_body.root) do |xml|
188
+ xml.reasons do
189
+ qr.failure_qualifier.reasons.each do |reason|
190
+ xml.reason do
191
+ details = reason.details
192
+ details &&= details.split("\n")
193
+ .map { |detail| detail.strip }
194
+ .reject { |detail| detail.empty? }
195
+ .join("\n")
196
+ xml.code reason.code if reason.code
197
+ xml.message reason.message if reason.message
198
+ xml.details details if details
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ if request.accept? 'application/xml'
205
+ headers = { 'Content-Type' => 'application/xml' }
206
+ body = resp_body.to_xml
207
+ elsif request.accept? 'text/xml'
208
+ headers = { 'Content-Type' => 'text/xml' }
209
+ body = resp_body.to_xml
210
+ elsif request.accept? 'application/json'
211
+ headers = { 'Content-Type' => 'application/json' }
212
+ body = convert_XML_to_JSON resp_body, { scheme: :gdata }
213
+ else
214
+ log(:violation) { "unexpected failure to match given 'Accept' header '#{request.accept}'" }
215
+ headers = { 'Content-Type' => 'text/xml' }
216
+ body = resp_body.to_xml
217
+ end
218
+
219
+ halt 422, headers, body
220
+ end
221
+ end
222
+
223
+ case qr.result
224
+ when :update
225
+
226
+ status 204
227
+ when :insert
228
+
229
+ status 201
230
+ else
231
+
232
+ log :violation, "Unkown trade action '#{qr.result}'"
233
+ status 500
234
+ end
235
+ end
236
+ end # class ItemDelete
237
+
238
+ # ##########################################################################
239
+ # module
240
+
241
+ end # module Trades
242
+ end # module RouteVerbAdaptors
243
+ end # module Applications
244
+ end # module Cassini
245
+ end # module RazorRisk
246
+
247
+ # ############################## end of file ############################# #
248
+
249
+
@@ -0,0 +1,8 @@
1
+
2
+ require 'razor_risk/cassini/applications/route_verb_adaptors/trades/collection_get'
3
+ require 'razor_risk/cassini/applications/route_verb_adaptors/trades/item_get'
4
+ require 'razor_risk/cassini/applications/route_verb_adaptors/trades/item_delete'
5
+ require 'razor_risk/cassini/applications/route_verb_adaptors/trades/item_post'
6
+ require 'razor_risk/cassini/applications/route_verb_adaptors/trades/item_put'
7
+ require 'razor_risk/cassini/applications/route_verb_adaptors/trades/collection_post'
8
+