usps-imis-api 1.0.0.pre.rc.4 → 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 -3
- data/Gemfile.lock +61 -27
- data/Readme.md +168 -32
- data/lib/usps/imis/api.rb +27 -39
- data/lib/usps/imis/business_object.rb +93 -40
- data/lib/usps/imis/config.rb +27 -10
- 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/panels/education.rb +33 -0
- data/lib/usps/imis/panels/vsc.rb +32 -0
- 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 +29 -3
- data/lib/usps/imis/version.rb +1 -1
- data/lib/usps/imis.rb +16 -13
- data/spec/lib/usps/imis/api_spec.rb +26 -13
- data/spec/lib/usps/imis/business_object_spec.rb +47 -13
- data/spec/lib/usps/imis/config_spec.rb +30 -4
- 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 +3 -0
- data/usps-imis-api.gemspec +3 -1
- metadata +43 -15
- 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 -65
- data/lib/usps/imis/panel/education.rb +0 -113
- data/lib/usps/imis/panel/vsc.rb +0 -111
- data/spec/lib/usps/imis/panel/base_panel_spec.rb +0 -32
- data/spec/lib/usps/imis/panel/education_spec.rb +0 -55
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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
plugins:
|
|
2
2
|
- rubocop-rspec
|
|
3
3
|
|
|
4
4
|
AllCops:
|
|
@@ -32,8 +32,6 @@ Layout/SpaceInsideHashLiteralBraces:
|
|
|
32
32
|
EnforcedStyleForEmptyBraces: no_space
|
|
33
33
|
Layout/SpaceInsideArrayLiteralBrackets:
|
|
34
34
|
EnforcedStyle: no_space
|
|
35
|
-
Layout/LineLength:
|
|
36
|
-
Max: 100
|
|
37
35
|
|
|
38
36
|
Lint/UnusedMethodArgument:
|
|
39
37
|
Enabled: true
|
data/Gemfile.lock
CHANGED
|
@@ -1,81 +1,115 @@
|
|
|
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
|
+
activesupport (~> 8.0)
|
|
5
6
|
|
|
6
7
|
GEM
|
|
7
8
|
remote: https://rubygems.org/
|
|
8
9
|
specs:
|
|
9
|
-
|
|
10
|
+
activesupport (8.1.0)
|
|
11
|
+
base64
|
|
12
|
+
bigdecimal
|
|
13
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
14
|
+
connection_pool (>= 2.2.5)
|
|
15
|
+
drb
|
|
16
|
+
i18n (>= 1.6, < 2)
|
|
17
|
+
json
|
|
18
|
+
logger (>= 1.4.2)
|
|
19
|
+
minitest (>= 5.1)
|
|
20
|
+
securerandom (>= 0.3)
|
|
21
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
22
|
+
uri (>= 0.13.1)
|
|
23
|
+
ast (2.4.3)
|
|
24
|
+
base64 (0.3.0)
|
|
25
|
+
bigdecimal (3.3.1)
|
|
26
|
+
concurrent-ruby (1.3.5)
|
|
27
|
+
connection_pool (2.5.4)
|
|
10
28
|
date (3.4.1)
|
|
11
|
-
diff-lcs (1.
|
|
29
|
+
diff-lcs (1.6.2)
|
|
12
30
|
docile (1.4.1)
|
|
13
|
-
dotenv (3.1.
|
|
14
|
-
|
|
31
|
+
dotenv (3.1.8)
|
|
32
|
+
drb (2.2.3)
|
|
33
|
+
erb (5.1.1)
|
|
34
|
+
i18n (1.14.7)
|
|
35
|
+
concurrent-ruby (~> 1.0)
|
|
15
36
|
io-console (0.8.1)
|
|
16
37
|
irb (1.15.2)
|
|
17
38
|
pp (>= 0.6.0)
|
|
18
39
|
rdoc (>= 4.0.0)
|
|
19
40
|
reline (>= 0.4.2)
|
|
20
|
-
json (2.
|
|
21
|
-
language_server-protocol (3.17.0.
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
json (2.15.1)
|
|
42
|
+
language_server-protocol (3.17.0.5)
|
|
43
|
+
lint_roller (1.1.0)
|
|
44
|
+
logger (1.7.0)
|
|
45
|
+
minitest (5.26.0)
|
|
46
|
+
parallel (1.27.0)
|
|
47
|
+
parser (3.3.9.0)
|
|
24
48
|
ast (~> 2.4.1)
|
|
25
49
|
racc
|
|
26
50
|
pp (0.6.3)
|
|
27
51
|
prettyprint
|
|
28
52
|
prettyprint (0.2.0)
|
|
53
|
+
prism (1.6.0)
|
|
29
54
|
psych (5.2.6)
|
|
30
55
|
date
|
|
31
56
|
stringio
|
|
32
57
|
racc (1.8.1)
|
|
33
58
|
rainbow (3.1.1)
|
|
34
|
-
rake (13.
|
|
59
|
+
rake (13.3.0)
|
|
35
60
|
rdoc (6.15.0)
|
|
36
61
|
erb
|
|
37
62
|
psych (>= 4.0.0)
|
|
38
63
|
tsort
|
|
39
|
-
regexp_parser (2.
|
|
64
|
+
regexp_parser (2.11.3)
|
|
40
65
|
reline (0.6.2)
|
|
41
66
|
io-console (~> 0.5)
|
|
42
|
-
rspec (3.13.
|
|
67
|
+
rspec (3.13.2)
|
|
43
68
|
rspec-core (~> 3.13.0)
|
|
44
69
|
rspec-expectations (~> 3.13.0)
|
|
45
70
|
rspec-mocks (~> 3.13.0)
|
|
46
|
-
rspec-core (3.13.
|
|
71
|
+
rspec-core (3.13.6)
|
|
47
72
|
rspec-support (~> 3.13.0)
|
|
48
|
-
rspec-expectations (3.13.
|
|
73
|
+
rspec-expectations (3.13.5)
|
|
49
74
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
50
75
|
rspec-support (~> 3.13.0)
|
|
51
|
-
rspec-mocks (3.13.
|
|
76
|
+
rspec-mocks (3.13.6)
|
|
52
77
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
53
78
|
rspec-support (~> 3.13.0)
|
|
54
|
-
rspec-support (3.13.
|
|
55
|
-
rubocop (1.
|
|
79
|
+
rspec-support (3.13.6)
|
|
80
|
+
rubocop (1.81.6)
|
|
56
81
|
json (~> 2.3)
|
|
57
|
-
language_server-protocol (
|
|
82
|
+
language_server-protocol (~> 3.17.0.2)
|
|
83
|
+
lint_roller (~> 1.1.0)
|
|
58
84
|
parallel (~> 1.10)
|
|
59
85
|
parser (>= 3.3.0.2)
|
|
60
86
|
rainbow (>= 2.2.2, < 4.0)
|
|
61
|
-
regexp_parser (>= 2.
|
|
62
|
-
rubocop-ast (>= 1.
|
|
87
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
88
|
+
rubocop-ast (>= 1.47.1, < 2.0)
|
|
63
89
|
ruby-progressbar (~> 1.7)
|
|
64
|
-
unicode-display_width (>= 2.4.0, <
|
|
65
|
-
rubocop-ast (1.
|
|
66
|
-
parser (>= 3.3.
|
|
67
|
-
|
|
68
|
-
|
|
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)
|
|
69
97
|
ruby-progressbar (1.13.0)
|
|
98
|
+
securerandom (0.4.1)
|
|
70
99
|
simplecov (0.22.0)
|
|
71
100
|
docile (~> 1.1)
|
|
72
101
|
simplecov-html (~> 0.11)
|
|
73
102
|
simplecov_json_formatter (~> 0.1)
|
|
74
|
-
simplecov-html (0.13.
|
|
103
|
+
simplecov-html (0.13.2)
|
|
75
104
|
simplecov_json_formatter (0.1.4)
|
|
76
105
|
stringio (3.1.7)
|
|
77
106
|
tsort (0.2.0)
|
|
78
|
-
|
|
107
|
+
tzinfo (2.0.6)
|
|
108
|
+
concurrent-ruby (~> 1.0)
|
|
109
|
+
unicode-display_width (3.2.0)
|
|
110
|
+
unicode-emoji (~> 4.1)
|
|
111
|
+
unicode-emoji (4.1.0)
|
|
112
|
+
uri (1.0.4)
|
|
79
113
|
|
|
80
114
|
PLATFORMS
|
|
81
115
|
arm64-darwin-23
|
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
|
|
@@ -25,11 +25,17 @@ require 'dotenv/load' # Optionally load environment variables from `.env` file
|
|
|
25
25
|
require 'usps/imis'
|
|
26
26
|
|
|
27
27
|
Usps::Imis.configure do |config|
|
|
28
|
-
|
|
29
|
-
config.
|
|
28
|
+
# This will default to `Rails.env` if available.
|
|
29
|
+
config.environment = :development
|
|
30
30
|
|
|
31
|
+
# These options will default to the listed `ENV` variable if available.
|
|
32
|
+
config.imis_id_query_name = ENV['IMIS_ID_QUERY_NAME']
|
|
31
33
|
config.username = ENV['IMIS_USERNAME']
|
|
32
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
|
|
33
39
|
end
|
|
34
40
|
```
|
|
35
41
|
|
|
@@ -75,23 +81,72 @@ You can also manually set the current ID, if you already have it for a given mem
|
|
|
75
81
|
api.imis_id = imis_id
|
|
76
82
|
```
|
|
77
83
|
|
|
78
|
-
|
|
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
|
|
79
95
|
|
|
80
96
|
To fetch member data, run e.g.:
|
|
81
97
|
|
|
82
98
|
```ruby
|
|
83
|
-
|
|
99
|
+
data = api.on('ABC_ASC_Individual_Demog').get
|
|
100
|
+
```
|
|
84
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
|
+
```
|
|
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
|
|
85
112
|
data = api.on('ABC_ASC_Individual_Demog').get
|
|
113
|
+
data['TotMMS']
|
|
114
|
+
data.raw['EntityTypeName']
|
|
86
115
|
```
|
|
87
116
|
|
|
88
|
-
|
|
117
|
+
Alias: `read`
|
|
89
118
|
|
|
90
|
-
|
|
119
|
+
#### GET Field
|
|
120
|
+
|
|
121
|
+
To fetch a specific field from member data, run e.g.:
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
tot_mms = api.on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
You can also access fields directly on the Business Object or Panel like a Hash:
|
|
128
|
+
|
|
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.:
|
|
91
138
|
|
|
92
139
|
```ruby
|
|
93
|
-
api.
|
|
140
|
+
data = api.on('ABC_ASC_Individual_Demog').get_fields('TotMMS', 'MMS_Updated')
|
|
141
|
+
```
|
|
94
142
|
|
|
143
|
+
Alias: `fetch_all`
|
|
144
|
+
|
|
145
|
+
#### PUT Fields
|
|
146
|
+
|
|
147
|
+
To update member data, run e.g.:
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
95
150
|
data = { 'MMS_Updated' => Time.now.strftime('%Y-%m-%dT%H:%M:%S'), 'TotMMS' => new_total }
|
|
96
151
|
update = api.on('ABC_ASC_Individual_Demog').put_fields(data)
|
|
97
152
|
```
|
|
@@ -99,19 +154,23 @@ update = api.on('ABC_ASC_Individual_Demog').put_fields(data)
|
|
|
99
154
|
This method fetches the current data structure, and filters it down to just what you want to
|
|
100
155
|
update, to reduce the likelihood of update collisions or type validation failures.
|
|
101
156
|
|
|
102
|
-
|
|
157
|
+
Alias: `patch`
|
|
158
|
+
|
|
159
|
+
#### PUT
|
|
103
160
|
|
|
104
161
|
To update member data, run e.g.:
|
|
105
162
|
|
|
106
163
|
```ruby
|
|
107
|
-
api.imis_id = 31092
|
|
108
|
-
|
|
109
164
|
update = api.on('ABC_ASC_Individual_Demog').put(complete_imis_object)
|
|
110
165
|
```
|
|
111
166
|
|
|
112
|
-
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).
|
|
170
|
+
|
|
171
|
+
Alias: `update`
|
|
113
172
|
|
|
114
|
-
|
|
173
|
+
#### POST
|
|
115
174
|
|
|
116
175
|
To create new member data, run e.g.:
|
|
117
176
|
|
|
@@ -121,17 +180,17 @@ created = api.on('ABC_ASC_Individual_Demog').post(complete_imis_object)
|
|
|
121
180
|
|
|
122
181
|
This method requires a complete iMIS data structure.
|
|
123
182
|
|
|
124
|
-
|
|
183
|
+
Alias: `create`
|
|
184
|
+
|
|
185
|
+
#### DELETE
|
|
125
186
|
|
|
126
187
|
To remove member data, run e.g.:
|
|
127
188
|
|
|
128
189
|
```ruby
|
|
129
|
-
api.imis_id = 31092
|
|
130
|
-
|
|
131
190
|
api.on('ABC_ASC_Individual_Demog').delete
|
|
132
191
|
```
|
|
133
192
|
|
|
134
|
-
|
|
193
|
+
Alias: `destroy`
|
|
135
194
|
|
|
136
195
|
### QUERY
|
|
137
196
|
|
|
@@ -140,19 +199,38 @@ Run an IQA Query
|
|
|
140
199
|
`query_params` is a hash of shape: `{ param_name => param_value }`
|
|
141
200
|
|
|
142
201
|
```ruby
|
|
143
|
-
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
|
|
144
211
|
```
|
|
145
212
|
|
|
146
213
|
### Field Mapper
|
|
147
214
|
|
|
148
215
|
For fields that have already been mapped between the ITCom database and iMIS, you can use the
|
|
149
|
-
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
|
+
```
|
|
150
222
|
|
|
151
223
|
```ruby
|
|
152
224
|
api.mapper.update(mm: 15)
|
|
153
225
|
```
|
|
154
226
|
|
|
155
|
-
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
|
+
```
|
|
156
234
|
|
|
157
235
|
```ruby
|
|
158
236
|
api.update(mm: 15)
|
|
@@ -168,24 +246,40 @@ For supported panels (usually, business objects with composite identity keys), y
|
|
|
168
246
|
with them in the same general way:
|
|
169
247
|
|
|
170
248
|
```ruby
|
|
171
|
-
vsc = Usps::Imis::
|
|
172
|
-
|
|
173
|
-
vsc.api.imis_id = 6374
|
|
249
|
+
vsc = Usps::Imis::Panels::Vsc.new(imis_id: 6374)
|
|
174
250
|
|
|
175
251
|
vsc.get(1417)
|
|
176
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
|
+
|
|
177
261
|
created = vsc.create(certificate: 'E136924', year: 2024, count: 42)
|
|
178
|
-
|
|
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
|
|
179
271
|
|
|
180
272
|
vsc.update(certificate: 'E136924', year: 2024, count: 43, ordinal: ordinal)
|
|
181
273
|
|
|
274
|
+
vsc.put_fields(ordinal, 'Quantity' => 44)
|
|
275
|
+
|
|
182
276
|
vsc.destroy(ordinal)
|
|
183
277
|
```
|
|
184
278
|
|
|
185
279
|
If you already have an iMIS ID to work with, you can pass that in immediately:
|
|
186
280
|
|
|
187
281
|
```ruby
|
|
188
|
-
vsc = Usps::Imis::
|
|
282
|
+
vsc = Usps::Imis::Panels::Vsc.new(imis_id: imis_id)
|
|
189
283
|
```
|
|
190
284
|
|
|
191
285
|
Panels are also accessible directly from the API object:
|
|
@@ -202,11 +296,11 @@ previous value.
|
|
|
202
296
|
|
|
203
297
|
```ruby
|
|
204
298
|
api.with(31092) do
|
|
205
|
-
# These
|
|
299
|
+
# These requests are identical:
|
|
206
300
|
|
|
207
|
-
on('ABC_ASC_Individual_Demog') {
|
|
301
|
+
on('ABC_ASC_Individual_Demog') { put_fields('TotMMS' => 15) }
|
|
208
302
|
|
|
209
|
-
on('ABC_ASC_Individual_Demog').
|
|
303
|
+
on('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15)
|
|
210
304
|
|
|
211
305
|
mapper.update(mm: 15)
|
|
212
306
|
|
|
@@ -220,12 +314,52 @@ api.with(6374) do
|
|
|
220
314
|
end
|
|
221
315
|
```
|
|
222
316
|
|
|
223
|
-
|
|
317
|
+
```ruby
|
|
318
|
+
api.with(31092) do
|
|
319
|
+
# These requests are identical:
|
|
224
320
|
|
|
225
|
-
|
|
321
|
+
on('ABC_ASC_Individual_Demog') do
|
|
322
|
+
get.raw['Properties']['$values'].find { it['Name'] == 'TotMMS' }['Value']['$value']
|
|
226
323
|
|
|
227
|
-
|
|
228
|
-
|
|
324
|
+
get['TotMMS']
|
|
325
|
+
|
|
326
|
+
get_field('TotMMS')
|
|
327
|
+
|
|
328
|
+
get_fields('TotMMS').first
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
332
|
+
|
|
333
|
+
on('ABC_ASC_Individual_Demog')['TotMMS']
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
# This request fetches the same data, but leaves the iMIS ID selected
|
|
337
|
+
api.with(31092).on('ABC_ASC_Individual_Demog').get_field('TotMMS')
|
|
338
|
+
```
|
|
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
|
+
|
|
360
|
+
## Exception Handling
|
|
361
|
+
|
|
362
|
+
All internal exceptions inherit from `Usps::Imis::Error`.
|
|
229
363
|
|
|
230
364
|
## Automated Testing and Linting
|
|
231
365
|
|
|
@@ -241,6 +375,8 @@ Linting is available by running:
|
|
|
241
375
|
bundle exec rubocop
|
|
242
376
|
```
|
|
243
377
|
|
|
378
|
+
100% branch coverage is enforced on the test suite.
|
|
379
|
+
|
|
244
380
|
### GitHub Actions
|
|
245
381
|
|
|
246
382
|
Testing and linting are automatically run on every push.
|
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 = {
|