reactive_freight 0.0.1

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.
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