freight_kit 0.1.15 → 0.1.16
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/Gemfile.lock +96 -43
- data/README.md +28 -6
- data/VERSION +1 -1
- data/configuration/carriers/abfs.yml +124 -0
- data/configuration/carriers/btvp.yml +84 -0
- data/configuration/carriers/ccyq.yml +121 -0
- data/configuration/carriers/clni.yml +113 -0
- data/configuration/carriers/cnwy.yml +113 -0
- data/configuration/carriers/ctbv.yml +117 -0
- data/configuration/carriers/dcha.yml +105 -0
- data/configuration/carriers/dlds.yml +111 -0
- data/configuration/carriers/dphe.yml +130 -0
- data/configuration/carriers/drrq.yml +131 -0
- data/configuration/carriers/fcsy.yml +102 -0
- data/configuration/carriers/fwda.yml +137 -0
- data/configuration/carriers/jfj_transportation.yml +2 -0
- data/configuration/carriers/mtvl.yml +12 -0
- data/configuration/carriers/numk.yml +14 -0
- data/configuration/carriers/otcl.yml +124 -0
- data/configuration/carriers/pens.yml +22 -0
- data/configuration/carriers/rdfs.yml +142 -0
- data/configuration/carriers/saia.yml +129 -0
- data/configuration/carriers/sefl.yml +115 -0
- data/configuration/carriers/totl.yml +111 -0
- data/configuration/carriers/tqyl.yml +28 -0
- data/configuration/carriers/wrds.yml +20 -0
- data/configuration/platforms/carrier_logistics.yml +25 -0
- data/configuration/platforms/next.yml +12 -0
- data/configuration/platforms/the_great_information_factory.yml +122 -0
- data/freight_kit.gemspec +9 -7
- data/lib/freight_kit/api_clients/soap_client.rb +70 -0
- data/lib/freight_kit/api_clients.rb +3 -0
- data/lib/freight_kit/carriers/abfs.rb +421 -0
- data/lib/freight_kit/carriers/btvp.rb +29 -0
- data/lib/freight_kit/carriers/ccyq.rb +317 -0
- data/lib/freight_kit/carriers/clni.rb +396 -0
- data/lib/freight_kit/carriers/cnwy.rb +327 -0
- data/lib/freight_kit/carriers/ctbv.rb +53 -0
- data/lib/freight_kit/carriers/dcha.rb +76 -0
- data/lib/freight_kit/carriers/dlds.rb +49 -0
- data/lib/freight_kit/carriers/dphe.rb +474 -0
- data/lib/freight_kit/carriers/drrq.rb +580 -0
- data/lib/freight_kit/carriers/fcsy.rb +57 -0
- data/lib/freight_kit/carriers/fwda.rb +744 -0
- data/lib/freight_kit/carriers/jfj_transportation.rb +13 -0
- data/lib/freight_kit/carriers/mtvl.rb +34 -0
- data/lib/freight_kit/carriers/numk.rb +58 -0
- data/lib/freight_kit/carriers/otcl.rb +528 -0
- data/lib/freight_kit/carriers/pens.rb +204 -0
- data/lib/freight_kit/carriers/rdfs.rb +521 -0
- data/lib/freight_kit/carriers/saia.rb +438 -0
- data/lib/freight_kit/carriers/sefl.rb +342 -0
- data/lib/freight_kit/carriers/totl.rb +172 -0
- data/lib/freight_kit/carriers/tqyl.rb +339 -0
- data/lib/freight_kit/carriers/wrds.rb +246 -0
- data/lib/freight_kit/carriers.rb +26 -0
- data/lib/freight_kit/helpers/documentable.rb +13 -0
- data/lib/freight_kit/helpers/pickupable.rb +39 -0
- data/lib/freight_kit/helpers/rateable.rb +28 -0
- data/lib/freight_kit/helpers/trackable.rb +25 -0
- data/lib/freight_kit/helpers.rb +6 -0
- data/lib/freight_kit/platforms/carrier_logistics.rb +450 -0
- data/lib/freight_kit/platforms/next.rb +101 -0
- data/lib/freight_kit/platforms/the_great_information_factory.rb +528 -0
- data/lib/freight_kit/platforms.rb +5 -0
- data/lib/freight_kit.rb +20 -1
- metadata +94 -14
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FreightKit
|
|
4
|
+
class PENS < FreightKit::Carrier
|
|
5
|
+
class << self
|
|
6
|
+
def maximum_height
|
|
7
|
+
Measured::Length.new(105, :inches)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def maximum_weight
|
|
11
|
+
Measured::Weight.new(10_000, :pounds)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def minimum_length_for_overlength_fees
|
|
15
|
+
Measured::Length.new(6, :feet)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def overlength_fees_require_tariff?
|
|
19
|
+
false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def required_credential_types
|
|
23
|
+
%i[api]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def requirements
|
|
27
|
+
%i[credentials]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
REACTIVE_FREIGHT_CARRIER = true
|
|
32
|
+
|
|
33
|
+
include FreightKit::Rateable
|
|
34
|
+
|
|
35
|
+
class << self
|
|
36
|
+
attr_reader :name, :scac
|
|
37
|
+
end
|
|
38
|
+
@name = 'Peninsula Truck Lines'
|
|
39
|
+
@scac = 'PENS'
|
|
40
|
+
|
|
41
|
+
# Documents
|
|
42
|
+
|
|
43
|
+
# Tracking
|
|
44
|
+
|
|
45
|
+
protected
|
|
46
|
+
|
|
47
|
+
def commit(action, request)
|
|
48
|
+
client_args = {
|
|
49
|
+
wsdl: request_url(action),
|
|
50
|
+
convert_request_keys_to: :lower_camelcase,
|
|
51
|
+
env_namespace: :soap,
|
|
52
|
+
element_form_default: :qualified
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
call_args = { message: request }
|
|
56
|
+
|
|
57
|
+
::FreightKit::SoapClient.new(
|
|
58
|
+
carrier: self,
|
|
59
|
+
action:,
|
|
60
|
+
client_args:,
|
|
61
|
+
call_args:,
|
|
62
|
+
soap_operation: @conf.dig(:api, :actions, action),
|
|
63
|
+
).call
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def parse_amount(amount)
|
|
67
|
+
negative = amount.start_with?('-$') || amount.start_with?('-')
|
|
68
|
+
|
|
69
|
+
['$', '-', ','].each do |char|
|
|
70
|
+
amount = amount.sub(char, '')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
return 0 if amount.blank?
|
|
74
|
+
|
|
75
|
+
amount = (amount.to_f * 100).to_i
|
|
76
|
+
return amount unless negative
|
|
77
|
+
|
|
78
|
+
amount * -1
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def request_url(action)
|
|
82
|
+
scheme = @conf.dig(:api, :use_ssl, action) ? 'https://' : 'http://'
|
|
83
|
+
"#{scheme}#{@conf.dig(:api, :domains, action)}#{@conf.dig(:api, :endpoints, action)}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Documents
|
|
87
|
+
|
|
88
|
+
# Rates
|
|
89
|
+
def build_rate_request(shipment:)
|
|
90
|
+
raise UnserviceableError, 'Unable to quote accessorials over API' if shipment.accessorials.present?
|
|
91
|
+
|
|
92
|
+
api_credentials = fetch_credential(:api)
|
|
93
|
+
|
|
94
|
+
request = {
|
|
95
|
+
accessorial_list: '', # TODO: Fix this!
|
|
96
|
+
account: api_credentials.account,
|
|
97
|
+
class_list: shipment.packages.map(&:freight_class).join(','),
|
|
98
|
+
customer_type: 'B',
|
|
99
|
+
destination_zip: shipment.destination.postal_code.to_s,
|
|
100
|
+
none_palletized_mode: shipment.packages.map(&:packaging).map(&:pallet?).any?(false) ? 'Y' : 'N',
|
|
101
|
+
origin_zip: shipment.origin.postal_code.to_s,
|
|
102
|
+
password: api_credentials.password,
|
|
103
|
+
plt_count_list: shipment.packages.map(&:quantity).join(','),
|
|
104
|
+
plt_length_list: shipment.packages.map { |p| p.inches(:length).ceil }.join(','),
|
|
105
|
+
plt_total_weight: shipment.packages.map { |p| p.pounds(:total).ceil }.join(','),
|
|
106
|
+
plt_width_list: shipment.packages.map { |p| p.inches(:width).ceil }.join(','),
|
|
107
|
+
user_id: api_credentials.username,
|
|
108
|
+
weight_list: shipment.packages.map { |p| p.pounds(:total) }.join(',')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
save_request(request)
|
|
112
|
+
request
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def parse_rate_response(shipment:, response:)
|
|
116
|
+
rate_response = RateResponse.new(request: last_request, response:)
|
|
117
|
+
|
|
118
|
+
if response.blank?
|
|
119
|
+
rate_response.error = ResponseError.new('Unknown response')
|
|
120
|
+
return rate_response
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
error = response.dig(:create_pens_rate_quote_response, :create_pens_rate_quote_result, :errors, :message)
|
|
124
|
+
|
|
125
|
+
if error.present?
|
|
126
|
+
if error.include?('[RatingService.ValidateZipCodes]')
|
|
127
|
+
rate_response.error = UnserviceableError.new('Origin or destination has no service available')
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
rate_response.error = ResponseError.new(error) if rate_response.error.blank?
|
|
131
|
+
return rate_response
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
result = response.dig(:create_pens_rate_quote_response, :create_pens_rate_quote_result)
|
|
135
|
+
|
|
136
|
+
if result.dig(:quote, :gross_charge).blank?
|
|
137
|
+
rate_response.error = ResponseError.new('Cost is blank')
|
|
138
|
+
return rate_response
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
service_type = :standard
|
|
142
|
+
api_service_type = result.dig(:quote, :transit_type)
|
|
143
|
+
|
|
144
|
+
@conf.dig(:services, :mappable).each do |key, val|
|
|
145
|
+
service_type = key if api_service_type.downcase.include?(val)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
transit_days = service_type == :next_day_ltl ? 1 : nil # TODO: Detect correctly
|
|
149
|
+
|
|
150
|
+
estimate_reference = result.dig('quote', 'quote_number')
|
|
151
|
+
|
|
152
|
+
prices = []
|
|
153
|
+
|
|
154
|
+
prices << Price.new(
|
|
155
|
+
blame: :api,
|
|
156
|
+
cents: parse_amount(result.dig(:quote, :gross_charge)),
|
|
157
|
+
description: 'Charge based on class and weight',
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
accessorial_details = result.dig(:quote, :accessorial_detail)
|
|
161
|
+
accessorial_details = [accessorial_details] if accessorial_details.is_a?(Hash)
|
|
162
|
+
|
|
163
|
+
accessorial_details.each do |accessorial_detail|
|
|
164
|
+
accessorial_item = accessorial_detail[:accessorial_item]
|
|
165
|
+
|
|
166
|
+
prices << Price.new(
|
|
167
|
+
blame: :api,
|
|
168
|
+
cents: parse_amount(accessorial_item[:charge]),
|
|
169
|
+
description: accessorial_item[:description]&.capitalize,
|
|
170
|
+
)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
prices << Price.new(
|
|
174
|
+
blame: :api,
|
|
175
|
+
cents: parse_amount(result.dig(:quote, :discount_amount)),
|
|
176
|
+
description: 'Discount',
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
prices << Price.new(
|
|
180
|
+
blame: :api,
|
|
181
|
+
cents: parse_amount(result.dig(:quote, :fsc_amount)),
|
|
182
|
+
description: 'Fuel surcharge',
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
rate = Rate.new(
|
|
186
|
+
carrier: self,
|
|
187
|
+
carrier_name: self.class.name,
|
|
188
|
+
currency: 'USD',
|
|
189
|
+
estimate_reference:,
|
|
190
|
+
scac: self.class.scac.upcase,
|
|
191
|
+
service_name: :standard,
|
|
192
|
+
shipment:,
|
|
193
|
+
prices:,
|
|
194
|
+
transit_days:,
|
|
195
|
+
with_excessive_length_fees: @conf.dig(:attributes, :rates, :with_excessive_length_fees),
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
rate_response.rates = [rate]
|
|
199
|
+
rate_response
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Tracking
|
|
203
|
+
end
|
|
204
|
+
end
|