shipping_connector 0.1.0 → 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: b5dc5dd88edc69471c3d50e15f9e84e59cc604fbd4a7a33f6f37310a67e7060e
4
- data.tar.gz: 86629918a4474ab6abb378ddd6f8b3c9500eaa86a7f8d343de498edc97cf23e1
3
+ metadata.gz: 513d12edb9b1d0272c2881b3e026b5a33e8f389f99596a8421b89c898e77d07c
4
+ data.tar.gz: 15f454b5b931284bb24671cf92e40dca5215ccc4a27a72e5034b2933042c0e2a
5
5
  SHA512:
6
- metadata.gz: 6b591b23947cd52b0783bd376e3137fcadc996ba59e85cc76b3af86fa34b416f988fe3547eb790bdf67c71f24cb9f9b9c118f46407107b08b4f7b4be59bae4be
7
- data.tar.gz: '094dbffaabfc78dfd8086614e1c40e4274f0c317cde2467ddaccf9e372b15c7b4cb1b30675473c18347678f699c1427fe669ec5c97145cc3dacfb3e21bec9963'
6
+ metadata.gz: 870b5d463ebaf3877f5461736278b922869311e7617a1b2b5ce1c099a7a3f39f16c48403c54bf0ec0d3af50fd1106fba74f96aa687f4a29dbae7dc0bfd2180d5
7
+ data.tar.gz: 4521d98d28d6699082f1e85fd6963cb73254469f944c5669a005d3843f1c6bfa19017502ddaa74fd5bc12f2af0ba581612e3e5b717ec0da2a9a904aee7fb4336
@@ -46,25 +46,56 @@ module ShippingConnector
46
46
  end
47
47
  end
48
48
 
49
+ # Returns a shipment with a list of events
50
+ # @param id [String] the shipment id
51
+ # @param locale [Symbol] two-letter language code, e.g. :da or :en
52
+ # @return [Shipment] the shipment for the given id
53
+ def shipment(id, locale: :en)
54
+ # Ugh... Why is Postnord not consistent in their API...
55
+ data = get('/rest/shipment/v5/trackandtrace/ids.json',
56
+ { id: id, locale: locale })
57
+
58
+ shipment = data['shipments'].first { |s| s['shipmentId'] == id.to_s }
59
+ raise "Shipment with ID #{id} not found" unless shipment
60
+
61
+ item = shipment['items'].first { |i| i['itemId'] == id.to_s }
62
+ raise "The shipment returned no items with ID #{id}" unless item
63
+
64
+ generate_shipment(shipment['status'], item)
65
+ end
66
+
49
67
  private
50
68
 
69
+ def generate_shipment(status, item)
70
+ events = generate_events(item['events'])
71
+ Shipment.new(
72
+ id: item['itemId'],
73
+ events: events, status: convert_status(status),
74
+ status_description: item['statusText']['header']
75
+ )
76
+ end
77
+
51
78
  def auth_params
52
79
  { apikey: @options[:api_key], returnType: 'json' }
53
80
  end
54
81
 
55
82
  def get(path, params)
56
83
  response = super(path, params.merge(auth_params))
57
- JSON.parse response.body
84
+ body = JSON.parse(response.body)
85
+ return body.values.first if body.keys.first =~ /Response$/
86
+
87
+ body
58
88
  rescue Faraday::ClientError => e
59
89
  body = JSON.parse e.response[:body]
60
- raise StandardError, "Postnord error: #{body['message']}"
90
+ message = body.values.first['compositeFault']['faults'][0]
91
+ raise StandardError, "Postnord error #{message['faultCode']}: #{message['explanationText']}"
61
92
  end
62
93
 
63
94
  def find_service_point(id, arguments)
64
95
  service_point = get('/rest/businesslocation/v5/servicepoints/ids',
65
96
  {
66
97
  ids: id, countryCode: arguments[:country]
67
- })['servicePointInformationResponse']['servicePoints'].first
98
+ })['servicePoints'].first
68
99
 
