reactive_freight 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +5 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +166 -0
  5. data/Rakefile +8 -0
  6. data/accessorial_symbols.txt +95 -0
  7. data/lib/reactive_freight.rb +21 -0
  8. data/lib/reactive_freight/carrier.rb +62 -0
  9. data/lib/reactive_freight/carriers.rb +18 -0
  10. data/lib/reactive_freight/carriers/btvp.rb +384 -0
  11. data/lib/reactive_freight/carriers/clni.rb +59 -0
  12. data/lib/reactive_freight/carriers/ctbv.rb +35 -0
  13. data/lib/reactive_freight/carriers/dphe.rb +296 -0
  14. data/lib/reactive_freight/carriers/drrq.rb +303 -0
  15. data/lib/reactive_freight/carriers/fcsy.rb +24 -0
  16. data/lib/reactive_freight/carriers/fwda.rb +243 -0
  17. data/lib/reactive_freight/carriers/jfj_transportation.rb +11 -0
  18. data/lib/reactive_freight/carriers/pens.rb +135 -0
  19. data/lib/reactive_freight/carriers/rdfs.rb +320 -0
  20. data/lib/reactive_freight/carriers/saia.rb +336 -0
  21. data/lib/reactive_freight/carriers/sefl.rb +234 -0
  22. data/lib/reactive_freight/carriers/totl.rb +96 -0
  23. data/lib/reactive_freight/carriers/wrds.rb +218 -0
  24. data/lib/reactive_freight/configuration/carriers/btvp.yml +139 -0
  25. data/lib/reactive_freight/configuration/carriers/clni.yml +107 -0
  26. data/lib/reactive_freight/configuration/carriers/ctbv.yml +117 -0
  27. data/lib/reactive_freight/configuration/carriers/dphe.yml +124 -0
  28. data/lib/reactive_freight/configuration/carriers/drrq.yml +115 -0
  29. data/lib/reactive_freight/configuration/carriers/fcsy.yml +104 -0
  30. data/lib/reactive_freight/configuration/carriers/fwda.yml +117 -0
  31. data/lib/reactive_freight/configuration/carriers/jfj_transportation.yml +2 -0
  32. data/lib/reactive_freight/configuration/carriers/pens.yml +22 -0
  33. data/lib/reactive_freight/configuration/carriers/rdfs.yml +135 -0
  34. data/lib/reactive_freight/configuration/carriers/saia.yml +117 -0
  35. data/lib/reactive_freight/configuration/carriers/sefl.yml +115 -0
  36. data/lib/reactive_freight/configuration/carriers/totl.yml +107 -0
  37. data/lib/reactive_freight/configuration/carriers/wrds.yml +19 -0
  38. data/lib/reactive_freight/configuration/platforms/carrier_logistics.yml +25 -0
  39. data/lib/reactive_freight/configuration/platforms/liftoff.yml +12 -0
  40. data/lib/reactive_freight/package.rb +137 -0
  41. data/lib/reactive_freight/platform.rb +36 -0
  42. data/lib/reactive_freight/platforms.rb +4 -0
  43. data/lib/reactive_freight/platforms/carrier_logistics.rb +317 -0
  44. data/lib/reactive_freight/platforms/liftoff.rb +102 -0
  45. data/lib/reactive_freight/rate_estimate.rb +113 -0
  46. data/lib/reactive_freight/shipment_event.rb +10 -0
  47. data/reactive_freight.gemspec +39 -0
  48. data/service_type_symbols.txt +4 -0
  49. metadata +198 -0
