restful-trades 0.8.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+