usps-imis-api 0.1.3 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a27bda1b2938e0cfedde1da424a7694a001c539deb705032c4e7aefe126361a
4
- data.tar.gz: f2fccb24b0f76b452a6b7b3719e225f6659f53d8e6251be130d920bff1f299dd
3
+ metadata.gz: 3bb98ea050e0d9e6b21b9c67b3e1cc7f74020781556015cc4c03e6b748a8cf3d
4
+ data.tar.gz: 8e309c38ebb754244a278de5b4968a6bd917c78d43271a042b0ab5e81846ea10
5
5
  SHA512:
6
- metadata.gz: 6a86560e9f859589317faf46dc524105d2b77b2e25d869c6eec604fa1f98592ed4bdf59a6675078e89345782ab45017fdf34f5895d99cf3944473fccf05e9faf
7
- data.tar.gz: aea9d7c488dec4f017a3252d5294cc9f9fa03eed3e374bbd4d9cc0926c9e76b6c725df5a65ea6eca3314e483153e80be05002917fa49aab8993884fe4cfbd3fd
6
+ metadata.gz: b8ac2e1b390b4f1c6922eb2bd48202aff6015af2ebd9a577572e61d4c24d4219c89ee85bc0c76438fd0c97a020c10b60c021fe95a7819bc260a282d7c56a83b8
7
+ data.tar.gz: 35aa8c10cc792f75ef6df018264e1171077598a74076193ea083dfd7edb754ed76173531acff8904df00d70adad9506dc844bce4b94d68537e1eca821d7c784d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- usps-imis-api (0.1.3)
4
+ usps-imis-api (0.2.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/Readme.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # USPS iMIS API for Ruby
2
2
 
3
- ![Gem Version](https://img.shields.io/gem/v/usps-imis-api)
3
+ [![Gem Version](https://img.shields.io/gem/v/usps-imis-api)](https://rubygems.org/gems/usps-imis-api)
4
4
 
5
5
  ## Installation
6
6
 
@@ -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', '>= 0.1.1'
16
+ gem 'usps-imis-api', '>= 0.2.0'
17
17
  ```
18
18
 
19
19
  ## Setup
@@ -112,7 +112,7 @@ Update only specific fields on a business object for the current member
112
112
  `fields` is a hash of shape: `{ field_name => new_value }`
113
113
 
114
114
  ```ruby
115
- api.put(business_object_name, fields)
115
+ api.put_fields(business_object_name, fields)
116
116
  ```
117
117
 
118
118
  Run an IQA Query
@@ -132,10 +132,36 @@ Mapper class to further simplify the update interface:
132
132
  api.mapper.update(mm: 15)
133
133
  ```
134
134
 
135
+ For simplicity, you can also call `update` on the `Api` class directly:
136
+
137
+ ```ruby
138
+ api.update(mm: 15)
139
+ ```
140
+
135
141
  If there is no known mapping for the requested field, the Mapper will give up, but will provide
136
142
  you with the standard API call syntax, and will suggest you inform ITCom leadership of the new
137
143
  mapping you need.
138
144
 
145
+ ### Panels
146
+
147
+ For supported panels (usually, business objects with composite identity keys), you can interact
148
+ with them in the same general way:
149
+
150
+ ```ruby
151
+ vsc = Imis::Panel::Vsc.new
152
+
153
+ vsc.api.imis_id = 6374
154
+
155
+ vsc.get(1417)
156
+
157
+ created = vsc.create(certificate: 'E136924', year: 2024, count: 42)
158
+ ordinal = created['Properties']['$values'][1]['Value']['$value']
159
+
160
+ vsc.update(certificate: 'E136924', year: 2024, count: 43, ordinal: ordinal)
161
+
162
+ vsc.destroy(ordinal)
163
+ ```
164
+
139
165
  ### DSL Mode
140
166
 
141
167
  Instead of manually setting the current iMIS ID, then running individual queries, you can instead
@@ -144,9 +170,15 @@ previous value.
144
170
 
145
171
  ```ruby
146
172
  api.with(31092) do
147
- # These two requests are identical:
173
+ # These three requests are identical:
174
+
148
175
  put('ABC_ASC_Individual_Demog', { 'TotMMS' => 15 })
176
+
149
177
  mapper.update(mm: 15)
178
+
179
+ update(mm: 15)
180
+
181
+ panels.vsc.get(1417)
150
182
  end
151
183
  ```
152
184
 
data/lib/imis/api.rb CHANGED
@@ -5,6 +5,7 @@ module Imis
5
5
  AUTHENTICATION_PATH = 'Token'
6
6
  API_PATH = 'api'
7
7
  QUERY_PATH = 'api/Query'
8
+ PANELS = Struct.new(:vsc)
8
9
 
9
10
  attr_reader :token, :token_expiration, :imis_id
10
11
 
@@ -39,8 +40,8 @@ module Imis
39
40
 
40
41
  # Get a business object for the current member
41
42
  #
42
- def get(business_object_name)
43
- uri = uri_for(business_object_name)
43
+ def get(business_object_name, url_id: nil)
44
+ uri = uri_for(business_object_name, url_id: url_id)
44
45
  request = Net::HTTP::Get.new(uri)
45
46
  result = submit(uri, authorize(request))
46
47
  JSON.parse(result.body)
@@ -50,15 +51,42 @@ module Imis
50
51
  #
51
52
  # fields - hash of shape: { field_name => new_value }
52
53
  #
53
- def put(business_object_name, fields)
54
- uri = uri_for(business_object_name)
55
- request = Net::HTTP::Put.new(uri)
54
+ def put_fields(business_object_name, fields, url_id: nil)
56
55
  updated = filter_fields(business_object_name, fields)
57
- request.body = JSON.dump(updated)
56
+ put(business_object_name, updated, url_id: url_id)
57
+ end
58
+
59
+ # Update a business object for the current member
60
+ #
61
+ def put(business_object_name, body, url_id: nil)
62
+ uri = uri_for(business_object_name, url_id: url_id)
63
+ request = Net::HTTP::Put.new(uri)
64
+ request.body = JSON.dump(body)
58
65
  result = submit(uri, authorize(request))
59
66
  JSON.parse(result.body)
60
67
  end
61
68
 
69
+ # Create a business object for the current member
70
+ #
71
+ def post(business_object_name, body, url_id: nil)
72
+ uri = uri_for(business_object_name, url_id: url_id)
73
+ request = Net::HTTP::Post.new(uri)
74
+ request.body = JSON.dump(body)
75
+ result = submit(uri, authorize(request))
76
+ JSON.parse(result.body)
77
+ end
78
+
79
+ # Remove a business object for the current member
80
+ #
81
+ # Returns empty string on success
82
+ #
83
+ def delete(business_object_name, url_id: nil)
84
+ uri = uri_for(business_object_name, url_id: url_id)
85
+ request = Net::HTTP::Delete.new(uri)
86
+ result = submit(uri, authorize(request))
87
+ result.body
88
+ end
89
+
62
90
  # Run an IQA Query
63
91
  #
64
92
  # query_name - the full path of the query in IQA, e.g. `$/_ABC/Fiander/iMIS_ID`
@@ -77,6 +105,12 @@ module Imis
77
105
  @mapper ||= Mapper.new(self)
78
106
  end
79
107
 
108
+ def panels
109
+ @panels ||= PANELS.new(
110
+ Panel::Vsc.new(self)
111
+ )
112
+ end
113
+
80
114
  def update(data)
81
115
  mapper.update(data)
82
116
  end
@@ -105,8 +139,10 @@ module Imis
105
139
 
106
140
  # Construct a business object API endpoint address
107
141
  #
108
- def uri_for(business_object_name)
109
- URI(File.join(imis_hostname, "#{API_PATH}/#{business_object_name}/#{imis_id}"))
142
+ def uri_for(business_object_name, url_id: nil)
143
+ url_id ||= imis_id
144
+ url_id = CGI.escape(url_id)
145
+ URI(File.join(imis_hostname, "#{API_PATH}/#{business_object_name}/#{url_id}"))
110
146
  end
111
147
 
112
148
  def submit(uri, request)
data/lib/imis/mapper.rb CHANGED
@@ -10,8 +10,8 @@ module Imis
10
10
 
11
11
  attr_reader :api
12
12
 
13
- def initialize(api)
14
- @api = api
13
+ def initialize(api = nil)
14
+ @api = api || Api.new
15
15
  end
16
16
 
17
17
  # Update a member's data on multiple affected business objects by arbitrary field names
@@ -30,7 +30,7 @@ module Imis
30
30
  end
31
31
 
32
32
  updates.map do |business_object_name, field_updates|
33
- api.put(business_object_name, field_updates)
33
+ api.put_fields(business_object_name, field_updates)
34
34
  end
35
35
  end
36
36
 
@@ -49,7 +49,7 @@ module Imis
49
49
  unless ENV['TESTING']
50
50
  warn(
51
51
  "Mapper does not know how to handle field \"#{field_name}\".\n\n" \
52
- 'You can use api.put(business_object_name, { field_name => value }) ' \
52
+ 'You can use api.put_fields(business_object_name, { field_name => value }) ' \
53
53
  "if you know the business object and iMIS-specific field name.\n\n"
54
54
  )
55
55
  end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Imis
4
+ module Panel
5
+ class Vsc
6
+ BUSINESS_OBJECT = 'ABC_ASC_Vessel_Safety_Checks'
7
+
8
+ attr_reader :api
9
+
10
+ def initialize(api = nil)
11
+ @api = api || Api.new
12
+ end
13
+
14
+ def get(ordinal)
15
+ api.get(BUSINESS_OBJECT, url_id: "~#{api.imis_id}|#{ordinal}")
16
+ end
17
+
18
+ def create(data)
19
+ api.post(BUSINESS_OBJECT, payload(data), url_id: '')
20
+ end
21
+
22
+ def update(data)
23
+ api.put(BUSINESS_OBJECT, payload(data), url_id: "~#{api.imis_id}|#{data[:ordinal]}")
24
+ end
25
+
26
+ def destroy(ordinal)
27
+ api.delete(BUSINESS_OBJECT, url_id: "~#{api.imis_id}|#{ordinal}")
28
+ end
29
+
30
+ private
31
+
32
+ # rubocop:disable Metrics/MethodLength
33
+ def payload(data)
34
+ {
35
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts',
36
+ 'EntityTypeName' => 'ABC_ASC_Vessel_Safety_Checks',
37
+ 'PrimaryParentEntityTypeName' => 'Party',
38
+ 'Identity' => {
39
+ '$type' => 'Asi.Soa.Core.DataContracts.IdentityData, Asi.Contracts',
40
+ 'EntityTypeName' => 'ABC_ASC_Vessel_Safety_Checks',
41
+ 'IdentityElements' => {
42
+ '$type' =>
43
+ 'System.Collections.ObjectModel.Collection`1[[System.String, mscorlib]], mscorlib',
44
+ '$values' => [api.imis_id]
45
+ }
46
+ },
47
+ 'PrimaryParentIdentity' => {
48
+ '$type' => 'Asi.Soa.Core.DataContracts.IdentityData, Asi.Contracts',
49
+ 'EntityTypeName' => 'Party',
50
+ 'IdentityElements' => {
51
+ '$type' =>
52
+ 'System.Collections.ObjectModel.Collection`1[[System.String, mscorlib]], mscorlib',
53
+ '$values' => [api.imis_id]
54
+ }
55
+ },
56
+ 'Properties' => {
57
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyDataCollection, Asi.Contracts',
58
+ '$values' => [
59
+ {
60
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
61
+ 'Name' => 'ID',
62
+ 'Value' => api.imis_id
63
+ },
64
+ (
65
+ if data[:ordinal]
66
+ {
67
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
68
+ 'Name' => 'Ordinal',
69
+ 'Value' => {
70
+ '$type' => 'System.Int32',
71
+ '$value' => data[:ordinal]
72
+ }
73
+ }
74
+ end
75
+ ),
76
+ {
77
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
78
+ 'Name' => 'Source_System',
79
+ 'Value' => 'Manual ITCom Entry'
80
+ },
81
+ {
82
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
83
+ 'Name' => 'ABC_ECertificate',
84
+ 'Value' => data[:certificate]
85
+ },
86
+ {
87
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
88
+ 'Name' => 'Activity_Type',
89
+ 'Value' => 'VSC'
90
+ },
91
+ {
92
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
93
+ 'Name' => 'Description',
94
+ 'Value' => 'Vessel Safety Checks'
95
+ },
96
+ {
97
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
98
+ 'Name' => 'Effective_Date',
99
+ 'Value' => "#{data[:year]}-12-01T00:00:00"
100
+ },
101
+ {
102
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
103
+ 'Name' => 'Quantity',
104
+ 'Value' => {
105
+ '$type' => 'System.Int32',
106
+ '$value' => data[:count]
107
+ }
108
+ },
109
+ {
110
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
111
+ 'Name' => 'Thru_Date',
112
+ 'Value' => "#{data[:year]}-12-31T00:00:00"
113
+ },
114
+ {
115
+ '$type' => 'Asi.Soa.Core.DataContracts.GenericPropertyData, Asi.Contracts',
116
+ 'Name' => 'Transaction_Date',
117
+ 'Value' => Time.now.strftime('%Y-%m-%dT%H:%M:%S')
118
+ }
119
+ ].compact
120
+ }
121
+ }
122
+ end
123
+ # rubocop:enable Metrics/MethodLength
124
+ end
125
+ end
126
+ end
data/lib/usps-imis-api.rb CHANGED
@@ -15,6 +15,7 @@ require 'imis/error/api'
15
15
  require 'imis/error/mapper'
16
16
  require 'imis/api'
17
17
  require 'imis/mapper'
18
+ require 'imis/panel/vsc'
18
19
 
19
20
  module Imis
20
21
  class << self
@@ -15,17 +15,23 @@ describe Imis::Api do
15
15
  before { api.imis_id = 31092 }
16
16
 
17
17
  it 'sends an update' do
18
- expect(api.put('ABC_ASC_Individual_Demog', { 'TotMMS' => 15 })).to be_a(Hash)
18
+ expect(api.put_fields('ABC_ASC_Individual_Demog', { 'TotMMS' => 15 })).to be_a(Hash)
19
19
  end
20
20
  end
21
21
 
22
22
  describe '#with' do
23
23
  it 'sends an update from put' do
24
- expect(api.with(31092) { put('ABC_ASC_Individual_Demog', { 'TotMMS' => 15 }) }).to be_a(Hash)
24
+ expect(
25
+ api.with(31092) { put_fields('ABC_ASC_Individual_Demog', { 'TotMMS' => 15 }) }
26
+ ).to be_a(Hash)
25
27
  end
26
28
 
27
29
  it 'sends an update from update' do
28
30
  expect(api.with(31092) { update(mm: 15) }.first).to be_a(Hash)
29
31
  end
32
+
33
+ it 'uses a panel correctly' do
34
+ expect(api.with(6374) { panels.vsc.get(1433) }).to be_a(Hash)
35
+ end
30
36
  end
31
37
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Imis::Panel::Vsc do
6
+ let(:vsc) { described_class.new }
7
+
8
+ let(:details) do
9
+ {
10
+ certificate: 'E136924',
11
+ year: 2024,
12
+ count: 42
13
+ }
14
+ end
15
+
16
+ before { vsc.api.imis_id = 6374 }
17
+
18
+ describe '#get' do
19
+ it 'loads a specific object' do
20
+ expect(vsc.get(1433)).to be_a(Hash)
21
+ end
22
+ end
23
+
24
+ # rubocop:disable RSpec/ExampleLength
25
+ it 'handles new records correctly', :aggregate_failures do
26
+ new_record = vsc.create(details)
27
+ expect(new_record).to be_a(Hash)
28
+
29
+ ordinal = new_record['Properties']['$values'][1]['Value']['$value']
30
+
31
+ update_result = vsc.update(details.merge(count: 43, ordinal: ordinal))
32
+ updated = update_result['Properties']['$values'].find { |v| v['Name'] == 'Quantity' }
33
+ expect(updated['Value']['$value']).to eq(43)
34
+
35
+ expect(vsc.destroy(ordinal)).to eq('')
36
+ end
37
+ # rubocop:enable RSpec/ExampleLength
38
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'usps-imis-api'
5
- s.version = '0.1.3'
5
+ s.version = '0.2.1'
6
6
  s.summary = 'iMIS API Wrapper'
7
7
  s.description = 'A wrapper for the iMIS API.'
8
8
  s.homepage = 'http://rubygems.org/gems/usps-imis-api'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: usps-imis-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Fiander
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-13 00:00:00.000000000 Z
11
+ date: 2024-10-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A wrapper for the iMIS API.
14
14
  email: jsfiander@gmail.com
@@ -30,9 +30,11 @@ files:
30
30
  - lib/imis/error/api.rb
31
31
  - lib/imis/error/mapper.rb
32
32
  - lib/imis/mapper.rb
33
+ - lib/imis/panel/vsc.rb
33
34
  - lib/usps-imis-api.rb
34
35
  - spec/lib/imis/api_spec.rb
35
36
  - spec/lib/imis/mapper_spec.rb
37
+ - spec/lib/imis/panel/vsc_spec.rb
36
38
  - spec/spec_helper.rb
37
39
  - usps-imis-api.gemspec
38
40
  homepage: http://rubygems.org/gems/usps-imis-api