freight_kit 0.1.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 +7 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +201 -0
- data/MIT-LICENSE +31 -0
- data/README.md +153 -0
- data/VERSION +1 -0
- data/accessorial_symbols.txt +95 -0
- data/freight_kit.gemspec +58 -0
- data/lib/freight_kit/carrier.rb +473 -0
- data/lib/freight_kit/carriers.rb +24 -0
- data/lib/freight_kit/contact.rb +17 -0
- data/lib/freight_kit/error.rb +5 -0
- data/lib/freight_kit/errors/document_not_found_error.rb +5 -0
- data/lib/freight_kit/errors/expired_credentials_error.rb +5 -0
- data/lib/freight_kit/errors/http_error.rb +25 -0
- data/lib/freight_kit/errors/invalid_credentials_error.rb +5 -0
- data/lib/freight_kit/errors/response_error.rb +16 -0
- data/lib/freight_kit/errors/shipment_not_found_error.rb +5 -0
- data/lib/freight_kit/errors/unserviceable_accessorials_error.rb +17 -0
- data/lib/freight_kit/errors/unserviceable_error.rb +5 -0
- data/lib/freight_kit/errors.rb +10 -0
- data/lib/freight_kit/model.rb +17 -0
- data/lib/freight_kit/models/credential.rb +117 -0
- data/lib/freight_kit/models/date_time.rb +37 -0
- data/lib/freight_kit/models/document_response.rb +17 -0
- data/lib/freight_kit/models/label.rb +13 -0
- data/lib/freight_kit/models/location.rb +108 -0
- data/lib/freight_kit/models/pickup_response.rb +19 -0
- data/lib/freight_kit/models/price.rb +38 -0
- data/lib/freight_kit/models/rate.rb +81 -0
- data/lib/freight_kit/models/rate_response.rb +15 -0
- data/lib/freight_kit/models/response.rb +21 -0
- data/lib/freight_kit/models/shipment.rb +66 -0
- data/lib/freight_kit/models/shipment_event.rb +38 -0
- data/lib/freight_kit/models/tracking_response.rb +75 -0
- data/lib/freight_kit/models.rb +17 -0
- data/lib/freight_kit/package.rb +313 -0
- data/lib/freight_kit/package_item.rb +65 -0
- data/lib/freight_kit/packaging.rb +52 -0
- data/lib/freight_kit/platform.rb +36 -0
- data/lib/freight_kit/shipment_packer.rb +116 -0
- data/lib/freight_kit/tariff.rb +29 -0
- data/lib/freight_kit/version.rb +5 -0
- data/lib/freight_kit.rb +34 -0
- data/service_type_symbols.txt +4 -0
- data/shipment_event_symbols.txt +17 -0
- metadata +453 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Class representing credentials.
|
5
|
+
#
|
6
|
+
# @!attribute kind
|
7
|
+
# What kind?
|
8
|
+
# @return [Symbol] One of `:api`, `:api_key`, `:oauth2`, `:website`
|
9
|
+
#
|
10
|
+
# @!attribute access_token
|
11
|
+
# Access token when type is `:oauth2`
|
12
|
+
# @return [String] Access token
|
13
|
+
#
|
14
|
+
# @!attribute expires_at
|
15
|
+
# Token expiration date/time when type is `:oauth2`
|
16
|
+
# @return [DateTime] Token expiration date/time
|
17
|
+
#
|
18
|
+
# @!attribute scope
|
19
|
+
# Scope when type is `:oauth2`
|
20
|
+
# @return [String] Scope
|
21
|
+
#
|
22
|
+
# @!attribute username
|
23
|
+
# Username when type is one of `:api`, `:website`
|
24
|
+
# @return [String] Username
|
25
|
+
#
|
26
|
+
# @!attribute password
|
27
|
+
# Password when type is one of `:api`, `:website`
|
28
|
+
# @return [String] Username
|
29
|
+
#
|
30
|
+
class Credential < Model
|
31
|
+
attr_accessor :type
|
32
|
+
|
33
|
+
# Returns a new instance of Credential.
|
34
|
+
#
|
35
|
+
# Other than the following, instance `:attr_reader`s are generated dynamically based on keys.
|
36
|
+
#
|
37
|
+
# @param [Symbol] type One of `:api`, `:website`
|
38
|
+
# @param [String] base_url Required when type is `:selenoid`
|
39
|
+
# @param [String] username Required when type is one of `:api`, `:website`
|
40
|
+
# @param [String] password Required when type is one of `:api`, `:website`
|
41
|
+
# @param [String] access_token Required when type is `:oauth2`
|
42
|
+
# @param [DateTime] expires_at Required when type is `:oauth2`
|
43
|
+
# @param [String] scope Required when type is `:oauth2`
|
44
|
+
# @param [String] proxy_url Required when type is `:api_proxy`
|
45
|
+
def initialize(hash)
|
46
|
+
raise ArgumentError, 'Credential#new: `type` cannot be blank' if hash[:type].blank?
|
47
|
+
|
48
|
+
type = hash[:type]
|
49
|
+
|
50
|
+
requirements = case type
|
51
|
+
when :api_key
|
52
|
+
{ api_key: String }
|
53
|
+
when :api, :website
|
54
|
+
{ password: String }
|
55
|
+
when :api_proxy
|
56
|
+
{ api_key: String, proxy_url: String }
|
57
|
+
when :oauth2
|
58
|
+
{ access_token: String, expires_at: ::DateTime, scope: String }
|
59
|
+
when :selenoid
|
60
|
+
{ base_url: URI, browser: Symbol }
|
61
|
+
else
|
62
|
+
{}
|
63
|
+
end
|
64
|
+
|
65
|
+
requirements.each_key do |k|
|
66
|
+
raise ArgumentError, "Credential#new: `#{k}` cannot be blank" if hash[k].blank?
|
67
|
+
|
68
|
+
unless hash[k].is_a?(requirements[k])
|
69
|
+
raise ArgumentError, "Credential#new: `#{k}` must be a #{requirements[k]}, got #{hash[k].class}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
hash.each do |k, _v|
|
74
|
+
next if k == :type
|
75
|
+
|
76
|
+
singleton_class.class_eval { attr_accessor(k.to_s) } unless singleton_class.respond_to?(k)
|
77
|
+
end
|
78
|
+
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
82
|
+
def selenoid_options
|
83
|
+
return unless type == :selenoid
|
84
|
+
return @selenoid_options if @selenoid_options.present?
|
85
|
+
|
86
|
+
download_url = base_url.dup
|
87
|
+
download_url.path = '/download'
|
88
|
+
download_url = download_url.to_s
|
89
|
+
|
90
|
+
@selenoid_options = { download_url: }
|
91
|
+
end
|
92
|
+
|
93
|
+
def watir_args
|
94
|
+
return unless type == :selenoid
|
95
|
+
return @watir_args if @watir_args.present?
|
96
|
+
|
97
|
+
url = base_url.dup
|
98
|
+
url.path = '/wd/hub/'
|
99
|
+
url = url.to_s
|
100
|
+
|
101
|
+
@watir_args = [
|
102
|
+
browser,
|
103
|
+
{
|
104
|
+
options: {
|
105
|
+
prefs: {
|
106
|
+
download: {
|
107
|
+
directory_upgrade: true,
|
108
|
+
prompt_for_download: false
|
109
|
+
}
|
110
|
+
}
|
111
|
+
},
|
112
|
+
url:
|
113
|
+
},
|
114
|
+
]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Represent dates and times in varous formats.
|
5
|
+
#
|
6
|
+
# @attribute date_time_with_zone
|
7
|
+
# Date and time with time zone.
|
8
|
+
# @return [ActiveSupport::TimeWithZone]
|
9
|
+
#
|
10
|
+
# @attribute local_date
|
11
|
+
# Local date.
|
12
|
+
# @return [Date]
|
13
|
+
#
|
14
|
+
# @attribute local_date_time
|
15
|
+
# Local date and time in the format `"YYYY-MM-DD HH:MM:SS"`
|
16
|
+
# (zero-padded 24 hour clock) aka `DateTime#to_fs(:db)` format.
|
17
|
+
# @return [String]
|
18
|
+
#
|
19
|
+
class DateTime < Model
|
20
|
+
attr_accessor :local_date, :local_date_time, :location, :date_time_with_zone
|
21
|
+
|
22
|
+
def initialize(*)
|
23
|
+
super
|
24
|
+
|
25
|
+
attempt_upgrade_using_location(location) if location.present?
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def attempt_upgrade_using_location(location)
|
31
|
+
return if @date_time_with_zone.present? || @local_date_time.blank? || location.time_zone.blank?
|
32
|
+
|
33
|
+
@date_time_with_zone = location.time_zone.parse(@local_date_time)
|
34
|
+
@local_date_time = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Represents the response to calls:
|
5
|
+
# - {FreightKit::Carrier#bol}
|
6
|
+
# - {FreightKit::Carrier#pod}
|
7
|
+
# - {FreightKit::Carrier#scanned_bol}
|
8
|
+
#
|
9
|
+
# @attribute content_type
|
10
|
+
# @return [String] The HTTP `Content-Type`
|
11
|
+
#
|
12
|
+
# @attribute data
|
13
|
+
# @return [String] Raw document data.
|
14
|
+
class DocumentResponse < Response
|
15
|
+
attr_accessor :content_type, :data
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Class representing a location.
|
5
|
+
#
|
6
|
+
# @attribute address1
|
7
|
+
# The first street line
|
8
|
+
# @return [String, nil]
|
9
|
+
#
|
10
|
+
# @attribute address2
|
11
|
+
# The second street line
|
12
|
+
# @return [String, nil]
|
13
|
+
#
|
14
|
+
# @attribute address3
|
15
|
+
# The third street line
|
16
|
+
# @return [String, nil]
|
17
|
+
#
|
18
|
+
# @attribute city
|
19
|
+
# The city name.
|
20
|
+
# @return [String, nil]
|
21
|
+
#
|
22
|
+
# @attribute contact
|
23
|
+
# The contact at the location.
|
24
|
+
# @return [String, nil]
|
25
|
+
#
|
26
|
+
# @attribute country
|
27
|
+
# The country of the location.
|
28
|
+
# @return [ActiveUtils::Country, nil]
|
29
|
+
#
|
30
|
+
# @attribute lat
|
31
|
+
# The latitude of the location.
|
32
|
+
# @return [BigNum, nil]
|
33
|
+
#
|
34
|
+
# @attribute lng
|
35
|
+
# The longitude of the location.
|
36
|
+
# @return [BigNum, nil]
|
37
|
+
#
|
38
|
+
# @attribute postal_code
|
39
|
+
# The postal code (or ZIP® code) of the location.
|
40
|
+
# @return [String, nil]
|
41
|
+
#
|
42
|
+
# @attribute province
|
43
|
+
# The province (or state/territory) abbreviation of the location.
|
44
|
+
# @return [String, nil]
|
45
|
+
#
|
46
|
+
# @attribute type
|
47
|
+
# The type of the location.
|
48
|
+
#
|
49
|
+
# It should be one of: :commercial, :po_box, :residential
|
50
|
+
#
|
51
|
+
# @return [Symbol, nil]
|
52
|
+
#
|
53
|
+
class Location < Model
|
54
|
+
TYPES = %i[commercial po_box residential].freeze
|
55
|
+
|
56
|
+
attr_accessor :address1, :address2, :address3, :city, :postal_code, :province
|
57
|
+
attr_reader :contact, :country, :lat, :lng, :type
|
58
|
+
|
59
|
+
def contact=(contact)
|
60
|
+
return @contact = nil if contact.blank?
|
61
|
+
|
62
|
+
raise ArgumentError, 'contact must be a Contact' unless contact.is_a?(FreightKit::Contact)
|
63
|
+
|
64
|
+
@contact = contact
|
65
|
+
end
|
66
|
+
|
67
|
+
def country=(country)
|
68
|
+
return country = nil if country.blank?
|
69
|
+
|
70
|
+
if country.is_a?(ActiveUtils::Country)
|
71
|
+
@country = country
|
72
|
+
return country
|
73
|
+
end
|
74
|
+
|
75
|
+
raise ArgumentError, 'country must be an ActiveUtils::Country'
|
76
|
+
end
|
77
|
+
|
78
|
+
def lat=(num)
|
79
|
+
return @lat = nil if num.blank?
|
80
|
+
|
81
|
+
return @lat = num if num.is_a?(BigNum)
|
82
|
+
|
83
|
+
raise ArgumentError, 'lat must be a BigNum'
|
84
|
+
end
|
85
|
+
|
86
|
+
def lng=(num)
|
87
|
+
return @lng = nil if num.blank?
|
88
|
+
|
89
|
+
return @lng = num if num.is_a?(BigNum)
|
90
|
+
|
91
|
+
raise ArgumentError, 'lng must be a BigNum'
|
92
|
+
end
|
93
|
+
|
94
|
+
def time_zone
|
95
|
+
return if country&.code(:alpha2)&.blank? || province.blank? || city.blank?
|
96
|
+
|
97
|
+
PlaceKit.lookup(country.code(:alpha2).to_s, province, city)
|
98
|
+
end
|
99
|
+
|
100
|
+
def type=(value)
|
101
|
+
return @type = nil if value.blank?
|
102
|
+
|
103
|
+
raise ArgumentError, "type must be one of :#{TYPES.join(", :")}" unless TYPES.include?(value)
|
104
|
+
|
105
|
+
@type = value
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# The `PickupResponse` object is returned by the {FreightKit::Carrier#create_pickup}
|
5
|
+
# call. The most important method is {#pickup_number}, which will return the pickup reference
|
6
|
+
# number.
|
7
|
+
#
|
8
|
+
# @!attribute labels
|
9
|
+
# Shipping labels.
|
10
|
+
# @return [Array<FreightKit::Label>]
|
11
|
+
#
|
12
|
+
# @!attribute pickup_number
|
13
|
+
# Pickup reference number.
|
14
|
+
# @return [String]
|
15
|
+
#
|
16
|
+
class PickupResponse < Response
|
17
|
+
attr_accessor :labels, :pickup_number
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Class representing a price.
|
5
|
+
#
|
6
|
+
# @!attribute blame
|
7
|
+
# Where did the cost come from?
|
8
|
+
# @return [Symbol] One of :api, :library, :tariff
|
9
|
+
#
|
10
|
+
# @!attribute description
|
11
|
+
# Description.
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
# @!attribute objects
|
15
|
+
# Array of objects that the price applies to.
|
16
|
+
# @return [Array]
|
17
|
+
#
|
18
|
+
# @!attribute cents
|
19
|
+
# The price in cents.
|
20
|
+
# @return [Integer]
|
21
|
+
#
|
22
|
+
class Price < Model
|
23
|
+
attr_accessor :description, :objects
|
24
|
+
attr_writer :blame, :cents
|
25
|
+
|
26
|
+
def blame
|
27
|
+
return @blame if %i[api library tariff].include?(@blame)
|
28
|
+
|
29
|
+
raise 'blame must be one of :api, :library, :tariff'
|
30
|
+
end
|
31
|
+
|
32
|
+
def cents
|
33
|
+
return @cents if @cents.is_a?(Integer)
|
34
|
+
|
35
|
+
raise 'cents must be an `Integer`'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Class representing a shipping option with estimated price.
|
5
|
+
#
|
6
|
+
# @!attribute carrier
|
7
|
+
# The carrier.
|
8
|
+
# @return [FreightKit::Carrier]
|
9
|
+
# @see FreightKit::Carrier
|
10
|
+
#
|
11
|
+
# @!attribute carrier_name
|
12
|
+
# Name of the carrier. It may differ from the `Carrier` providing the rate quote
|
13
|
+
# when the `Carrier` is acting as a broker.
|
14
|
+
# @return [String]
|
15
|
+
#
|
16
|
+
# @!attribute currency
|
17
|
+
# ISO4217 currency code of the quoted rate estimates (e.g. `CAD`, `EUR`, or `USD`)
|
18
|
+
# @return [String]
|
19
|
+
# @see http://en.wikipedia.org/wiki/ISO_4217
|
20
|
+
#
|
21
|
+
# @!attribute estimate_reference
|
22
|
+
# Quote number.
|
23
|
+
# @return [String]
|
24
|
+
#
|
25
|
+
# @!attribute expires_at
|
26
|
+
# When the rate estimate will expire.
|
27
|
+
# @return [DateTime]
|
28
|
+
#
|
29
|
+
# @!attribute prices
|
30
|
+
# Breakdown of a rate estimate's prices with amounts in cents.
|
31
|
+
# @return [Array<Prices>]
|
32
|
+
# @see FreightKit::Price
|
33
|
+
#
|
34
|
+
# @!attribute scac
|
35
|
+
# SCAC code of the carrier. It may differ from the `Carrier` providing the rate
|
36
|
+
# estimate when the `Carrier` is acting as a broker.
|
37
|
+
# @return [String]
|
38
|
+
#
|
39
|
+
# @!attribute service_name
|
40
|
+
# The name of the shipping service (e.g. 'First Class Ground')
|
41
|
+
# @return [String]
|
42
|
+
#
|
43
|
+
# @!attribute shipment
|
44
|
+
# The shipment.
|
45
|
+
# @return [FreightKit::Shipment]
|
46
|
+
#
|
47
|
+
# @!attribute transit_days
|
48
|
+
# Estimated transit days after date of pickup.
|
49
|
+
# @return [Integer]
|
50
|
+
#
|
51
|
+
# @!attribute with_excessive_length_fees
|
52
|
+
# When the rate estimate `Price`s include applicable excessive length fees.
|
53
|
+
# @return [Integer]
|
54
|
+
#
|
55
|
+
class Rate < Model
|
56
|
+
attr_accessor :carrier,
|
57
|
+
:carrier_name,
|
58
|
+
:estimate_reference,
|
59
|
+
:expires_at,
|
60
|
+
:prices,
|
61
|
+
:scac,
|
62
|
+
:service_name,
|
63
|
+
:shipment,
|
64
|
+
:transit_days,
|
65
|
+
:with_excessive_length_fees
|
66
|
+
|
67
|
+
attr_writer :currency
|
68
|
+
|
69
|
+
def currency
|
70
|
+
ActiveUtils::CurrencyCode.standardize(@currency)
|
71
|
+
end
|
72
|
+
|
73
|
+
# The total price of the shipment in cents.
|
74
|
+
# @return [Integer]
|
75
|
+
def total_cents
|
76
|
+
return 0 if @prices.blank?
|
77
|
+
|
78
|
+
@prices.sum(&:cents)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# The `RateResponse` object is returned by the {FreightKit::Carrier#find_rates}
|
5
|
+
# call. The most important method is {#rates}, which will return a list of possible
|
6
|
+
# shipping options with an estimated price.
|
7
|
+
#
|
8
|
+
# @!attribute rates
|
9
|
+
# The available rate options for the shipment, with an estimated price.
|
10
|
+
# @return [Array<FreightKit::Rate>]
|
11
|
+
#
|
12
|
+
class RateResponse < Response
|
13
|
+
attr_accessor :rates
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Basic Response class for requests against a carrier's API.
|
5
|
+
#
|
6
|
+
# @!attribute error
|
7
|
+
# The error object.
|
8
|
+
# @return [FreightKit::Error, NilClass]
|
9
|
+
#
|
10
|
+
# @!attribute request
|
11
|
+
# The raw request.
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
# @!attribute response
|
15
|
+
# The raw response.
|
16
|
+
# @return [String]
|
17
|
+
#
|
18
|
+
class Response < Model
|
19
|
+
attr_accessor :error, :request, :response
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Shipment is the abstract base class for all rate requests.
|
5
|
+
#
|
6
|
+
# @!attribute accessorials [Hash<Symbol>] Acceessorials requested.
|
7
|
+
# @!attribute declared_value_cents [Integer] Declared value in cents.
|
8
|
+
# @!attribute destination [FreightKit::Location] Where the package will go.
|
9
|
+
# @!attribute origin [FreightKit::Location] Where the shipment will originate from.
|
10
|
+
# @!attribute order_number [String] Order number (also known as shipper number, SO #).
|
11
|
+
# @!attribute packages [Array<FreightKit::Package>] The list of packages that will
|
12
|
+
# be in the shipment.
|
13
|
+
# @!attribute po_number [String] Purchase order number (also known as PO #).
|
14
|
+
# @!attribute pickup_at [FreightKit::DateTime] Pickup date/time.
|
15
|
+
class Shipment < Model
|
16
|
+
attr_accessor :accessorials,
|
17
|
+
:declared_value_cents,
|
18
|
+
:destination,
|
19
|
+
:origin,
|
20
|
+
:order_number,
|
21
|
+
:packages,
|
22
|
+
:po_number,
|
23
|
+
:pro
|
24
|
+
attr_reader :pickup_at
|
25
|
+
|
26
|
+
def loose?
|
27
|
+
return false if @packages.blank?
|
28
|
+
|
29
|
+
packages.map(&:packaging).map(&:pallet?).none?(true)
|
30
|
+
end
|
31
|
+
|
32
|
+
def hazmat?
|
33
|
+
packages.map(&:hazmat?).any?(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
def loose_and_palletized?
|
37
|
+
!loose? && !palletized?
|
38
|
+
end
|
39
|
+
|
40
|
+
def palletized?
|
41
|
+
return false if @packages.blank?
|
42
|
+
|
43
|
+
packages.map(&:packaging).map(&:pallet?).none?(false)
|
44
|
+
end
|
45
|
+
|
46
|
+
def pickup_at=(date_time)
|
47
|
+
if date_time.is_a?(ActiveSupport::TimeWithZone)
|
48
|
+
@pickup_at = FreightKit::DateTime.new(date_time_with_zone: date_time)
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
raise ArgumentError, 'date_time must be an FreightKit::DateTime' unless date_time.is_a?(DateTime)
|
53
|
+
|
54
|
+
@pickup_at = date_time
|
55
|
+
end
|
56
|
+
|
57
|
+
def valid?
|
58
|
+
return false if @accessorials.nil?
|
59
|
+
return false unless @destination.is_a?(Location)
|
60
|
+
return false unless @packages.is_a?(Array)
|
61
|
+
return false if @packages.any? { |p| p.class != Package }
|
62
|
+
|
63
|
+
true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# `ShipmentEvent` is the abstract base class for all shipment events (usually
|
5
|
+
# attached to `TrackingEresponse`).
|
6
|
+
#
|
7
|
+
# @attribute date_time
|
8
|
+
# @return [DateTime] Date and time the event occurred.
|
9
|
+
#
|
10
|
+
# @attribute location
|
11
|
+
# @return [Location] Location the event occurred.
|
12
|
+
#
|
13
|
+
# @attribute type_code
|
14
|
+
# @return [Symbol] One of:
|
15
|
+
# ```
|
16
|
+
# :arrived_at_terminal
|
17
|
+
# :delayed_due_to_weather
|
18
|
+
# :delivered
|
19
|
+
# :delivery_appointment_scheduled
|
20
|
+
# :departed
|
21
|
+
# :found
|
22
|
+
# :located
|
23
|
+
# :lost
|
24
|
+
# :out_for_delivery
|
25
|
+
# :pending_delivery_appointment
|
26
|
+
# :picked_up
|
27
|
+
# :pickup_driver_assigned
|
28
|
+
# :pickup_information_received_by_carrier
|
29
|
+
# :pickup_information_sent_to_carrier
|
30
|
+
# :sailed
|
31
|
+
# :trailer_closed
|
32
|
+
# :trailer_unloaded
|
33
|
+
# ```
|
34
|
+
#
|
35
|
+
class ShipmentEvent < Model
|
36
|
+
attr_accessor :date_time, :location, :type_code
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FreightKit
|
4
|
+
# Represents the response to a {FreightKit::Carrier#find_tracking_info} call.
|
5
|
+
#
|
6
|
+
# @note Some carriers provide more information than others, so not all attributes
|
7
|
+
# will be set, depending on what carrier you are using.
|
8
|
+
#
|
9
|
+
# @!attribute actual_delivery_date
|
10
|
+
# @return [DateTime]
|
11
|
+
#
|
12
|
+
# @!attribute attempted_delivery_date
|
13
|
+
# @return [DateTime]
|
14
|
+
#
|
15
|
+
# @!attribute carrier
|
16
|
+
# @return [Symbol]
|
17
|
+
#
|
18
|
+
# @!attribute carrier_name
|
19
|
+
# @return [String]
|
20
|
+
#
|
21
|
+
# @!attribute delivery_signature
|
22
|
+
# @return [String]
|
23
|
+
#
|
24
|
+
# @!attribute destination
|
25
|
+
# @return [FreightKit::Location]
|
26
|
+
#
|
27
|
+
# @!attribute estimated_delivery_date
|
28
|
+
# @return [FreightKit::DateTime]
|
29
|
+
#
|
30
|
+
# @!attribute origin
|
31
|
+
# @return [FreightKit::Location]
|
32
|
+
#
|
33
|
+
# @!attribute scheduled_delivery_date
|
34
|
+
# @return [DateTime]
|
35
|
+
#
|
36
|
+
# @!attribute ship_time
|
37
|
+
# @return [Date, Time]
|
38
|
+
#
|
39
|
+
# @!attribute shipment_events
|
40
|
+
# @return [Array<FreightKit::ShipmentEvent>]
|
41
|
+
#
|
42
|
+
# @!attribute shipper_address
|
43
|
+
# @return [FreightKit::Location]
|
44
|
+
#
|
45
|
+
# @!attribute status
|
46
|
+
# @return [Symbol]
|
47
|
+
#
|
48
|
+
# @!attribute status_code
|
49
|
+
# @return [string]
|
50
|
+
#
|
51
|
+
# @!attribute status_description
|
52
|
+
# @return [String]
|
53
|
+
#
|
54
|
+
# @!attribute tracking_number
|
55
|
+
# @return [String]
|
56
|
+
#
|
57
|
+
class TrackingResponse < Response
|
58
|
+
attr_accessor :actual_delivery_date,
|
59
|
+
:attempted_delivery_date,
|
60
|
+
:carrier,
|
61
|
+
:carrier_name,
|
62
|
+
:delivery_signature,
|
63
|
+
:destination,
|
64
|
+
:estimated_delivery_date,
|
65
|
+
:origin,
|
66
|
+
:scheduled_delivery_date,
|
67
|
+
:ship_time,
|
68
|
+
:shipment_events,
|
69
|
+
:shipper_address,
|
70
|
+
:status,
|
71
|
+
:status_code,
|
72
|
+
:status_description,
|
73
|
+
:tracking_number
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'freight_kit/models/credential'
|
4
|
+
require 'freight_kit/models/label'
|
5
|
+
require 'freight_kit/models/price'
|
6
|
+
require 'freight_kit/models/rate'
|
7
|
+
require 'freight_kit/models/shipment'
|
8
|
+
|
9
|
+
require 'freight_kit/models/date_time'
|
10
|
+
require 'freight_kit/models/location'
|
11
|
+
|
12
|
+
require 'freight_kit/models/response'
|
13
|
+
require 'freight_kit/models/document_response'
|
14
|
+
require 'freight_kit/models/pickup_response'
|
15
|
+
require 'freight_kit/models/rate_response'
|
16
|
+
require 'freight_kit/models/shipment_event'
|
17
|
+
require 'freight_kit/models/tracking_response'
|