usps-imis-api 0.9.3 → 0.9.5
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/Readme.md +14 -3
- data/lib/usps/imis/api.rb +9 -4
- data/lib/usps/imis/business_object.rb +4 -2
- data/lib/usps/imis/config.rb +7 -3
- data/lib/usps/imis/errors/mapper_error.rb +1 -1
- data/lib/usps/imis/mapper.rb +20 -10
- data/lib/usps/imis/panels/base_panel.rb +2 -0
- data/lib/usps/imis/query.rb +7 -5
- data/lib/usps/imis/requests.rb +7 -5
- data/lib/usps/imis/version.rb +1 -1
- data/lib/usps/imis.rb +4 -2
- data/spec/lib/usps/imis/mapper_spec.rb +24 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0e2478447353e616e857b13ac4b3c87d62c8f8d9a499a1ef8610355d91181539
|
|
4
|
+
data.tar.gz: f00d8b31112b0295834eca9a74176318d5e51f7596d9fa2082267671763255e6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8dda7fe4ff5daab7fc34df6ca508005f38295987f626cc73762fbb6f641404e5f9ad9f4108815362f98333e806c2366b7143c94cf3a861d6729cdc77034b2a09
|
|
7
|
+
data.tar.gz: d9b0f87d187cdb1e10d66ee439a750d659e87ae033fe3c7848d87dc96f211895041ff7196fa88d1f60b27fdfb8a7e39ce03b34a5e74e4be8c88445cb16b01540
|
data/Gemfile.lock
CHANGED
data/Readme.md
CHANGED
|
@@ -34,7 +34,7 @@ Usps::Imis.configure do |config|
|
|
|
34
34
|
config.password = ENV['IMIS_PASSWORD']
|
|
35
35
|
|
|
36
36
|
# These options will use these defaults
|
|
37
|
-
config.logger = Logger.new($stdout)
|
|
37
|
+
config.logger = ActiveSupport::TaggedLogging.new(Logger.new($stdout))
|
|
38
38
|
config.logger.level = :info
|
|
39
39
|
end
|
|
40
40
|
```
|
|
@@ -213,13 +213,24 @@ end
|
|
|
213
213
|
### Field Mapper
|
|
214
214
|
|
|
215
215
|
For fields that have already been mapped between the ITCom database and iMIS, you can use the
|
|
216
|
-
Mapper class to further simplify the update
|
|
216
|
+
Mapper class to further simplify the fetch / update interfaces:
|
|
217
|
+
|
|
218
|
+
```ruby
|
|
219
|
+
mm = api.mapper.fetch(:mm)
|
|
220
|
+
mm = api.mapper[:mm]
|
|
221
|
+
```
|
|
217
222
|
|
|
218
223
|
```ruby
|
|
219
224
|
api.mapper.update(mm: 15)
|
|
220
225
|
```
|
|
221
226
|
|
|
222
|
-
For simplicity, you can also call `
|
|
227
|
+
For simplicity, you can also call `fetch` (or simply use Hash access syntax) and `update` on the
|
|
228
|
+
`Api` class directly:
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
api.fetch(:mm)
|
|
232
|
+
api[:mm]
|
|
233
|
+
```
|
|
223
234
|
|
|
224
235
|
```ruby
|
|
225
236
|
api.update(mm: 15)
|
data/lib/usps/imis/api.rb
CHANGED
|
@@ -128,11 +128,14 @@ module Usps
|
|
|
128
128
|
@mapper ||= Mapper.new(self)
|
|
129
129
|
end
|
|
130
130
|
|
|
131
|
+
# Convenience alias for reading mapped fields
|
|
132
|
+
#
|
|
133
|
+
def fetch(field_key) = mapper.fetch(field_key)
|
|
134
|
+
alias [] fetch
|
|
135
|
+
|
|
131
136
|
# Convenience alias for updating mapped fields
|
|
132
137
|
#
|
|
133
|
-
def update(data)
|
|
134
|
-
mapper.update(data)
|
|
135
|
-
end
|
|
138
|
+
def update(data) = mapper.update(data)
|
|
136
139
|
|
|
137
140
|
# Convenience accessor for available Panel objects, each using this instance as its parent
|
|
138
141
|
# +Api+
|
|
@@ -147,10 +150,12 @@ module Usps
|
|
|
147
150
|
|
|
148
151
|
private
|
|
149
152
|
|
|
153
|
+
def logger = Imis.logger('Api')
|
|
154
|
+
|
|
150
155
|
# Authenticate to the iMIS API, and store the access token and expiration time
|
|
151
156
|
#
|
|
152
157
|
def authenticate
|
|
153
|
-
|
|
158
|
+
logger.debug 'Authenticating with iMIS'
|
|
154
159
|
|
|
155
160
|
uri = URI(File.join(Imis.configuration.hostname, AUTHENTICATION_PATH))
|
|
156
161
|
req = Net::HTTP::Post.new(uri)
|
|
@@ -111,6 +111,8 @@ module Usps
|
|
|
111
111
|
def token = api.token
|
|
112
112
|
def token_expiration = api.token_expiration
|
|
113
113
|
|
|
114
|
+
def logger = Imis.logger('BusinessObject')
|
|
115
|
+
|
|
114
116
|
# Construct a business object API endpoint address
|
|
115
117
|
#
|
|
116
118
|
def uri(id: nil)
|
|
@@ -164,7 +166,7 @@ module Usps
|
|
|
164
166
|
request = Net::HTTP::Get.new(uri)
|
|
165
167
|
result = submit(uri, authorize(request))
|
|
166
168
|
result = Data.from_json(result.body)
|
|
167
|
-
JSON.pretty_generate(result).split("\n").each {
|
|
169
|
+
JSON.pretty_generate(result).split("\n").each { logger.debug " -> #{it}" }
|
|
168
170
|
result
|
|
169
171
|
end
|
|
170
172
|
|
|
@@ -174,7 +176,7 @@ module Usps
|
|
|
174
176
|
request.body = JSON.dump(body)
|
|
175
177
|
result = submit(uri, authorize(request))
|
|
176
178
|
result = Data.from_json(result.body)
|
|
177
|
-
JSON.pretty_generate(result).split("\n").each {
|
|
179
|
+
JSON.pretty_generate(result).split("\n").each { logger.debug " -> #{it}" }
|
|
178
180
|
result
|
|
179
181
|
end
|
|
180
182
|
end
|
data/lib/usps/imis/config.rb
CHANGED
|
@@ -8,15 +8,15 @@ module Usps
|
|
|
8
8
|
IMIS_ROOT_URL_PROD = 'https://portal.americasboatingclub.org'
|
|
9
9
|
IMIS_ROOT_URL_DEV = 'https://abcdev.imiscloud.com'
|
|
10
10
|
|
|
11
|
-
attr_accessor :imis_id_query_name, :username, :password
|
|
12
|
-
attr_reader :environment, :logger_level
|
|
11
|
+
attr_accessor :imis_id_query_name, :username, :password
|
|
12
|
+
attr_reader :environment, :logger, :logger_level
|
|
13
13
|
|
|
14
14
|
def initialize
|
|
15
15
|
@environment = defined?(Rails) ? Rails.env : ActiveSupport::StringInquirer.new('development')
|
|
16
16
|
@imis_id_query_name = ENV.fetch('IMIS_ID_QUERY_NAME', nil)
|
|
17
17
|
@username = ENV.fetch('IMIS_USERNAME', nil)
|
|
18
18
|
@password = ENV.fetch('IMIS_PASSWORD', nil)
|
|
19
|
-
@logger = Logger.new($stdout, level: :info)
|
|
19
|
+
@logger = ActiveSupport::TaggedLogging.new(Logger.new($stdout, level: :info))
|
|
20
20
|
|
|
21
21
|
yield self if block_given?
|
|
22
22
|
|
|
@@ -27,6 +27,10 @@ module Usps
|
|
|
27
27
|
@environment = ActiveSupport::StringInquirer.new(env.to_s)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def logger=(logger)
|
|
31
|
+
@logger = ActiveSupport::TaggedLogging.new(logger)
|
|
32
|
+
end
|
|
33
|
+
|
|
30
34
|
# Environment-specific API endpoint hostname
|
|
31
35
|
#
|
|
32
36
|
# @return The API hostname for the current environment
|
|
@@ -19,7 +19,7 @@ module Usps
|
|
|
19
19
|
#
|
|
20
20
|
def message
|
|
21
21
|
<<~MESSAGE.chomp
|
|
22
|
-
Mapper does not recognize field: "#{metadata[:
|
|
22
|
+
Mapper does not recognize field: "#{metadata[:field_key]}".
|
|
23
23
|
Please report what data you are attempting to work with to ITCom leadership.
|
|
24
24
|
MESSAGE
|
|
25
25
|
end
|
data/lib/usps/imis/mapper.rb
CHANGED
|
@@ -28,6 +28,14 @@ module Usps
|
|
|
28
28
|
@api.imis_id = imis_id if imis_id
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
def fetch(field_key)
|
|
32
|
+
missing_mapping!(field_key) unless FIELD_MAPPING.key?(field_key.to_sym)
|
|
33
|
+
|
|
34
|
+
business_object_name, field = FIELD_MAPPING[field_key]
|
|
35
|
+
api.on(business_object_name)[field]
|
|
36
|
+
end
|
|
37
|
+
alias [] fetch
|
|
38
|
+
|
|
31
39
|
# Update a member's data on multiple affected business objects by arbitrary field names
|
|
32
40
|
#
|
|
33
41
|
# Does not require knowing which business object / iMIS-specific field name to use
|
|
@@ -57,25 +65,27 @@ module Usps
|
|
|
57
65
|
|
|
58
66
|
private
|
|
59
67
|
|
|
60
|
-
def
|
|
61
|
-
|
|
68
|
+
def logger = Imis.logger('Mapper')
|
|
69
|
+
|
|
70
|
+
def map_update(field_key)
|
|
71
|
+
missing_mapping!(field_key) unless FIELD_MAPPING.key?(field_key.to_sym)
|
|
62
72
|
|
|
63
|
-
business_object_name, field = FIELD_MAPPING[
|
|
73
|
+
business_object_name, field = FIELD_MAPPING[field_key.to_sym]
|
|
64
74
|
yield(business_object_name, field)
|
|
65
75
|
end
|
|
66
76
|
|
|
67
|
-
def missing_mapping!(
|
|
77
|
+
def missing_mapping!(field_key)
|
|
68
78
|
unless ENV['TESTING']
|
|
69
79
|
# :nocov:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"
|
|
74
|
-
|
|
80
|
+
"Mapper does not know how to handle field \"#{field_key}\".\n\n" \
|
|
81
|
+
'You can use api.put_fields(business_object_name, { field_name => value }) ' \
|
|
82
|
+
"if you know the business object and iMIS-specific field name.\n\n"
|
|
83
|
+
.split("\n")
|
|
84
|
+
.each { logger.warn(it) }
|
|
75
85
|
# :nocov:
|
|
76
86
|
end
|
|
77
87
|
|
|
78
|
-
raise Errors::MapperError.new({
|
|
88
|
+
raise Errors::MapperError.new({ field_key: })
|
|
79
89
|
end
|
|
80
90
|
end
|
|
81
91
|
end
|
data/lib/usps/imis/query.rb
CHANGED
|
@@ -43,7 +43,7 @@ module Usps
|
|
|
43
43
|
# Iterate through all results from the query
|
|
44
44
|
#
|
|
45
45
|
def each(&)
|
|
46
|
-
|
|
46
|
+
logger.info 'Running IQA Query on iMIS'
|
|
47
47
|
|
|
48
48
|
items = []
|
|
49
49
|
find_each { items << it }
|
|
@@ -57,14 +57,14 @@ module Usps
|
|
|
57
57
|
count = 0
|
|
58
58
|
|
|
59
59
|
while result['HasNext']
|
|
60
|
-
|
|
60
|
+
logger.info 'Fetching IQA Query page'
|
|
61
61
|
|
|
62
62
|
result = fetch
|
|
63
63
|
|
|
64
64
|
count += result['Count'] || 0
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
JSON.pretty_generate(result).split("\n").each {
|
|
65
|
+
logger.info " -> #{count} / #{result['TotalCount']} #{'item'.pluralize(count)}"
|
|
66
|
+
logger.debug ' -> Query page data:'
|
|
67
|
+
JSON.pretty_generate(result).split("\n").each { logger.debug " -> #{it}" }
|
|
68
68
|
|
|
69
69
|
items = result['Items']['$values'].map { it.except('$type') }
|
|
70
70
|
@offset = result['NextOffset']
|
|
@@ -87,6 +87,8 @@ module Usps
|
|
|
87
87
|
def path = "#{QUERY_PATH}?#{query_params.merge(QueryName: query_name, Offset: offset).to_query}"
|
|
88
88
|
def uri = URI(File.join(Imis.configuration.hostname, path))
|
|
89
89
|
def fetch = JSON.parse(submit(uri, authorize(Net::HTTP::Get.new(uri))).body)
|
|
90
|
+
|
|
91
|
+
def logger = Imis.logger('Query')
|
|
90
92
|
end
|
|
91
93
|
end
|
|
92
94
|
end
|
data/lib/usps/imis/requests.rb
CHANGED
|
@@ -7,6 +7,8 @@ module Usps
|
|
|
7
7
|
module Requests
|
|
8
8
|
private
|
|
9
9
|
|
|
10
|
+
def logger = Imis.logger
|
|
11
|
+
|
|
10
12
|
def client(uri)
|
|
11
13
|
Net::HTTP.new(uri.host, uri.port).tap do |http|
|
|
12
14
|
http.use_ssl = true
|
|
@@ -20,20 +22,20 @@ module Usps
|
|
|
20
22
|
#
|
|
21
23
|
def authorize(request)
|
|
22
24
|
if token_expiration < Time.now
|
|
23
|
-
|
|
25
|
+
logger.debug 'Token expired: re-authenticating with iMIS'
|
|
24
26
|
authenticate
|
|
25
27
|
end
|
|
26
28
|
request.tap { it.add_field('Authorization', "Bearer #{token}") }
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def submit(uri, request)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
sanitized_request_body(request).split("\n").each {
|
|
32
|
+
logger.info 'Submitting request to iMIS'
|
|
33
|
+
logger.debug " -> #{request.class.name.demodulize.upcase} #{uri}"
|
|
34
|
+
sanitized_request_body(request).split("\n").each { logger.debug " -> #{it}" }
|
|
33
35
|
client(uri).request(request).tap do |result|
|
|
34
36
|
raise Errors::ResponseError.from(result) unless result.is_a?(Net::HTTPSuccess)
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
logger.info 'Request succeeded'
|
|
37
39
|
end
|
|
38
40
|
end
|
|
39
41
|
|
data/lib/usps/imis/version.rb
CHANGED
data/lib/usps/imis.rb
CHANGED
|
@@ -11,6 +11,8 @@ require 'active_support/core_ext/object/to_query'
|
|
|
11
11
|
require 'active_support/core_ext/enumerable'
|
|
12
12
|
require 'active_support/string_inquirer'
|
|
13
13
|
require 'logger'
|
|
14
|
+
require 'active_support/isolated_execution_state' # Fix costant loading issue with TaggedLogging
|
|
15
|
+
require 'active_support/tagged_logging'
|
|
14
16
|
|
|
15
17
|
# Internal requires
|
|
16
18
|
require_relative 'imis/config'
|
|
@@ -43,9 +45,9 @@ module Usps
|
|
|
43
45
|
configuration
|
|
44
46
|
end
|
|
45
47
|
|
|
46
|
-
# Logger
|
|
48
|
+
# Logger (with optional nested tags) to write to
|
|
47
49
|
#
|
|
48
|
-
def logger = configuration.logger
|
|
50
|
+
def logger(*tags) = configuration.logger.tagged('iMIS', *tags)
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
53
|
end
|
|
@@ -13,6 +13,30 @@ describe Usps::Imis::Mapper do
|
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
describe '#fetch' do
|
|
17
|
+
before { api.imis_id = 31092 }
|
|
18
|
+
|
|
19
|
+
it 'fetches a mapped field' do
|
|
20
|
+
expect(api.mapper.fetch(:mm)).to be_a(Integer)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'supports Hash access syntax' do
|
|
24
|
+
expect(api.mapper[:mm]).to be_a(Integer)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'supports Hash access syntax on the Api directly' do
|
|
28
|
+
expect(api[:mm]).to be_a(Integer)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'raises for unmapped updates' do
|
|
32
|
+
expect { api.mapper.fetch(:another) }.to raise_error(
|
|
33
|
+
Usps::Imis::Errors::MapperError,
|
|
34
|
+
%(Mapper does not recognize field: "another".\n) \
|
|
35
|
+
'Please report what data you are attempting to work with to ITCom leadership.'
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
16
40
|
describe '#update' do
|
|
17
41
|
before { api.imis_id = 31092 }
|
|
18
42
|
|