usps-imis-api 0.1.3 → 0.2.0

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: 596057339ef96ddfa1bc884107307bae2bedfa3ef28610f1293218362daa53ad
4
+ data.tar.gz: 304f7b47a0923b08646266b71365049074235d24983abaa78fac615f0b02e5cc
5
5
  SHA512:
6
- metadata.gz: 6a86560e9f859589317faf46dc524105d2b77b2e25d869c6eec604fa1f98592ed4bdf59a6675078e89345782ab45017fdf34f5895d99cf3944473fccf05e9faf
7
- data.tar.gz: aea9d7c488dec4f017a3252d5294cc9f9fa03eed3e374bbd4d9cc0926c9e76b6c725df5a65ea6eca3314e483153e80be05002917fa49aab8993884fe4cfbd3fd
6
+ metadata.gz: ec4ec8cedb9966992b4e6d86b34e2a219c3f6cc28d4c01622d460e1f1f7c44fdfa8c6aa76f3aad1fb97b2e44f75366eb7060f9685b83c1bca21937c8b778414f
7
+ data.tar.gz: 412e3f664b0384330956c11eee3ce11f0c6bb77a3154d24fb4c671e34d919628fb58f7780a92b5a164cb987de8f43893308a7de9f892580a3f6478515d861b3b
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.0)
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
 
@@ -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,13 @@ 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)
150
180
  end
151
181
  ```
152
182
 
data/lib/imis/api.rb CHANGED
@@ -39,8 +39,8 @@ module Imis
39
39
 
40
40
  # Get a business object for the current member
41
41
  #
42
- def get(business_object_name)
43
- uri = uri_for(business_object_name)
42
+ def get(business_object_name, url_id: nil)
43
+ uri = uri_for(business_object_name, url_id: url_id)
44
44
  request = Net::HTTP::Get.new(uri)
45
45
  result = submit(uri, authorize(request))
46
46
  JSON.parse(result.body)
@@ -50,15 +50,42 @@ module Imis
50
50
  #
51
51
  # fields - hash of shape: { field_name => new_value }
52
52
  #
53
- def put(business_object_name, fields)
54
- uri = uri_for(business_object_name)
55
- request = Net::HTTP::Put.new(uri)
53
+ def put_fields(business_object_name, fields, url_id: nil)
56
54
  updated = filter_fields(business_object_name, fields)
57
- request.body = JSON.dump(updated)
55
+ put(business_object_name, updated, url_id: url_id)
56
+ end
57
+
58
+ # Update a business object for the current member
59
+ #
60
+ def put(business_object_name, body, url_id: nil)
61
+ uri = uri_for(business_object_name, url_id: url_id)
62
+ request = Net::HTTP::Put.new(uri)
63
+ request.body = JSON.dump(body)
58
64
  result = submit(uri, authorize(request))
59
65
  JSON.parse(result.body)
60
66
  end
61
67
 
68
+ # Create a business object for the current member
69
+ #
70
+ def post(business_object_name, body, url_id: nil)
71
+ uri = uri_for(business_object_name, url_id: url_id)
72
+ request = Net::HTTP::Post.new(uri)
73
+ request.body = JSON.dump(body)
74
+ result = submit(uri, authorize(request))
75
+ JSON.parse(result.body)
76
+ end
77
+
78
+ # Remove a business object for the current member
79
+ #
80
+ # Returns empty string on success
81
+ #
82
+ def delete(business_object_name, url_id: nil)
83
+ uri = uri_for(business_object_name, url_id: url_id)
84
+ request = Net::HTTP::Delete.new(uri)
85
+ result = submit(uri, authorize(request))
86
+ result.body
87
+ end
88
+
62
89
  # Run an IQA Query
63
90
  #
64
91
  # query_name - the full path of the query in IQA, e.g. `$/_ABC/Fiander/iMIS_ID`
@@ -105,8 +132,10 @@ module Imis
105
132
 
106
133
  # Construct a business object API endpoint address
107
134
  #
108
- def uri_for(business_object_name)
109
- URI(File.join(imis_hostname, "#{API_PATH}/#{business_object_name}/#{imis_id}"))
135
+ def uri_for(business_object_name, url_id: nil)
136
+ url_id ||= imis_id
137
+ url_id = CGI.escape(url_id)
138
+ URI(File.join(imis_hostname, "#{API_PATH}/#{business_object_name}/#{url_id}"))
110
139
  end
111
140
 
112
141
  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,13 +15,15 @@ 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
@@ -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.0'
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.0
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