69
100
  ServicePoint.new(
70
101
  id: service_point['servicePointId'], zip_code: service_point['visitingAddress']['postalCode'],
@@ -87,7 +118,7 @@ module ShippingConnector
87
118
  params[:numberOfServicePoints] = options[:limit] || 10
88
119
 
89
120
  array = get('/rest/businesslocation/v5/servicepoints/nearest/byaddress',
90
- params)['servicePointInformationResponse']['servicePoints']
121
+ params)['servicePoints']
91
122
 
92
123
  generate_service_points array
93
124
  end
@@ -99,7 +130,7 @@ module ShippingConnector
99
130
  northing: options[:latitude],
100
131
  easting: options[:longitude],
101
132
  numberOfServicePoints: options[:limit] || 10
102
- })['servicePointInformationResponse']['servicePoints']
133
+ })['servicePoints']
103
134
 
104
135
  generate_service_points array
105
136
  end
@@ -112,7 +143,7 @@ module ShippingConnector
112
143
  name: service_point['name'], city: service_point['visitingAddress']['city'],
113
144
  address: "#{service_point['visitingAddress']['streetName']} #{service_point['visitingAddress']['streetName']}",
114
145
  distance: service_point['routeDistance'], opening_hours: opening_hours(service_point['openingHours'])
115
- )
146
+ )
116
147
  end
117
148
  result
118
149
  end
@@ -126,5 +157,35 @@ module ShippingConnector
126
157
 
127
158
  ServicePoint::OpeningHours.new(hash)
128
159
  end
160
+
161
+ def generate_events(events)
162
+ array = []
163
+ events.each do |event|
164
+ array << Shipment::Event.new(
165
+ type: convert_status(event['status']),
166
+ time: convert_time(event['eventTime']),
167
+ description: event['eventDescription'],
168
+ location: event['location']['displayName']
169
+ )
170
+ end
171
+ array
172
+ end
173
+
174
+ def convert_status(status)
175
+ # FIXME: Find a good status category for 'OTHER'
176
+ hash = {
177
+ 'DELIVERED' => :delivered,
178
+ 'EN_ROUTE' => :en_route,
179
+ 'AVAILABLE_FOR_DELIVERY' => :available_for_delivery
180
+ }
181
+ return hash[status] if hash[status]
182
+
183
+ warn "Unknown status: #{status}"
184
+ :unknown
185
+ end
186
+
187
+ def convert_time(time_string)
188
+ TZInfo::Timezone.get('Europe/Copenhagen').to_local(Time.parse(time_string))
189
+ end
129
190
  end
130
191
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShippingConnector
4
+ class Shipment
5
+ attr_reader :id, :receiver, :sender, :events, :status, :status_description
6
+
7
+ def initialize(params = {})
8
+ params.each { |key, value| instance_variable_set("@#{key}", value) }
9
+ end
10
+
11
+ class Event
12
+ attr_reader :type, :time, :description, :location
13
+
14
+ def initialize(params = {})
15
+ params.each { |key, value| instance_variable_set("@#{key}", value) }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'faraday'
4
- require 'json'
5
- require 'active_support/core_ext/class/attribute'
6
-
7
3
  require 'shipping_connector/carrier'
8
4
  require 'shipping_connector/carriers'
9
5
  require 'shipping_connector/service_point'
6
+ require 'shipping_connector/shipment'
metadata CHANGED
@@ -1,15 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shipping_connector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Thyregod Kristensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-25 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2021-10-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tzinfo
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: tzinfo-data
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
13
83
  description: |2
14
84
  ShippingConnector is an abstraction library that makes connecting to various shipping
15
85
  carriers' APIs easier. As with everything Ruby, the goal is to make writing code that
@@ -25,6 +95,7 @@ files:
25
95
  - lib/shipping_connector/carrier/postnord.rb
26
96
  - lib/shipping_connector/carriers.rb
27
97
  - lib/shipping_connector/service_point.rb
98
+ - lib/shipping_connector/shipment.rb
28
99
  homepage: https://github.com/sthyregod/shipping_connector
29
100
  licenses:
30
101
  - MIT