usps-imis-api 1.0.0.pre.rc.5 → 1.0.0.pre.rc.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/Gemfile.lock +36 -30
- data/Readme.md +140 -32
- data/lib/usps/imis/api.rb +27 -39
- data/lib/usps/imis/business_object.rb +87 -47
- data/lib/usps/imis/config.rb +14 -3
- data/lib/usps/imis/data.rb +72 -0
- data/lib/usps/imis/error.rb +51 -0
- data/lib/usps/imis/errors/api_error.rb +11 -0
- data/lib/usps/imis/errors/config_error.rb +11 -0
- data/lib/usps/imis/errors/locked_id_error.rb +15 -0
- data/lib/usps/imis/errors/mapper_error.rb +29 -0
- data/lib/usps/imis/errors/not_found_error.rb +11 -0
- data/lib/usps/imis/errors/panel_unimplemented_error.rb +34 -0
- data/lib/usps/imis/{error → errors}/response_error.rb +5 -8
- data/lib/usps/imis/errors/unexpected_property_type_error.rb +31 -0
- data/lib/usps/imis/mapper.rb +28 -20
- data/lib/usps/imis/mocks/business_object.rb +47 -0
- data/lib/usps/imis/mocks.rb +11 -0
- data/lib/usps/imis/panels/base_panel.rb +144 -0
- data/lib/usps/imis/{panel → panels}/education.rb +2 -2
- data/lib/usps/imis/{panel → panels}/vsc.rb +2 -2
- data/lib/usps/imis/panels.rb +25 -0
- data/lib/usps/imis/properties.rb +50 -0
- data/lib/usps/imis/query.rb +94 -0
- data/lib/usps/imis/requests.rb +27 -3
- data/lib/usps/imis/version.rb +1 -1
- data/lib/usps/imis.rb +15 -15
- data/spec/lib/usps/imis/api_spec.rb +26 -13
- data/spec/lib/usps/imis/business_object_spec.rb +44 -20
- data/spec/lib/usps/imis/config_spec.rb +2 -2
- data/spec/lib/usps/imis/data_spec.rb +66 -0
- data/spec/lib/usps/imis/{error/api_error_spec.rb → error_spec.rb} +1 -1
- data/spec/lib/usps/imis/{error → errors}/response_error_spec.rb +4 -4
- data/spec/lib/usps/imis/mapper_spec.rb +27 -3
- data/spec/lib/usps/imis/mocks/business_object_spec.rb +65 -0
- data/spec/lib/usps/imis/panels/base_panel_spec.rb +33 -0
- data/spec/lib/usps/imis/panels/education_spec.rb +70 -0
- data/spec/lib/usps/imis/{panel → panels}/vsc_spec.rb +6 -7
- data/spec/lib/usps/imis/properties_spec.rb +19 -0
- data/spec/spec_helper.rb +2 -0
- data/usps-imis-api.gemspec +1 -1
- metadata +28 -16
- data/lib/ext/hash.rb +0 -10
- data/lib/usps/imis/error/api_error.rb +0 -44
- data/lib/usps/imis/error/mapper_error.rb +0 -11
- data/lib/usps/imis/panel/base_panel.rb +0 -101
- data/lib/usps/imis/panel/panel_properties.rb +0 -52
- data/spec/lib/usps/imis/panel/base_panel_spec.rb +0 -32
- data/spec/lib/usps/imis/panel/education_spec.rb +0 -55
- data/spec/lib/usps/imis/panel/panel_properties_spec.rb +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f1db4f3db3cd61b247cdef10a3f017ea8efbe7fbf3f98ed17d80fbaa56947b7
|
|
4
|
+
data.tar.gz: 837b83d46d08d02bd6a27442adde8f5fbf7857050df06efd602583205745dad6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0e49fd7400ee2fb1932a4321944122f9e6864a89901e56b2c2a5f4b342f4426a039bd789e89159bdec3579725af733213ff5b4b9694d6a59d04901506a71f8b6
|
|
7
|
+
data.tar.gz: d9dff6ac6e989b163d009a6fe247fed18645a078f5cc00468f5b4011e47050336d561d4bef30f552c51fe531fec3c567086da4d2d5cd6a54bfe0d4a39246d2ff
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
usps-imis-api (1.0.0.pre.rc.
|
|
4
|
+
usps-imis-api (1.0.0.pre.rc.7)
|
|
5
5
|
activesupport (~> 8.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
activesupport (8.0
|
|
10
|
+
activesupport (8.1.0)
|
|
11
11
|
base64
|
|
12
|
-
benchmark (>= 0.3)
|
|
13
12
|
bigdecimal
|
|
14
13
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
15
14
|
connection_pool (>= 2.2.5)
|
|
16
15
|
drb
|
|
17
16
|
i18n (>= 1.6, < 2)
|
|
17
|
+
json
|
|
18
18
|
logger (>= 1.4.2)
|
|
19
19
|
minitest (>= 5.1)
|
|
20
20
|
securerandom (>= 0.3)
|
|
21
21
|
tzinfo (~> 2.0, >= 2.0.5)
|
|
22
22
|
uri (>= 0.13.1)
|
|
23
|
-
ast (2.4.
|
|
23
|
+
ast (2.4.3)
|
|
24
24
|
base64 (0.3.0)
|
|
25
|
-
benchmark (0.4.1)
|
|
26
25
|
bigdecimal (3.3.1)
|
|
27
26
|
concurrent-ruby (1.3.5)
|
|
28
27
|
connection_pool (2.5.4)
|
|
29
28
|
date (3.4.1)
|
|
30
|
-
diff-lcs (1.
|
|
29
|
+
diff-lcs (1.6.2)
|
|
31
30
|
docile (1.4.1)
|
|
32
|
-
dotenv (3.1.
|
|
31
|
+
dotenv (3.1.8)
|
|
33
32
|
drb (2.2.3)
|
|
34
|
-
erb (5.
|
|
33
|
+
erb (5.1.1)
|
|
35
34
|
i18n (1.14.7)
|
|
36
35
|
concurrent-ruby (~> 1.0)
|
|
37
36
|
io-console (0.8.1)
|
|
@@ -39,70 +38,77 @@ GEM
|
|
|
39
38
|
pp (>= 0.6.0)
|
|
40
39
|
rdoc (>= 4.0.0)
|
|
41
40
|
reline (>= 0.4.2)
|
|
42
|
-
json (2.
|
|
43
|
-
language_server-protocol (3.17.0.
|
|
41
|
+
json (2.15.1)
|
|
42
|
+
language_server-protocol (3.17.0.5)
|
|
43
|
+
lint_roller (1.1.0)
|
|
44
44
|
logger (1.7.0)
|
|
45
45
|
minitest (5.26.0)
|
|
46
|
-
parallel (1.
|
|
47
|
-
parser (3.3.
|
|
46
|
+
parallel (1.27.0)
|
|
47
|
+
parser (3.3.9.0)
|
|
48
48
|
ast (~> 2.4.1)
|
|
49
49
|
racc
|
|
50
50
|
pp (0.6.3)
|
|
51
51
|
prettyprint
|
|
52
52
|
prettyprint (0.2.0)
|
|
53
|
+
prism (1.6.0)
|
|
53
54
|
psych (5.2.6)
|
|
54
55
|
date
|
|
55
56
|
stringio
|
|
56
57
|
racc (1.8.1)
|
|
57
58
|
rainbow (3.1.1)
|
|
58
|
-
rake (13.
|
|
59
|
+
rake (13.3.0)
|
|
59
60
|
rdoc (6.15.0)
|
|
60
61
|
erb
|
|
61
62
|
psych (>= 4.0.0)
|
|
62
63
|
tsort
|
|
63
|
-
regexp_parser (2.
|
|
64
|
+
regexp_parser (2.11.3)
|
|
64
65
|
reline (0.6.2)
|
|
65
66
|
io-console (~> 0.5)
|
|
66
|
-
rspec (3.13.
|
|
67
|
+
rspec (3.13.2)
|
|
67
68
|
rspec-core (~> 3.13.0)
|
|
68
69
|
rspec-expectations (~> 3.13.0)
|
|
69
70
|
rspec-mocks (~> 3.13.0)
|
|
70
|
-
rspec-core (3.13.
|
|
71
|
+
rspec-core (3.13.6)
|
|
71
72
|
rspec-support (~> 3.13.0)
|
|
72
|
-
rspec-expectations (3.13.
|
|
73
|
+
rspec-expectations (3.13.5)
|
|
73
74
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
74
75
|
rspec-support (~> 3.13.0)
|
|
75
|
-
rspec-mocks (3.13.
|
|
76
|
+
rspec-mocks (3.13.6)
|
|
76
77
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
77
78
|
rspec-support (~> 3.13.0)
|
|
78
|
-
rspec-support (3.13.
|
|
79
|
-
rubocop (1.
|
|
79
|
+
rspec-support (3.13.6)
|
|
80
|
+
rubocop (1.81.6)
|
|
80
81
|
json (~> 2.3)
|
|
81
|
-
language_server-protocol (
|
|
82
|
+
language_server-protocol (~> 3.17.0.2)
|
|
83
|
+
lint_roller (~> 1.1.0)
|
|
82
84
|
parallel (~> 1.10)
|
|
83
85
|
parser (>= 3.3.0.2)
|
|
84
86
|
rainbow (>= 2.2.2, < 4.0)
|
|
85
|
-
regexp_parser (>= 2.
|
|
86
|
-
rubocop-ast (>= 1.
|
|
87
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
88
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
87
89
|
ruby-progressbar (~> 1.7)
|
|
88
|
-
unicode-display_width (>= 2.4.0, <
|
|
89
|
-
rubocop-ast (1.
|
|
90
|
-
parser (>= 3.3.
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
91
|
+
rubocop-ast (1.47.1)
|
|
92
|
+
parser (>= 3.3.7.2)
|
|
93
|
+
prism (~> 1.4)
|
|
94
|
+
rubocop-rspec (3.7.0)
|
|
95
|
+
lint_roller (~> 1.1)
|
|
96
|
+
rubocop (~> 1.72, >= 1.72.1)
|
|
93
97
|
ruby-progressbar (1.13.0)
|
|
94
98
|
securerandom (0.4.1)
|
|
95
99
|
simplecov (0.22.0)
|
|
96
100
|
docile (~> 1.1)
|
|
97
101
|
simplecov-html (~> 0.11)
|
|
98
102
|
simplecov_json_formatter (~> 0.1)
|
|
99
|
-
simplecov-html (0.13.
|
|
103
|
+
simplecov-html (0.13.2)
|
|
100
104
|
simplecov_json_formatter (0.1.4)
|
|
101
105
|
stringio (3.1.7)
|
|
102
106
|
tsort (0.2.0)
|
|
103
107
|
tzinfo (2.0.6)
|
|
104
108
|
concurrent-ruby (~> 1.0)
|
|
105
|
-
unicode-display_width (2.
|
|
109
|
+
unicode-display_width (3.2.0)
|
|
110
|
+
unicode-emoji (~> 4.1)
|
|
111
|
+
unicode-emoji (4.1.0)
|
|
106
112
|
uri (1.0.4)
|
|
107
113
|
|
|
108
114
|
PLATFORMS
|
data/Readme.md
CHANGED
|
@@ -13,7 +13,7 @@ gem install usps-imis-api
|
|
|
13
13
|
or add this line to your Gemfile:
|
|
14
14
|
|
|
15
15
|
```ruby
|
|
16
|
-
gem 'usps-imis-api'
|
|
16
|
+
gem 'usps-imis-api'
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Setup
|
|
@@ -32,6 +32,10 @@ Usps::Imis.configure do |config|
|
|
|
32
32
|
config.imis_id_query_name = ENV['IMIS_ID_QUERY_NAME']
|
|
33
33
|
config.username = ENV['IMIS_USERNAME']
|
|
34
34
|
config.password = ENV['IMIS_PASSWORD']
|
|
35
|
+
|
|
36
|
+
# These options will use these defaults
|
|
37
|
+
config.logger = ActiveSupport::TaggedLogging.new(Logger.new($stdout))
|
|
38
|
+
config.logger.level = :info
|
|
35
39
|
end
|
|
36
40
|
```
|
|
37
41
|
|
|
@@ -77,33 +81,72 @@ You can also manually set the current ID, if you already have it for a given mem
|
|
|
77
81
|
api.imis_id = imis_id
|
|
78
82
|
```
|
|
79
83
|
|
|
80
|
-
|
|
84
|
+
#### Without an iMIS ID
|
|
85
|
+
|
|
86
|
+
Running requests without an iMIS ID set will result in query results returned from the API.
|
|
87
|
+
|
|
88
|
+
### Business Object and Panel Actions
|
|
89
|
+
|
|
90
|
+
Business Objects and Panels support the following actions.
|
|
91
|
+
|
|
92
|
+
Panels require passing in the ordinal identifier as an argument, except for `POST`.
|
|
93
|
+
|
|
94
|
+
#### GET
|
|
81
95
|
|
|
82
96
|
To fetch member data, run e.g.:
|
|
83
97
|
|
|
84
98
|
```ruby
|
|
85
|
-
|
|
99
|
+
data = api.on('ABC_ASC_Individual_Demog').get
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
You can also pass in specific field names to filter the returned member data, e.g.:
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
data = api.on('ABC_ASC_Individual_Demog').get('TotMMS', 'MMS_Updated')
|
|
106
|
+
```
|
|
86
107
|
|
|
108
|
+
The response from `get` behaves like a Hash, but directly accesses property values by name.
|
|
109
|
+
If you need to access the rest of the underlying data, use the `raw` method:
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
87
112
|
data = api.on('ABC_ASC_Individual_Demog').get
|
|
113
|
+
data['TotMMS']
|
|
114
|
+
data.raw['EntityTypeName']
|
|
88
115
|
```
|
|
89
116
|
|
|
90
|
-
|
|
117
|
+
Alias: `read`
|
|
118
|
+
|
|
119
|
+
#### GET Field
|
|
91
120
|
|
|
92
121
|
To fetch a specific field from member data, run e.g.:
|
|
93
122
|
|
|
94
123
|
```ruby
|
|
95
|
-
api.imis_id = 31092
|
|
96
|
-
|
|
97
124
|
tot_mms = api.on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
98
125
|
```
|
|
99
126
|
|
|
100
|
-
|
|
127
|
+
You can also access fields directly on the Business Object or Panel like a Hash:
|
|
101
128
|
|
|
102
|
-
|
|
129
|
+
```ruby
|
|
130
|
+
tot_mms = api.on('ABC_ASC_Individual_Demog')['TotMMS']
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Alias: `fetch`
|
|
134
|
+
|
|
135
|
+
#### GET Fields
|
|
136
|
+
|
|
137
|
+
To fetch multiple specific fields from member data, run e.g.:
|
|
103
138
|
|
|
104
139
|
```ruby
|
|
105
|
-
api.
|
|
140
|
+
data = api.on('ABC_ASC_Individual_Demog').get_fields('TotMMS', 'MMS_Updated')
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Alias: `fetch_all`
|
|
106
144
|
|
|
145
|
+
#### PUT Fields
|
|
146
|
+
|
|
147
|
+
To update member data, run e.g.:
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
107
150
|
data = { 'MMS_Updated' => Time.now.strftime('%Y-%m-%dT%H:%M:%S'), 'TotMMS' => new_total }
|
|
108
151
|
update = api.on('ABC_ASC_Individual_Demog').put_fields(data)
|
|
109
152
|
```
|
|
@@ -111,19 +154,23 @@ update = api.on('ABC_ASC_Individual_Demog').put_fields(data)
|
|
|
111
154
|
This method fetches the current data structure, and filters it down to just what you want to
|
|
112
155
|
update, to reduce the likelihood of update collisions or type validation failures.
|
|
113
156
|
|
|
114
|
-
|
|
157
|
+
Alias: `patch`
|
|
158
|
+
|
|
159
|
+
#### PUT
|
|
115
160
|
|
|
116
161
|
To update member data, run e.g.:
|
|
117
162
|
|
|
118
163
|
```ruby
|
|
119
|
-
api.imis_id = 31092
|
|
120
|
-
|
|
121
164
|
update = api.on('ABC_ASC_Individual_Demog').put(complete_imis_object)
|
|
122
165
|
```
|
|
123
166
|
|
|
124
|
-
This method requires a complete iMIS data structure.
|
|
167
|
+
This method requires a complete iMIS data structure. However, any properties not included will be
|
|
168
|
+
left unmodified (meaning this also effectively handles `PATCH`, though iMIS does not accept that
|
|
169
|
+
HTTP verb).
|
|
125
170
|
|
|
126
|
-
|
|
171
|
+
Alias: `update`
|
|
172
|
+
|
|
173
|
+
#### POST
|
|
127
174
|
|
|
128
175
|
To create new member data, run e.g.:
|
|
129
176
|
|
|
@@ -133,17 +180,17 @@ created = api.on('ABC_ASC_Individual_Demog').post(complete_imis_object)
|
|
|
133
180
|
|
|
134
181
|
This method requires a complete iMIS data structure.
|
|
135
182
|
|
|
136
|
-
|
|
183
|
+
Alias: `create`
|
|
184
|
+
|
|
185
|
+
#### DELETE
|
|
137
186
|
|
|
138
187
|
To remove member data, run e.g.:
|
|
139
188
|
|
|
140
189
|
```ruby
|
|
141
|
-
api.imis_id = 31092
|
|
142
|
-
|
|
143
190
|
api.on('ABC_ASC_Individual_Demog').delete
|
|
144
191
|
```
|
|
145
192
|
|
|
146
|
-
|
|
193
|
+
Alias: `destroy`
|
|
147
194
|
|
|
148
195
|
### QUERY
|
|
149
196
|
|
|
@@ -152,19 +199,38 @@ Run an IQA Query
|
|
|
152
199
|
`query_params` is a hash of shape: `{ param_name => param_value }`
|
|
153
200
|
|
|
154
201
|
```ruby
|
|
155
|
-
api.query(query_name, query_params)
|
|
202
|
+
query = api.query(query_name, query_params)
|
|
203
|
+
|
|
204
|
+
query.each do |item|
|
|
205
|
+
# Download all pages of the query, then iterate on the results
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
query.find_each do |item|
|
|
209
|
+
# Iterate one page at a time, fetching new pages automatically
|
|
210
|
+
end
|
|
156
211
|
```
|
|
157
212
|
|
|
158
213
|
### Field Mapper
|
|
159
214
|
|
|
160
215
|
For fields that have already been mapped between the ITCom database and iMIS, you can use the
|
|
161
|
-
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
|
+
```
|
|
162
222
|
|
|
163
223
|
```ruby
|
|
164
224
|
api.mapper.update(mm: 15)
|
|
165
225
|
```
|
|
166
226
|
|
|
167
|
-
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
|
+
```
|
|
168
234
|
|
|
169
235
|
```ruby
|
|
170
236
|
api.update(mm: 15)
|
|
@@ -180,24 +246,40 @@ For supported panels (usually, business objects with composite identity keys), y
|
|
|
180
246
|
with them in the same general way:
|
|
181
247
|
|
|
182
248
|
```ruby
|
|
183
|
-
vsc = Usps::Imis::
|
|
184
|
-
|
|
185
|
-
vsc.api.imis_id = 6374
|
|
249
|
+
vsc = Usps::Imis::Panels::Vsc.new(imis_id: 6374)
|
|
186
250
|
|
|
187
251
|
vsc.get(1417)
|
|
188
252
|
|
|
253
|
+
# All of these options are identical
|
|
254
|
+
#
|
|
255
|
+
vsc.get(1417, 'Quantity').first
|
|
256
|
+
vsc.get(1417)['Quantity']
|
|
257
|
+
vsc[1417, 'Quantity']
|
|
258
|
+
vsc.get(1417).raw['Properties']['$values'].find { it['Name'] == 'Quantity' }['Value']['$value']
|
|
259
|
+
vsc.get_field(1417, 'Quantity')
|
|
260
|
+
|
|
189
261
|
created = vsc.create(certificate: 'E136924', year: 2024, count: 42)
|
|
190
|
-
|
|
262
|
+
|
|
263
|
+
# Get the Ordinal identifier from the response
|
|
264
|
+
#
|
|
265
|
+
# All of these options are identical
|
|
266
|
+
#
|
|
267
|
+
ordinal = created.ordinal
|
|
268
|
+
ordinal = created['Ordinal']
|
|
269
|
+
ordinal = created.raw['Properties']['$values'].find { it['Name'] == 'Ordinal' }['Value']['$value']
|
|
270
|
+
ordinal = created.raw['Identity']['IdentityElements']['$values'][1].to_i # Value is duplicated here
|
|
191
271
|
|
|
192
272
|
vsc.update(certificate: 'E136924', year: 2024, count: 43, ordinal: ordinal)
|
|
193
273
|
|
|
274
|
+
vsc.put_fields(ordinal, 'Quantity' => 44)
|
|
275
|
+
|
|
194
276
|
vsc.destroy(ordinal)
|
|
195
277
|
```
|
|
196
278
|
|
|
197
279
|
If you already have an iMIS ID to work with, you can pass that in immediately:
|
|
198
280
|
|
|
199
281
|
```ruby
|
|
200
|
-
vsc = Usps::Imis::
|
|
282
|
+
vsc = Usps::Imis::Panels::Vsc.new(imis_id: imis_id)
|
|
201
283
|
```
|
|
202
284
|
|
|
203
285
|
Panels are also accessible directly from the API object:
|
|
@@ -216,9 +298,9 @@ previous value.
|
|
|
216
298
|
api.with(31092) do
|
|
217
299
|
# These requests are identical:
|
|
218
300
|
|
|
219
|
-
on('ABC_ASC_Individual_Demog') {
|
|
301
|
+
on('ABC_ASC_Individual_Demog') { put_fields('TotMMS' => 15) }
|
|
220
302
|
|
|
221
|
-
on('ABC_ASC_Individual_Demog').
|
|
303
|
+
on('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15)
|
|
222
304
|
|
|
223
305
|
mapper.update(mm: 15)
|
|
224
306
|
|
|
@@ -237,21 +319,47 @@ api.with(31092) do
|
|
|
237
319
|
# These requests are identical:
|
|
238
320
|
|
|
239
321
|
on('ABC_ASC_Individual_Demog') do
|
|
240
|
-
get['Properties']['$values'].find {
|
|
241
|
-
|
|
322
|
+
get.raw['Properties']['$values'].find { it['Name'] == 'TotMMS' }['Value']['$value']
|
|
323
|
+
|
|
324
|
+
get['TotMMS']
|
|
242
325
|
|
|
243
|
-
|
|
326
|
+
get_field('TotMMS')
|
|
327
|
+
|
|
328
|
+
get_fields('TotMMS').first
|
|
329
|
+
end
|
|
244
330
|
|
|
245
331
|
on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
332
|
+
|
|
333
|
+
on('ABC_ASC_Individual_Demog')['TotMMS']
|
|
246
334
|
end
|
|
247
335
|
|
|
248
336
|
# This request fetches the same data, but leaves the iMIS ID selected
|
|
249
337
|
api.with(31092).on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
250
338
|
```
|
|
251
339
|
|
|
340
|
+
### Data Methods
|
|
341
|
+
|
|
342
|
+
Data responses from the API can be handled as a standard Hash using the `raw` method.
|
|
343
|
+
|
|
344
|
+
If you need to access all of the property values, you can use the `properties` method.
|
|
345
|
+
By default, this will exclude the `ID` and `Ordinal` properties; they can be included with
|
|
346
|
+
`properties(include_ids: true)`.
|
|
347
|
+
|
|
348
|
+
## Test Data Mocking
|
|
349
|
+
|
|
350
|
+
You can use the provided Business Object Mock to generate stub data for rspec:
|
|
351
|
+
|
|
352
|
+
```ruby
|
|
353
|
+
allow(api).to(
|
|
354
|
+
receive(:on).with('ABC_ASC_Individual_Demog').and_return(
|
|
355
|
+
Usps::Imis::Mocks::BusinessObject.new(TotMMS: 2)
|
|
356
|
+
)
|
|
357
|
+
)
|
|
358
|
+
```
|
|
359
|
+
|
|
252
360
|
## Exception Handling
|
|
253
361
|
|
|
254
|
-
All internal exceptions inherit from `Usps::Imis::
|
|
362
|
+
All internal exceptions inherit from `Usps::Imis::Error`.
|
|
255
363
|
|
|
256
364
|
## Automated Testing and Linting
|
|
257
365
|
|
data/lib/usps/imis/api.rb
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'requests'
|
|
4
|
+
require_relative 'business_object'
|
|
5
|
+
require_relative 'mapper'
|
|
6
|
+
require_relative 'query'
|
|
7
|
+
|
|
3
8
|
module Usps
|
|
4
9
|
module Imis
|
|
5
10
|
# The core API wrapper
|
|
@@ -11,10 +16,6 @@ module Usps
|
|
|
11
16
|
#
|
|
12
17
|
AUTHENTICATION_PATH = 'Token'
|
|
13
18
|
|
|
14
|
-
# Endpoint for IQA query requests
|
|
15
|
-
#
|
|
16
|
-
QUERY_PATH = 'api/Query'
|
|
17
|
-
|
|
18
19
|
# API bearer token
|
|
19
20
|
#
|
|
20
21
|
attr_reader :token
|
|
@@ -48,9 +49,9 @@ module Usps
|
|
|
48
49
|
# @param id [Integer, String] iMIS ID to select for future requests
|
|
49
50
|
#
|
|
50
51
|
def imis_id=(id)
|
|
51
|
-
raise
|
|
52
|
+
raise Errors::LockedIdError if lock_imis_id
|
|
52
53
|
|
|
53
|
-
@imis_id = id&.to_i
|
|
54
|
+
@imis_id = id&.to_i
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
# Convert a member's certificate number into an iMIS ID number
|
|
@@ -60,13 +61,12 @@ module Usps
|
|
|
60
61
|
# @return [String] Corresponding iMIS ID
|
|
61
62
|
#
|
|
62
63
|
def imis_id_for(certificate)
|
|
63
|
-
raise
|
|
64
|
+
raise Errors::LockedIdError if lock_imis_id
|
|
64
65
|
|
|
65
66
|
begin
|
|
66
|
-
|
|
67
|
-
@imis_id = result['Items']['$values'][0]['ID']
|
|
67
|
+
self.imis_id = query(Imis.configuration.imis_id_query_name, { certificate: }).first['ID'].to_i
|
|
68
68
|
rescue StandardError
|
|
69
|
-
raise
|
|
69
|
+
raise Errors::NotFoundError, 'Member not found'
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -97,7 +97,7 @@ module Usps
|
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
#
|
|
100
|
+
# Build an IQA Query interface
|
|
101
101
|
#
|
|
102
102
|
# @param query_name [String] Full path of the query in IQA, e.g. +$/_ABC/Fiander/iMIS_ID+
|
|
103
103
|
# @query_params [Hash] Conforms to pattern +{ param_name => param_value }+
|
|
@@ -105,21 +105,7 @@ module Usps
|
|
|
105
105
|
# @return [Hash] Response data from the API
|
|
106
106
|
#
|
|
107
107
|
def query(query_name, query_params = {})
|
|
108
|
-
|
|
109
|
-
path = "#{QUERY_PATH}?#{query_params.to_query}"
|
|
110
|
-
uri = URI(File.join(Imis.configuration.hostname, path))
|
|
111
|
-
request = Net::HTTP::Get.new(uri)
|
|
112
|
-
result = submit(uri, authorize(request))
|
|
113
|
-
JSON.parse(result.body)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
# An instance of +BusinessObject+, using this instance as its parent +Api+
|
|
117
|
-
#
|
|
118
|
-
# @param business_object_name [String] Name of the business object
|
|
119
|
-
# @param url_id [String] Override the ID param of the URL (e.g. used for Panels)
|
|
120
|
-
#
|
|
121
|
-
def business_object(business_object_name, url_id: nil)
|
|
122
|
-
BusinessObject.new(self, business_object_name, url_id:)
|
|
108
|
+
Query.new(self, query_name, query_params)
|
|
123
109
|
end
|
|
124
110
|
|
|
125
111
|
# Run requests as DSL, with specific +BusinessObject+ only maintained for this scope
|
|
@@ -127,15 +113,13 @@ module Usps
|
|
|
127
113
|
# If no block is given, this returns the specified +BusinessObject+.
|
|
128
114
|
#
|
|
129
115
|
# @param business_object_name [String] Name of the business object
|
|
130
|
-
# @param
|
|
116
|
+
# @param ordinal [Integer] Ordinal to build override ID param of the URL (e.g. used for Panels)
|
|
131
117
|
#
|
|
132
|
-
def on(business_object_name,
|
|
133
|
-
object =
|
|
118
|
+
def on(business_object_name, ordinal: nil, &)
|
|
119
|
+
object = BusinessObject.new(self, business_object_name, ordinal:)
|
|
134
120
|
return object unless block_given?
|
|
135
121
|
|
|
136
|
-
|
|
137
|
-
object.tap { |obj| result = obj.instance_eval(&) }
|
|
138
|
-
result
|
|
122
|
+
object.instance_eval(&)
|
|
139
123
|
end
|
|
140
124
|
|
|
141
125
|
# An instance of +Mapper+, using this instance as its parent +Api+
|
|
@@ -144,20 +128,20 @@ module Usps
|
|
|
144
128
|
@mapper ||= Mapper.new(self)
|
|
145
129
|
end
|
|
146
130
|
|
|
131
|
+
# Convenience alias for reading mapped fields
|
|
132
|
+
#
|
|
133
|
+
def fetch(field_key) = mapper.fetch(field_key)
|
|
134
|
+
alias [] fetch
|
|
135
|
+
|
|
147
136
|
# Convenience alias for updating mapped fields
|
|
148
137
|
#
|
|
149
|
-
def update(data)
|
|
150
|
-
mapper.update(data)
|
|
151
|
-
end
|
|
138
|
+
def update(data) = mapper.update(data)
|
|
152
139
|
|
|
153
140
|
# Convenience accessor for available Panel objects, each using this instance as its parent
|
|
154
141
|
# +Api+
|
|
155
142
|
#
|
|
156
143
|
def panels
|
|
157
|
-
@panels ||=
|
|
158
|
-
Panel::Vsc.new(self),
|
|
159
|
-
Panel::Education.new(self)
|
|
160
|
-
)
|
|
144
|
+
@panels ||= Panels.all(self)
|
|
161
145
|
end
|
|
162
146
|
|
|
163
147
|
# Ruby 3.5 instance variable filter
|
|
@@ -166,9 +150,13 @@ module Usps
|
|
|
166
150
|
|
|
167
151
|
private
|
|
168
152
|
|
|
153
|
+
def logger = Imis.logger('Api')
|
|
154
|
+
|
|
169
155
|
# Authenticate to the iMIS API, and store the access token and expiration time
|
|
170
156
|
#
|
|
171
157
|
def authenticate
|
|
158
|
+
logger.debug 'Authenticating with iMIS'
|
|
159
|
+
|
|
172
160
|
uri = URI(File.join(Imis.configuration.hostname, AUTHENTICATION_PATH))
|
|
173
161
|
req = Net::HTTP::Post.new(uri)
|
|
174
162
|
authentication_data = {
|