@@ -0,0 +1,115 @@
1
+ :accessorials:
2
+ :mappable:
3
+ :airport_delivery: chkAPD
4
+ :airport_pickup: chkAPU
5
+ :amusement_park_delivery: chkLAD
6
+ :amusement_park_pickup: chkLAP
7
+ :appointment_delivery: chkAN
8
+ :athletic_facility_delivery: chkLAD
9
+ :athletic_facility_pickup: chkLAP
10
+ :cemetery_delivery: chkLAD
11
+ :cemetery_pickup: chkLAP
12
+ :church_delivery: chkLAD
13
+ :church_pickup: chkLAP
14
+ :construction_delivery: chkLAD
15
+ :construction_pickup: chkLAP
16
+ :convention_delivery: chkLAD
17
+ :convention_pickup: chkLAP
18
+ :dock_dropoff: chkSHC
19
+ :fair_delivery: chkLAD
20
+ :fair_pickup: chkLAP
21
+ :farm_delivery: chkLAD
22
+ :farm_pickup: chkLAP
23
+ :fitness_center_delivery: chkLAD
24
+ :fitness_center_pickup: chkLAP
25
+ :golf_course_delivery: chkLAD
26
+ :golf_course_pickup: chkLAP
27
+ :government_delivery: chkLAD
28
+ :government_pickup: chkLAP
29
+ :grocery_store_delivery: chkLAD
30
+ :grocery_store_pickup: chkLAP
31
+ :guaranteed_delivery: chkDG
32
+ :guaranteed_delivery_am: chkNG
33
+ :guaranteed_delivery_pm: chkDG
34
+ :hospital_delivery: chkLAD
35
+ :hospital_pickup: chkLAP
36
+ :hotel_delivery: chkLAD
37
+ :hotel_pickup: chkLAP
38
+ :inside_delivery: chkID
39
+ :inside_pickup: chkIP
40
+ :inspection_site_delivery: chkLAD
41
+ :inspection_site_pickup: chkLAP
42
+ :jobsite_delivery: chkLAD
43
+ :jobsite_pickup: chkLAP
44
+ :liftgate_delivery: chkLGD
45
+ :liftgate_pickup: chkLGP
46
+ :mall_delivery: chkLAD
47
+ :mall_pickup: chkLAP
48
+ :marina_delivery: chkLAD
49
+ :marina_pickup: chkLAP
50
+ :military_site_delivery: chkLAD
51
+ :military_site_pickup: chkLAP
52
+ :mine_site_delivery: chkLAD
53
+ :mine_site_pickup: chkLAP
54
+ :motel_delivery: chkLAD
55
+ :motel_pickup: chkLAP
56
+ :nursing_home_delivery: chkLAD
57
+ :nursing_home_pickup: chkLAP
58
+ :park_delivery: chkLAD
59
+ :park_pickup: chkLAP
60
+ :prison_delivery: chkLAD
61
+ :prison_pickup: chkLAP
62
+ :ranch_delivery: chkLAD
63
+ :ranch_pickup: chkLAP
64
+ :reservation_delivery: chkLAD
65
+ :reservation_pickup: chkLAP
66
+ :residential_delivery: chkPR
67
+ :residential_pickup: chkPR
68
+ :resort_delivery: chkLAD
69
+ :resort_pickup: chkLAP
70
+ :restaurant_delivery: chkLAD
71
+ :restaurant_pickup: chkLAP
72
+ :school_delivery: chkLAD
73
+ :school_pickup: chkLAP
74
+ :steel_mill_delivery: chkLAD
75
+ :steel_mill_pickup: chkLAP
76
+ :storage_facility_delivery: chkLAD
77
+ :storage_facility_pickup: chkLAP
78
+ :university_delivery: chkLAD
79
+ :university_pickup: chkLAP
80
+ :utility_site_delivery: chkLAD
81
+ :utility_site_pickup: chkLAP
82
+ # May be inaccurate
83
+ :unquotable:
84
+ - :dock_pickup
85
+ # May be inaccurate
86
+ :unserviceable:
87
+ - :afterhours_delivery
88
+ - :afterhours_pickup
89
+ - :appointment_pickup
90
+ - :brewery_delivery
91
+ - :brewery_pickup
92
+ - :customs_brokerage
93
+ - :driver_assist
94
+ - :early_morning_delivery
95
+ - :early_morning_pickup
96
+ - :flatbed_delivery
97
+ - :flatbed_pickup
98
+ - :grocery_warehouse_delivery
99
+ - :grocery_warehouse_pickup
100
+ - :winery_delivery
101
+ - :winery_pickup
102
+ :api:
103
+ :domain: www.sefl.com
104
+ :endpoints:
105
+ :rates: /webconnect/ratequotes/rest/submitQuote
106
+ :methods:
107
+ :get_rate: :get
108
+ :rates: :post
109
+ :use_ssl: false
110
+ :attributes:
111
+ :rates:
112
+ :with_excessive_length_fees: true
113
+ :services:
114
+ :types:
115
+ - :standard
@@ -0,0 +1,107 @@
1
+ :accessorials:
2
+ :mappable:
3
+ :appointment_delivery: '&APPT=yes'
4
+ :inside_delivery: '&IDL=yes'
5
+ :inside_pickup: '&IDL=yes'
6
+ :liftgate_delivery: '&LIFT=yes'
7
+ :liftgate_pickup: '&LIFTP=yes'
8
+ :residential_delivery: '&RESI=yes'
9
+ :residential_pickup: '&RESP=yes'
10
+ # May be inaccurate
11
+ :unquotable:
12
+ - :amusement_park_delivery
13
+ - :amusement_park_pickup
14
+ - :athletic_facility_delivery
15
+ - :athletic_facility_delivery
16
+ - :athletic_facility_pickup
17
+ - :cemetery_delivery
18
+ - :cemetery_pickup
19
+ - :church_delivery
20
+ - :church_pickup
21
+ - :construction_delivery
22
+ - :construction_pickup
23
+ - :dock_dropoff
24
+ - :dock_pickup
25
+ - :farm_delivery
26
+ - :farm_pickup
27
+ - :fitness_center_delivery
28
+ - :fitness_center_pickup
29
+ - :golf_course_delivery
30
+ - :golf_course_pickup
31
+ - :government_delivery
32
+ - :government_pickup
33
+ - :grocery_store_delivery
34
+ - :grocery_store_pickup
35
+ - :hospital_delivery
36
+ - :hospital_pickup
37
+ - :hotel_delivery
38
+ - :hotel_pickup
39
+ - :inspection_site_delivery
40
+ - :inspection_site_pickup
41
+ - :jobsite_delivery
42
+ - :jobsite_pickup
43
+ - :mall_delivery
44
+ - :mall_pickup
45
+ - :marina_delivery
46
+ - :marina_pickup
47
+ - :mine_site_delivery
48
+ - :mine_site_pickup
49
+ - :motel_delivery
50
+ - :motel_pickup
51
+ - :nursing_home_delivery
52
+ - :nursing_home_pickup
53
+ - :park_delivery
54
+ - :park_pickup
55
+ - :prison_delivery
56
+ - :prison_pickup
57
+ - :ranch_delivery
58
+ - :ranch_pickup
59
+ - :reservation_delivery
60
+ - :reservation_pickup
61
+ - :resort_delivery
62
+ - :resort_pickup
63
+ - :restaurant_delivery
64
+ - :restaurant_pickup
65
+ - :school_delivery
66
+ - :school_pickup
67
+ - :steel_mill_delivery
68
+ - :steel_mill_pickup
69
+ - :storage_facility_delivery
70
+ - :storage_facility_pickup
71
+ - :university_delivery
72
+ - :university_pickup
73
+ - :utility_site_delivery
74
+ - :utility_site_pickup
75
+ # May be inaccurate
76
+ :unserviceable:
77
+ - :airport_delivery
78
+ - :airport_pickup
79
+ - :appointment_pickup
80
+ - :brewery_delivery
81
+ - :brewery_pickup
82
+ - :convention_delivery
83
+ - :convention_pickup
84
+ - :customs_brokerage
85
+ - :driver_assist
86
+ - :early_morning_delivery
87
+ - :fair_delivery
88
+ - :fair_pickup
89
+ - :flatbed_delivery
90
+ - :flatbed_pickup
91
+ - :grocery_warehouse_delivery
92
+ - :grocery_warehouse_pickup
93
+ - :guaranteed_delivery
94
+ - :guaranteed_delivery_am
95
+ - :guaranteed_delivery_pm
96
+ - :military_site_delivery
97
+ - :military_site_pickup
98
+ - :winery_delivery
99
+ - :winery_pickup
100
+ :api:
101
+ :carrier_code: tot
102
+ :attributes:
103
+ :rates:
104
+ :with_excessive_length_fees: true
105
+ :services:
106
+ :types:
107
+ - :standard
@@ -0,0 +1,19 @@
1
+ :api:
2
+ :domain: tracking.wrds.com
3
+ :endpoints:
4
+ :pod: /zLogin.aspx
5
+ :track: /zTrack2.aspx
6
+ :methods:
7
+ :track: :post
8
+ :use_ssl:
9
+ :bol: false
10
+ :pod: false
11
+ :track: true
12
+ :events:
13
+ :types:
14
+ :arrived_at_terminal: arrived
15
+ :delivered: delivered
16
+ :departed: departed
17
+ :services:
18
+ :types:
19
+ - :standard
@@ -0,0 +1,25 @@
1
+ :api:
2
+ :domain: tracking.carrierlogistics.com
3
+ :endpoints:
4
+ :bol: /scripts/@CARRIER_CODE@.pol/web-login.htm?
5
+ :pod: /scripts/@CARRIER_CODE@.pol/web-login.htm?
6
+ :rates: /scripts/@CARRIER_CODE@.pol/ratequote.xml?
7
+ :track: /scripts/@CARRIER_CODE@.pol/boldetail.htm?
8
+ :use_ssl:
9
+ :bol: true
10
+ :pod: true
11
+ :rates: true
12
+ :track: true
13
+ :attributes:
14
+ :rates:
15
+ :with_excessive_length_fees: false
16
+ :events:
17
+ :types:
18
+ :arrived_at_terminal: trailer arrived
19
+ :delivered: delivered
20
+ :departed: trailer departed
21
+ :out_for_delivery: out for delivery
22
+ :picked_up: picked up
23
+ :pickup_scheduled: pickup request received
24
+ :trailer_closed: loaded on trailer
25
+ :trailer_unloaded: undisp
@@ -0,0 +1,12 @@
1
+ :api:
2
+ :endpoints:
3
+ :authenticate: /authenticate
4
+ :show: /shipments
5
+ :methods:
6
+ :authenticate: :post
7
+ :show: :get
8
+ :prefix: /api/v1
9
+ :scopes:
10
+ :broker: /broker
11
+ :customer: /customer
12
+ :use_ssl: true
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReactiveShipping
4
+ class Package
5
+ VALID_FREIGHT_CLASSES = [55, 60, 65, 70, 77.5, 85, 92.5, 100, 110, 125, 150, 175, 200, 250, 300, 400].freeze
6
+
7
+ attr_writer :declared_freight_class
8
+
9
+ def initialize(grams_or_ounces, dimensions, options = {})
10
+ options = @@default_options.update(options) if @@default_options
11
+ options.symbolize_keys!
12
+ @options = options
13
+
14
+ # For backward compatibility
15
+ if dimensions.is_a?(Array)
16
+ @dimensions = [dimensions].flatten.reject(&:nil?)
17
+ else
18
+ @dimensions = [dimensions.dig(:height), dimensions.dig(:width), dimensions.dig(:length)]
19
+ @dimensions = [@dimensions].flatten.reject(&:nil?)
20
+ end
21
+
22
+ imperial = (options[:units] == :imperial)
23
+
24
+ weight_imperial = dimensions_imperial = imperial if options.include?(:units)
25
+
26
+ if options.include?(:weight_units)
27
+ weight_imperial = (options[:weight_units] == :imperial)
28
+ end
29
+
30
+ if options.include?(:dim_units)
31
+ dimensions_imperial = (options[:dim_units] == :imperial)
32
+ end
33
+
34
+ @weight_unit_system = weight_imperial ? :imperial : :metric
35
+ @dimensions_unit_system = dimensions_imperial ? :imperial : :metric
36
+
37
+ @weight = attribute_from_metric_or_imperial(grams_or_ounces, Measured::Weight, @weight_unit_system, :grams, :ounces)
38
+
39
+ if @dimensions.blank?
40
+ zero_length = Measured::Length.new(0, (dimensions_imperial ? :inches : :centimetres))
41
+ @dimensions = [zero_length] * 3
42
+ else
43
+ # Overriding ReactiveShipping's protected process_dimensions which sorts
44
+ # them making it confusing for ReactiveFreight carrier API's that expect
45
+ # the H x W x L order. Since H x W x L is nonstandard in the freight
46
+ # industry ReactiveFreight introduces explicit functions for each
47
+ @dimensions = @dimensions.map do |l|
48
+ attribute_from_metric_or_imperial(l, Measured::Length, @dimensions_unit_system, :centimetres, :inches)
49
+ end
50
+ 2.downto(@dimensions.length) do |_n|
51
+ @dimensions.unshift(@dimensions[0])
52
+ end
53
+ end
54
+
55
+ @value = Package.cents_from(options[:value])
56
+ @currency = options[:currency] || (options[:value].currency if options[:value].respond_to?(:currency))
57
+ @cylinder = (options[:cylinder] || options[:tube]) ? true : false
58
+ @gift = options[:gift] ? true : false
59
+ @oversized = options[:oversized] ? true : false
60
+ @unpackaged = options[:unpackaged] ? true : false
61
+ end
62
+
63
+ def cubic_ft
64
+ if !inches[0].blank? && !inches[1].blank? && !inches[2].blank?
65
+ cubic_ft = (inches[0] * inches[1] * inches[2]).to_f / 1728
66
+ return ('%0.2f' % cubic_ft).to_f
67
+ end
68
+ nil
69
+ end
70
+
71
+ def density
72
+ if !inches[0].blank? && !inches[1].blank? && !inches[2].blank? && pounds
73
+ density = pounds.to_f / cubic_ft
74
+ return ('%0.2f' % density).to_f
75
+ end
76
+ nil
77
+ end
78
+
79
+ def calculated_freight_class
80
+ sanitized_freight_class(density_to_freight_class(density))
81
+ end
82
+
83
+ def declared_freight_class
84
+ @declared_freight_class || @options[:declared_freight_class]
85
+ end
86
+
87
+ def freight_class
88
+ declared_freight_class.blank? ? calculated_freight_class : declared_freight_class
89
+ end
90
+
91
+ def length(unit)
92
+ @dimensions[2].convert_to(unit).value.to_f
93
+ end
94
+
95
+ def width(unit)
96
+ @dimensions[1].convert_to(unit).value.to_f
97
+ end
98
+
99
+ def height(unit)
100
+ @dimensions[0].convert_to(unit).value.to_f
101
+ end
102
+
103
+ protected
104
+
105
+ def density_to_freight_class(density)
106
+ return nil unless density
107
+ return 400 if density < 1
108
+ return 60 if density > 30
109
+
110
+ density_table = [
111
+ [1, 2, 300],
112
+ [2, 4, 250],
113
+ [4, 6, 175],
114
+ [6, 8, 125],
115
+ [8, 10, 100],
116
+ [10, 12, 92.5],
117
+ [12, 15, 85],
118
+ [15, 22.5, 70],
119
+ [22.5, 30, 65],
120
+ [30, 35, 60]
121
+ ]
122
+ density_table.each do |density_row|
123
+ return density_row[2] if (density >= density_row[0]) && (density < density_row[1])
124
+ end
125
+ end
126
+
127
+ def sanitized_freight_class(freight_class)
128
+ return nil if freight_class.blank?
129
+
130
+ if VALID_FREIGHT_CLASSES.include?(freight_class)
131
+ return freight_class.to_i == freight_class ? freight_class.to_i : freight_class
132
+ end
133
+
134
+ nil
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReactiveShipping
4
+ class Platform < ReactiveShipping::Carrier
5
+ attr_accessor :conf
6
+
7
+ def initialize(options = {})
8
+ requirements.each { |key| requires!(options, key) }
9
+ @conf = nil
10
+ @debug = options[:debug].blank? ? false : true
11
+ @options = options
12
+ @last_request = nil
13
+ @test_mode = @options[:test]
14
+
15
+ conf_path = File.join(__dir__, 'configuration', 'platforms', "#{self.class.ancestors[1].name.split('::')[1].underscore}.yml")
16
+ @conf = YAML.safe_load(File.read(conf_path), permitted_classes: [Symbol])
17
+
18
+ conf_path = File.join(__dir__, 'configuration', 'carriers', "#{self.class.to_s.split('::')[1].underscore}.yml")
19
+ @conf = @conf.deep_merge(YAML.safe_load(File.read(conf_path), permitted_classes: [Symbol]))
20
+
21
+ @rates_with_excessive_length_fees = @conf.dig(:attributes, :rates, :with_excessive_length_fees)
22
+ end
23
+
24
+ def find_bol(*)
25
+ raise NotImplementedError, "#{self.class.name}: #find_bol not supported"
26
+ end
27
+
28
+ def find_estimate(*)
29
+ raise NotImplementedError, "#{self.class.name}: #find_estimate not supported"
30
+ end
31
+
32
+ def find_pod(*)
33
+ raise NotImplementedError, "#{self.class.name}: #find_pod not supported"
34
+ end
35
+ end
36
+ end