freight_kit 0.1.19 → 0.1.21

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 (439) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/Gemfile.lock +51 -52
  4. data/README.md +37 -2
  5. data/Rakefile +6 -0
  6. data/VERSION +1 -1
  7. data/configuration/locations/amazon_warehouses.yml +3330 -0
  8. data/freight_kit.gemspec +21 -18
  9. data/lib/freight_kit/address_normalizer.rb +26 -0
  10. data/lib/freight_kit/amazon_warehouse.rb +33 -0
  11. data/lib/freight_kit/api_clients/soap_client.rb +7 -9
  12. data/lib/freight_kit/carrier.rb +250 -303
  13. data/lib/freight_kit/carriers/a1_express.rb +25 -0
  14. data/lib/freight_kit/carriers/a_duie_pyle.rb +30 -0
  15. data/lib/freight_kit/carriers/aaa_cooper.rb +11 -0
  16. data/lib/freight_kit/carriers/aaa_expedited_services.rb +10 -0
  17. data/lib/freight_kit/carriers/ab_brothers_usa_inc.rb +12 -0
  18. data/lib/freight_kit/carriers/aberdeen_express_inc.rb +28 -0
  19. data/lib/freight_kit/carriers/abf_freight_system.rb +492 -0
  20. data/lib/freight_kit/carriers/access_transport.rb +10 -0
  21. data/lib/freight_kit/carriers/action_express.rb +10 -0
  22. data/lib/freight_kit/carriers/adams_and_companies.rb +10 -0
  23. data/lib/freight_kit/carriers/advance_distribution.rb +28 -0
  24. data/lib/freight_kit/carriers/alcon_transport.rb +10 -0
  25. data/lib/freight_kit/carriers/all_freight.rb +10 -0
  26. data/lib/freight_kit/carriers/alliance_transportation_group.rb +10 -0
  27. data/lib/freight_kit/carriers/allstate_transport.rb +10 -0
  28. data/lib/freight_kit/carriers/aloha_freight_forwarders.rb +35 -0
  29. data/lib/freight_kit/carriers/amado_trucking.rb +35 -0
  30. data/lib/freight_kit/carriers/american_fast_freight.rb +28 -0
  31. data/lib/freight_kit/carriers/amigos_service_transportation.rb +10 -0
  32. data/lib/freight_kit/carriers/anderson_towing_and_transport.rb +10 -0
  33. data/lib/freight_kit/carriers/apex_transporting.rb +10 -0
  34. data/lib/freight_kit/carriers/archer_cargo.rb +35 -0
  35. data/lib/freight_kit/carriers/armstrong_transport_group.rb +10 -0
  36. data/lib/freight_kit/carriers/autobahn_logistics.rb +10 -0
  37. data/lib/freight_kit/carriers/averitt_express.rb +30 -0
  38. data/lib/freight_kit/carriers/ba_transportation.rb +10 -0
  39. data/lib/freight_kit/carriers/balkin_express.rb +10 -0
  40. data/lib/freight_kit/carriers/bay_area_express.rb +10 -0
  41. data/lib/freight_kit/carriers/bc_freightways.rb +11 -0
  42. data/lib/freight_kit/carriers/benjamin_best_freight_inc.rb +37 -0
  43. data/lib/freight_kit/carriers/bennett_trucking.rb +10 -0
  44. data/lib/freight_kit/carriers/best_overnite_express.rb +78 -0
  45. data/lib/freight_kit/carriers/best_trucking.rb +10 -0
  46. data/lib/freight_kit/carriers/bestway_transport.rb +10 -0
  47. data/lib/freight_kit/carriers/bryan_systems.rb +10 -0
  48. data/lib/freight_kit/carriers/c_and_w_express.rb +10 -0
  49. data/lib/freight_kit/carriers/campbell_trucking.rb +10 -0
  50. data/lib/freight_kit/carriers/carde_transportation.rb +10 -0
  51. data/lib/freight_kit/carriers/cardinal_logistics.rb +28 -0
  52. data/lib/freight_kit/carriers/cdc_transport.rb +10 -0
  53. data/lib/freight_kit/carriers/cdo_express_diversified.rb +10 -0
  54. data/lib/freight_kit/carriers/cedar_supply_trucking.rb +10 -0
  55. data/lib/freight_kit/carriers/central_freight_lines.rb +12 -0
  56. data/lib/freight_kit/carriers/central_transport.rb +12 -0
  57. data/lib/freight_kit/carriers/chicago_suburban_express.rb +28 -0
  58. data/lib/freight_kit/carriers/city_logistics.rb +11 -0
  59. data/lib/freight_kit/carriers/clear_lane_freight_systems.rb +483 -0
  60. data/lib/freight_kit/carriers/cleopatra_trucking.rb +10 -0
  61. data/lib/freight_kit/carriers/clifford_transportation.rb +10 -0
  62. data/lib/freight_kit/carriers/cms_domestic.rb +25 -0
  63. data/lib/freight_kit/carriers/cnd_logistics.rb +10 -0
  64. data/lib/freight_kit/carriers/coast_to_coast_transport.rb +27 -0
  65. data/lib/freight_kit/carriers/countrywide_carriers.rb +10 -0
  66. data/lib/freight_kit/carriers/cpl_express.rb +35 -0
  67. data/lib/freight_kit/carriers/crosby_trucking_service.rb +29 -0
  68. data/lib/freight_kit/carriers/cross_country_freight_solutions.rb +419 -0
  69. data/lib/freight_kit/carriers/crowley.rb +10 -0
  70. data/lib/freight_kit/carriers/csa_transportation.rb +40 -0
  71. data/lib/freight_kit/carriers/csx_transportation.rb +40 -0
  72. data/lib/freight_kit/carriers/custom_global_logistics.rb +14 -0
  73. data/lib/freight_kit/carriers/d_and_a_transport.rb +10 -0
  74. data/lib/freight_kit/carriers/dak_transport.rb +10 -0
  75. data/lib/freight_kit/carriers/dash_courier_and_logistics_north_carolina.rb +10 -0
  76. data/lib/freight_kit/carriers/daylight_transport.rb +29 -0
  77. data/lib/freight_kit/carriers/dayton_freight_lines.rb +30 -0
  78. data/lib/freight_kit/carriers/dbr_logistics.rb +10 -0
  79. data/lib/freight_kit/carriers/deep_south_freight.rb +27 -0
  80. data/lib/freight_kit/carriers/delta_express.rb +10 -0
  81. data/lib/freight_kit/carriers/delta_transport.rb +10 -0
  82. data/lib/freight_kit/carriers/delta_trucking_logistics.rb +10 -0
  83. data/lib/freight_kit/carriers/demco_express.rb +10 -0
  84. data/lib/freight_kit/carriers/dependable_global_express.rb +10 -0
  85. data/lib/freight_kit/carriers/dependable_hawaiian_express.rb +24 -0
  86. data/lib/freight_kit/carriers/dependable_highway_express.rb +585 -0
  87. data/lib/freight_kit/carriers/desert_coastal_transport.rb +10 -0
  88. data/lib/freight_kit/carriers/dhl.rb +11 -0
  89. data/lib/freight_kit/carriers/diamond_line_delivery.rb +174 -0
  90. data/lib/freight_kit/carriers/ding_tai_trucking.rb +10 -0
  91. data/lib/freight_kit/carriers/diversified_transfer_and_storage.rb +29 -0
  92. data/lib/freight_kit/carriers/dohrn_transfer_company.rb +30 -0
  93. data/lib/freight_kit/carriers/dot_line_transportation.rb +29 -0
  94. data/lib/freight_kit/carriers/drt_transportation.rb +13 -0
  95. data/lib/freight_kit/carriers/dugan_truck_line.rb +29 -0
  96. data/lib/freight_kit/carriers/dupont.rb +10 -0
  97. data/lib/freight_kit/carriers/e_transport_carriers.rb +29 -0
  98. data/lib/freight_kit/carriers/echo_global_logistics.rb +13 -0
  99. data/lib/freight_kit/carriers/ecklund_logistics.rb +10 -0
  100. data/lib/freight_kit/carriers/el_emplumado_transport.rb +10 -0
  101. data/lib/freight_kit/carriers/elite_carriers.rb +28 -0
  102. data/lib/freight_kit/carriers/emerald_express.rb +10 -0
  103. data/lib/freight_kit/carriers/era_transport.rb +10 -0
  104. data/lib/freight_kit/carriers/estes_express_lines.rb +25 -0
  105. data/lib/freight_kit/carriers/euro_kam.rb +28 -0
  106. data/lib/freight_kit/carriers/ew_riverside_trucking.rb +10 -0
  107. data/lib/freight_kit/carriers/express_2000_inc.rb +12 -0
  108. data/lib/freight_kit/carriers/express_services_international.rb +10 -0
  109. data/lib/freight_kit/carriers/f_and_a_express.rb +27 -0
  110. data/lib/freight_kit/carriers/fairmont_logistics.rb +13 -0
  111. data/lib/freight_kit/carriers/fargo_cargo.rb +10 -0
  112. data/lib/freight_kit/carriers/fast_freight_transportation.rb +10 -0
  113. data/lib/freight_kit/carriers/fast_load_transport.rb +10 -0
  114. data/lib/freight_kit/carriers/fed_ex_express.rb +30 -0
  115. data/lib/freight_kit/carriers/fed_ex_ground.rb +24 -0
  116. data/lib/freight_kit/carriers/fed_ex_ltl_economy.rb +11 -0
  117. data/lib/freight_kit/carriers/fed_ex_ltl_priority.rb +11 -0
  118. data/lib/freight_kit/carriers/first_trucking_express.rb +10 -0
  119. data/lib/freight_kit/carriers/flash_trucking.rb +10 -0
  120. data/lib/freight_kit/carriers/fort_transportation_and_service_company_inc.rb +37 -0
  121. data/lib/freight_kit/carriers/forward_air.rb +789 -0
  122. data/lib/freight_kit/carriers/frahtex.rb +10 -0
  123. data/lib/freight_kit/carriers/frozen_food_express.rb +10 -0
  124. data/lib/freight_kit/carriers/gholia_bros_trucking.rb +36 -0
  125. data/lib/freight_kit/carriers/global_cargo.rb +10 -0
  126. data/lib/freight_kit/carriers/global_logistics_and_transportation.rb +10 -0
  127. data/lib/freight_kit/carriers/gls_freight.rb +32 -0
  128. data/lib/freight_kit/carriers/go_trucking_services.rb +10 -0
  129. data/lib/freight_kit/carriers/gold_eagle_transportation.rb +11 -0
  130. data/lib/freight_kit/carriers/golden_drop_trucking.rb +10 -0
  131. data/lib/freight_kit/carriers/gonzalez_transportation.rb +10 -0
  132. data/lib/freight_kit/carriers/gps_transport.rb +10 -0
  133. data/lib/freight_kit/carriers/greene_enterprise.rb +10 -0
  134. data/lib/freight_kit/carriers/gsa_international.rb +10 -0
  135. data/lib/freight_kit/carriers/gsp_express.rb +24 -0
  136. data/lib/freight_kit/carriers/gsv_transportation.rb +10 -0
  137. data/lib/freight_kit/carriers/gta_transportation.rb +10 -0
  138. data/lib/freight_kit/carriers/guam_freight_services.rb +10 -0
  139. data/lib/freight_kit/carriers/harrah_transportation.rb +23 -0
  140. data/lib/freight_kit/carriers/her_trucking.rb +10 -0
  141. data/lib/freight_kit/carriers/hercules_freight.rb +20 -0
  142. data/lib/freight_kit/carriers/highlander_xpress.rb +36 -0
  143. data/lib/freight_kit/carriers/hn_transport.rb +10 -0
  144. data/lib/freight_kit/carriers/honolulu_freight_service.rb +10 -0
  145. data/lib/freight_kit/carriers/hot_line_freight_system_inc.rb +12 -0
  146. data/lib/freight_kit/carriers/hotshot_freight_of_texas.rb +13 -0
  147. data/lib/freight_kit/carriers/houser_transport.rb +27 -0
  148. data/lib/freight_kit/carriers/infiniti_freight_logistics.rb +28 -0
  149. data/lib/freight_kit/carriers/infinity_trucking.rb +10 -0
  150. data/lib/freight_kit/carriers/interstate_tma.rb +10 -0
  151. data/lib/freight_kit/carriers/intrade_industries.rb +10 -0
  152. data/lib/freight_kit/carriers/jasper_trucking.rb +28 -0
  153. data/lib/freight_kit/carriers/jb_hunt.rb +11 -0
  154. data/lib/freight_kit/carriers/jfj_transportation.rb +8 -8
  155. data/lib/freight_kit/carriers/jkb_express.rb +10 -0
  156. data/lib/freight_kit/carriers/jlm_transport.rb +10 -0
  157. data/lib/freight_kit/carriers/johansson_transport.rb +10 -0
  158. data/lib/freight_kit/carriers/jones_express.rb +10 -0
  159. data/lib/freight_kit/carriers/jp_logistics.rb +41 -0
  160. data/lib/freight_kit/carriers/just_in_time_cargo.rb +29 -0
  161. data/lib/freight_kit/carriers/kengkok_times.rb +10 -0
  162. data/lib/freight_kit/carriers/kings_express.rb +10 -0
  163. data/lib/freight_kit/carriers/klc_transportation.rb +10 -0
  164. data/lib/freight_kit/carriers/km_trucking.rb +10 -0
  165. data/lib/freight_kit/carriers/kma_logistics.rb +10 -0
  166. data/lib/freight_kit/carriers/krc_logistics.rb +10 -0
  167. data/lib/freight_kit/carriers/ktx.rb +10 -0
  168. data/lib/freight_kit/carriers/landstar.rb +25 -0
  169. data/lib/freight_kit/carriers/lanter_distributing_llc.rb +30 -0
  170. data/lib/freight_kit/carriers/ld_trucking.rb +10 -0
  171. data/lib/freight_kit/carriers/legacy_logistics_solutions.rb +10 -0
  172. data/lib/freight_kit/carriers/leonards_express.rb +10 -0
  173. data/lib/freight_kit/carriers/liberty_linehaul_west.rb +28 -0
  174. data/lib/freight_kit/carriers/liberty_transport.rb +10 -0
  175. data/lib/freight_kit/carriers/lightning_express.rb +10 -0
  176. data/lib/freight_kit/carriers/lj_express.rb +24 -0
  177. data/lib/freight_kit/carriers/lkp_enterprises.rb +10 -0
  178. data/lib/freight_kit/carriers/ltl_pros.rb +28 -0
  179. data/lib/freight_kit/carriers/m_and_m_and_sons.rb +10 -0
  180. data/lib/freight_kit/carriers/mag_lines_transport.rb +10 -0
  181. data/lib/freight_kit/carriers/magic_messenger.rb +24 -0
  182. data/lib/freight_kit/carriers/majors_transit.rb +10 -0
  183. data/lib/freight_kit/carriers/map_global_logistics.rb +10 -0
  184. data/lib/freight_kit/carriers/matths_trucking.rb +11 -0
  185. data/lib/freight_kit/carriers/mav_canadian_transport.rb +13 -0
  186. data/lib/freight_kit/carriers/mc_systems.rb +35 -0
  187. data/lib/freight_kit/carriers/mega_fleet.rb +10 -0
  188. data/lib/freight_kit/carriers/mega_trans_group.rb +28 -0
  189. data/lib/freight_kit/carriers/meta_express.rb +10 -0
  190. data/lib/freight_kit/carriers/mia_transportation.rb +10 -0
  191. data/lib/freight_kit/carriers/midwest_motor_express.rb +14 -0
  192. data/lib/freight_kit/carriers/midwest_transport_and_trucking.rb +10 -0
  193. data/lib/freight_kit/carriers/mikade_delivery_service.rb +10 -0
  194. data/lib/freight_kit/carriers/mohoff_freight_lines.rb +23 -0
  195. data/lib/freight_kit/carriers/montata_travelers_express.rb +10 -0
  196. data/lib/freight_kit/carriers/morgan_van_lines.rb +29 -0
  197. data/lib/freight_kit/carriers/moto_transportation.rb +24 -0
  198. data/lib/freight_kit/carriers/mountain_valley_express.rb +197 -0
  199. data/lib/freight_kit/carriers/ms_freight.rb +27 -0
  200. data/lib/freight_kit/carriers/mvg_transport.rb +10 -0
  201. data/lib/freight_kit/carriers/n_and_m_transfer_co_inc.rb +29 -0
  202. data/lib/freight_kit/carriers/nabot_transport_solutions.rb +10 -0
  203. data/lib/freight_kit/carriers/national_freight_xpress.rb +10 -0
  204. data/lib/freight_kit/carriers/navigation_group.rb +10 -0
  205. data/lib/freight_kit/carriers/nelson_trucking.rb +10 -0
  206. data/lib/freight_kit/carriers/network_1_transportation.rb +10 -0
  207. data/lib/freight_kit/carriers/new_century_transport.rb +28 -0
  208. data/lib/freight_kit/carriers/new_penn_motor_express.rb +11 -0
  209. data/lib/freight_kit/carriers/nieves_transportation.rb +10 -0
  210. data/lib/freight_kit/carriers/nolan_transportation_group.rb +26 -0
  211. data/lib/freight_kit/carriers/northland_trucking.rb +10 -0
  212. data/lib/freight_kit/carriers/northwest_carrier_logistics.rb +27 -0
  213. data/lib/freight_kit/carriers/nt_usa.rb +10 -0
  214. data/lib/freight_kit/carriers/nu_line_transportation.rb +10 -0
  215. data/lib/freight_kit/carriers/numark_transportation.rb +80 -0
  216. data/lib/freight_kit/carriers/nvk_transport.rb +10 -0
  217. data/lib/freight_kit/carriers/ny_transport.rb +10 -0
  218. data/lib/freight_kit/carriers/oak_harbor.rb +28 -0
  219. data/lib/freight_kit/carriers/oakline_transportation.rb +10 -0
  220. data/lib/freight_kit/carriers/old_dominion_freight_line.rb +30 -0
  221. data/lib/freight_kit/carriers/on_trac.rb +573 -0
  222. data/lib/freight_kit/carriers/one_hundred_one_transport.rb +10 -0
  223. data/lib/freight_kit/carriers/one_way_delivery.rb +10 -0
  224. data/lib/freight_kit/carriers/oracle_transportation_solutions.rb +10 -0
  225. data/lib/freight_kit/carriers/orange_courier.rb +27 -0
  226. data/lib/freight_kit/carriers/ortas_trucking.rb +10 -0
  227. data/lib/freight_kit/carriers/pac_trux_transportation.rb +10 -0
  228. data/lib/freight_kit/carriers/pacer.rb +10 -0
  229. data/lib/freight_kit/carriers/pacific_logistics.rb +10 -0
  230. data/lib/freight_kit/carriers/pacific_states_truck_lines.rb +10 -0
  231. data/lib/freight_kit/carriers/paradise_distributing.rb +10 -0
  232. data/lib/freight_kit/carriers/paramount_freight_systems.rb +10 -0
  233. data/lib/freight_kit/carriers/peninsula_truck_lines.rb +222 -0
  234. data/lib/freight_kit/carriers/pg_transport.rb +10 -0
  235. data/lib/freight_kit/carriers/pgs_360.rb +10 -0
  236. data/lib/freight_kit/carriers/pilot_freight_services.rb +10 -0
  237. data/lib/freight_kit/carriers/pious_trans.rb +27 -0
  238. data/lib/freight_kit/carriers/pitt_ohio_express.rb +30 -0
  239. data/lib/freight_kit/carriers/pki_logistics.rb +12 -0
  240. data/lib/freight_kit/carriers/plana_transportation.rb +28 -0
  241. data/lib/freight_kit/carriers/prestige.rb +10 -0
  242. data/lib/freight_kit/carriers/pro_trans_solutions.rb +28 -0
  243. data/lib/freight_kit/carriers/puma_logistics.rb +10 -0
  244. data/lib/freight_kit/carriers/pwc_international.rb +10 -0
  245. data/lib/freight_kit/carriers/quality_logistics.rb +10 -0
  246. data/lib/freight_kit/carriers/queen_star_trucking.rb +27 -0
  247. data/lib/freight_kit/carriers/r_and_l_carriers.rb +11 -0
  248. data/lib/freight_kit/carriers/rac_transport.rb +10 -0
  249. data/lib/freight_kit/carriers/re_logistics.rb +23 -0
  250. data/lib/freight_kit/carriers/reddaway.rb +11 -0
  251. data/lib/freight_kit/carriers/reefer_van_network.rb +13 -0
  252. data/lib/freight_kit/carriers/refrigerated_trucking_and_ltl_transportation_services.rb +10 -0
  253. data/lib/freight_kit/carriers/ridgeline_express.rb +10 -0
  254. data/lib/freight_kit/carriers/rist_transport.rb +29 -0
  255. data/lib/freight_kit/carriers/river_city_transport.rb +10 -0
  256. data/lib/freight_kit/carriers/roadrunner_transportation_services.rb +675 -0
  257. data/lib/freight_kit/carriers/roadtex.rb +13 -0
  258. data/lib/freight_kit/carriers/ronald_transport_services.rb +10 -0
  259. data/lib/freight_kit/carriers/rose_trucking.rb +24 -0
  260. data/lib/freight_kit/carriers/rp_and_j_transport.rb +24 -0
  261. data/lib/freight_kit/carriers/rpm_transportation.rb +11 -0
  262. data/lib/freight_kit/carriers/rude_transportation.rb +30 -0
  263. data/lib/freight_kit/carriers/s_and_s_logistics.rb +10 -0
  264. data/lib/freight_kit/carriers/saia.rb +470 -363
  265. data/lib/freight_kit/carriers/sb_transportation.rb +27 -0
  266. data/lib/freight_kit/carriers/schneider_national.rb +29 -0
  267. data/lib/freight_kit/carriers/schwarz_trucking.rb +10 -0
  268. data/lib/freight_kit/carriers/sewell_motor_express.rb +29 -0
  269. data/lib/freight_kit/carriers/shawnee_trucking.rb +28 -0
  270. data/lib/freight_kit/carriers/shi_logistics.rb +10 -0
  271. data/lib/freight_kit/carriers/sinbad_transport.rb +10 -0
  272. data/lib/freight_kit/carriers/skyway.rb +10 -0
  273. data/lib/freight_kit/carriers/smith_cargo_transportation_services.rb +23 -0
  274. data/lib/freight_kit/carriers/sna_transportation.rb +10 -0
  275. data/lib/freight_kit/carriers/solid_group.rb +10 -0
  276. data/lib/freight_kit/carriers/solution_carrier_express.rb +10 -0
  277. data/lib/freight_kit/carriers/southeastern_freight_lines.rb +450 -0
  278. data/lib/freight_kit/carriers/southwestern_motor_transport.rb +30 -0
  279. data/lib/freight_kit/carriers/span_alaska.rb +10 -0
  280. data/lib/freight_kit/carriers/specialize_transportation.rb +27 -0
  281. data/lib/freight_kit/carriers/ssi_refrigerated_express.rb +10 -0
  282. data/lib/freight_kit/carriers/standard_forwarding_llc.rb +28 -0
  283. data/lib/freight_kit/carriers/star_american_enterprise.rb +10 -0
  284. data/lib/freight_kit/carriers/sterling_transportation.rb +10 -0
  285. data/lib/freight_kit/carriers/stg.rb +163 -0
  286. data/lib/freight_kit/carriers/supervan_service.rb +10 -0
  287. data/lib/freight_kit/carriers/sutton_transport_inc.rb +12 -0
  288. data/lib/freight_kit/carriers/swift_transportation.rb +28 -0
  289. data/lib/freight_kit/carriers/t_force_worldwide.rb +617 -0
  290. data/lib/freight_kit/carriers/tax_airfreight_inc.rb +35 -0
  291. data/lib/freight_kit/carriers/tforce_freight_inc.rb +30 -0
  292. data/lib/freight_kit/carriers/the_custom_companies.rb +162 -0
  293. data/lib/freight_kit/carriers/thk_trucking.rb +28 -0
  294. data/lib/freight_kit/carriers/tiger_cool_express.rb +11 -0
  295. data/lib/freight_kit/carriers/tili_logistics.rb +10 -0
  296. data/lib/freight_kit/carriers/tmt_industries.rb +10 -0
  297. data/lib/freight_kit/carriers/top_ten_express.rb +28 -0
  298. data/lib/freight_kit/carriers/total_quality_logistics.rb +338 -0
  299. data/lib/freight_kit/carriers/total_transportation.rb +258 -0
  300. data/lib/freight_kit/carriers/trans_international_trucking.rb +29 -0
  301. data/lib/freight_kit/carriers/treasure_transportation.rb +10 -0
  302. data/lib/freight_kit/carriers/tri_state_services.rb +10 -0
  303. data/lib/freight_kit/carriers/tritex_freighters.rb +10 -0
  304. data/lib/freight_kit/carriers/triways.rb +10 -0
  305. data/lib/freight_kit/carriers/tsi_kansas.rb +29 -0
  306. data/lib/freight_kit/carriers/u_and_r_transportation.rb +23 -0
  307. data/lib/freight_kit/carriers/union_pacific.rb +11 -0
  308. data/lib/freight_kit/carriers/united_freight_logistics.rb +10 -0
  309. data/lib/freight_kit/carriers/unlimited_distance_transportation.rb +10 -0
  310. data/lib/freight_kit/carriers/up_streamline.rb +10 -0
  311. data/lib/freight_kit/carriers/ups_freight.rb +12 -0
  312. data/lib/freight_kit/carriers/us_freightways.rb +10 -0
  313. data/lib/freight_kit/carriers/usa_truck.rb +28 -0
  314. data/lib/freight_kit/carriers/usf_holland.rb +11 -0
  315. data/lib/freight_kit/carriers/valley_cartage.rb +11 -0
  316. data/lib/freight_kit/carriers/vc_transport.rb +10 -0
  317. data/lib/freight_kit/carriers/vision_express.rb +11 -0
  318. data/lib/freight_kit/carriers/vision_logistics_group.rb +10 -0
  319. data/lib/freight_kit/carriers/vmg_transportation_group.rb +10 -0
  320. data/lib/freight_kit/carriers/volpe_express.rb +10 -0
  321. data/lib/freight_kit/carriers/ward_trucking.rb +29 -0
  322. data/lib/freight_kit/carriers/wdwb.rb +10 -0
  323. data/lib/freight_kit/carriers/western_flyer_express.rb +28 -0
  324. data/lib/freight_kit/carriers/western_regional_delivery_service.rb +271 -0
  325. data/lib/freight_kit/carriers/western_specialized_trucking.rb +22 -0
  326. data/lib/freight_kit/carriers/win_distribution.rb +28 -0
  327. data/lib/freight_kit/carriers/wlb_transport.rb +10 -0
  328. data/lib/freight_kit/carriers/x_trux.rb +29 -0
  329. data/lib/freight_kit/carriers/xpo_logistics.rb +427 -0
  330. data/lib/freight_kit/carriers/xpress_global_systems.rb +30 -0
  331. data/lib/freight_kit/carriers/xylo_trucking.rb +10 -0
  332. data/lib/freight_kit/carriers/yrc_freight.rb +24 -0
  333. data/lib/freight_kit/carriers/zentner_transportation.rb +28 -0
  334. data/lib/freight_kit/carriers.rb +332 -36
  335. data/lib/freight_kit/countries.rb +22 -0
  336. data/lib/freight_kit/error.rb +0 -2
  337. data/lib/freight_kit/errors/document_not_found_error.rb +0 -2
  338. data/lib/freight_kit/errors/expired_credentials_error.rb +0 -2
  339. data/lib/freight_kit/errors/http_error.rb +0 -2
  340. data/lib/freight_kit/errors/invalid_credentials_error.rb +0 -2
  341. data/lib/freight_kit/errors/response_error.rb +1 -3
  342. data/lib/freight_kit/errors/shipment_not_found_error.rb +0 -2
  343. data/lib/freight_kit/errors/unserviceable_accessorials_error.rb +2 -4
  344. data/lib/freight_kit/errors/unserviceable_error.rb +0 -2
  345. data/lib/freight_kit/helpers/documentable.rb +0 -2
  346. data/lib/freight_kit/helpers/pickupable.rb +3 -5
  347. data/lib/freight_kit/helpers/rateable.rb +0 -2
  348. data/lib/freight_kit/helpers/trackable.rb +0 -2
  349. data/lib/freight_kit/http_client/cache_store.rb +59 -0
  350. data/lib/freight_kit/http_client/log_device.rb +13 -0
  351. data/lib/freight_kit/http_client/response.rb +38 -0
  352. data/lib/freight_kit/http_client/revalidation.rb +25 -0
  353. data/lib/freight_kit/http_client/safe_retries.rb +23 -0
  354. data/lib/freight_kit/http_client/zstd.rb +28 -0
  355. data/lib/freight_kit/http_client.rb +76 -0
  356. data/lib/freight_kit/model.rb +1 -3
  357. data/lib/freight_kit/models/address.rb +15 -0
  358. data/lib/freight_kit/models/contact.rb +3 -4
  359. data/lib/freight_kit/models/country.rb +20 -0
  360. data/lib/freight_kit/models/credential.rb +14 -16
  361. data/lib/freight_kit/models/date_time.rb +0 -2
  362. data/lib/freight_kit/models/document_response.rb +0 -2
  363. data/lib/freight_kit/models/label.rb +0 -2
  364. data/lib/freight_kit/models/location.rb +10 -25
  365. data/lib/freight_kit/models/pickup_response.rb +0 -2
  366. data/lib/freight_kit/models/price.rb +0 -2
  367. data/lib/freight_kit/models/rate.rb +0 -2
  368. data/lib/freight_kit/models/rate_response.rb +0 -2
  369. data/lib/freight_kit/models/region.rb +19 -0
  370. data/lib/freight_kit/models/response.rb +0 -2
  371. data/lib/freight_kit/models/shipment.rb +4 -6
  372. data/lib/freight_kit/models/shipment_event.rb +0 -2
  373. data/lib/freight_kit/models/terminal.rb +10 -0
  374. data/lib/freight_kit/models/tracking_response.rb +0 -2
  375. data/lib/freight_kit/package.rb +52 -54
  376. data/lib/freight_kit/package_item.rb +15 -15
  377. data/lib/freight_kit/packaging.rb +21 -26
  378. data/lib/freight_kit/platform.rb +0 -32
  379. data/lib/freight_kit/platforms/carrier_logistics.rb +331 -345
  380. data/lib/freight_kit/platforms/next_tms.rb +93 -0
  381. data/lib/freight_kit/platforms/the_great_information_factory.rb +500 -426
  382. data/lib/freight_kit/regions.rb +27 -0
  383. data/lib/freight_kit/shipment_packer.rb +36 -38
  384. data/lib/freight_kit/tariff/overlength_rule.rb +1 -5
  385. data/lib/freight_kit/tariff.rb +0 -2
  386. data/lib/freight_kit.rb +89 -25
  387. metadata +454 -84
  388. data/configuration/carriers/abfs.yml +0 -124
  389. data/configuration/carriers/btvp.yml +0 -84
  390. data/configuration/carriers/ccyq.yml +0 -121
  391. data/configuration/carriers/clni.yml +0 -113
  392. data/configuration/carriers/cnwy.yml +0 -113
  393. data/configuration/carriers/ctbv.yml +0 -117
  394. data/configuration/carriers/dcha.yml +0 -105
  395. data/configuration/carriers/dlds.yml +0 -111
  396. data/configuration/carriers/dphe.yml +0 -130
  397. data/configuration/carriers/drrq.yml +0 -131
  398. data/configuration/carriers/fcsy.yml +0 -102
  399. data/configuration/carriers/fwda.yml +0 -137
  400. data/configuration/carriers/jfj_transportation.yml +0 -2
  401. data/configuration/carriers/mtvl.yml +0 -12
  402. data/configuration/carriers/numk.yml +0 -14
  403. data/configuration/carriers/otcl.yml +0 -124
  404. data/configuration/carriers/pens.yml +0 -22
  405. data/configuration/carriers/rdfs.yml +0 -142
  406. data/configuration/carriers/saia.yml +0 -129
  407. data/configuration/carriers/sefl.yml +0 -115
  408. data/configuration/carriers/totl.yml +0 -111
  409. data/configuration/carriers/tqyl.yml +0 -28
  410. data/configuration/carriers/wrds.yml +0 -20
  411. data/configuration/platforms/carrier_logistics.yml +0 -25
  412. data/configuration/platforms/next.yml +0 -12
  413. data/configuration/platforms/the_great_information_factory.yml +0 -122
  414. data/freight_kit-0.1.18.gem +0 -0
  415. data/lib/freight_kit/api_clients.rb +0 -3
  416. data/lib/freight_kit/carriers/abfs.rb +0 -421
  417. data/lib/freight_kit/carriers/btvp.rb +0 -29
  418. data/lib/freight_kit/carriers/ccyq.rb +0 -317
  419. data/lib/freight_kit/carriers/clni.rb +0 -396
  420. data/lib/freight_kit/carriers/cnwy.rb +0 -327
  421. data/lib/freight_kit/carriers/ctbv.rb +0 -53
  422. data/lib/freight_kit/carriers/dcha.rb +0 -76
  423. data/lib/freight_kit/carriers/dlds.rb +0 -49
  424. data/lib/freight_kit/carriers/dphe.rb +0 -474
  425. data/lib/freight_kit/carriers/drrq.rb +0 -580
  426. data/lib/freight_kit/carriers/fcsy.rb +0 -57
  427. data/lib/freight_kit/carriers/fwda.rb +0 -744
  428. data/lib/freight_kit/carriers/mtvl.rb +0 -34
  429. data/lib/freight_kit/carriers/numk.rb +0 -58
  430. data/lib/freight_kit/carriers/otcl.rb +0 -528
  431. data/lib/freight_kit/carriers/pens.rb +0 -204
  432. data/lib/freight_kit/carriers/rdfs.rb +0 -521
  433. data/lib/freight_kit/carriers/sefl.rb +0 -342
  434. data/lib/freight_kit/carriers/totl.rb +0 -172
  435. data/lib/freight_kit/carriers/tqyl.rb +0 -339
  436. data/lib/freight_kit/carriers/wrds.rb +0 -246
  437. data/lib/freight_kit/helpers.rb +0 -6
  438. data/lib/freight_kit/platforms/next.rb +0 -101
  439. data/lib/freight_kit/platforms.rb +0 -5
@@ -1,438 +1,545 @@
1
- # frozen_string_literal: true
2
-
3
1
  module FreightKit
4
- class SAIA < FreightKit::Carrier
5
- REACTIVE_FREIGHT_CARRIER = true
2
+ module Carriers
3
+ class Saia < FreightKit::Carrier
4
+ class << self
5
+ def check_mailing_addresses
6
+ [
7
+ Address.new(
8
+ city: 'Dallas',
9
+ country: Countries.find_by(iso31661_alpha2: 'US'),
10
+ id: '85c2c731-88c3-4768-808a-858fff783fa2',
11
+ postal_code: '75373',
12
+ region_abbreviation: 'TX',
13
+ street: 'PO Box 730532',
14
+ street2: '800 765 7242'
15
+ )
16
+ ]
17
+ end
6
18
 
7
- include FreightKit::Rateable
8
- include FreightKit::Trackable
19
+ def contacts
20
+ [Contact.new(department: 'Main', id: '8c2b4da9-b91a-4b72-a7df-6e21c3f12018', phone: '+17702325067')]
21
+ end
9
22
 
10
- class << self
11
- attr_reader :name, :scac
12
- end
13
- @name = 'Saia'
14
- @scac = 'SAIA'
23
+ def find_rates_with_declared_value? = true
24
+
25
+ def headquarters
26
+ Address.new(
27
+ city: 'Johns Creek',
28
+ country: Countries.find_by(iso31661_alpha2: 'US'),
29
+ id: '6d40ce8f-c88a-418e-b29d-db4c3239c945',
30
+ postal_code: '30097',
31
+ region_abbreviation: 'GA',
32
+ street: '11465 Johns Creek Pkwy Ste 400'
33
+ )
34
+ end
15
35
 
16
- class << self
17
- def find_rates_with_declared_value?
18
- true
19
- end
36
+ def id = '26a6a0c0-2e95-4835-ad73-4a3c8bb38cdd'
37
+ def legal_name = 'Saia Motor Freight Line LLC'
20
38
 
21
- def maximum_height
22
- Measured::Length.new(105, :inches)
23
- end
39
+ def mappable_accessorials
40
+ {
41
+ airport_delivery: 'LimitedAccessLocation',
42
+ airport_pickup: 'LimitedAccessLocationPU',
43
+ amusement_park_delivery: 'LimitedAccessLocation',
44
+ amusement_park_pickup: 'LimitedAccessLocationPU',
45
+ appointment_delivery: 'ArrivalNotice/Appointment',
46
+ cemetery_delivery: 'LimitedAccessLocation',
47
+ cemetery_pickup: 'LimitedAccessLocationPU',
48
+ church_delivery: 'LimitedAccessLocation',
49
+ church_pickup: 'LimitedAccessLocationPU',
50
+ construction_delivery: 'LimitedAccessLocation',
51
+ construction_pickup: 'LimitedAccessLocationPU',
52
+ convention_delivery: 'TradeShowDelivery',
53
+ convention_pickup: 'TradeShowPickup',
54
+ driver_assist: 'WhiteGlove',
55
+ fair_delivery: 'LimitedAccessLocation',
56
+ fair_pickup: 'LimitedAccessLocationPU',
57
+ government_delivery: 'LimitedAccessLocation',
58
+ government_pickup: 'LimitedAccessLocationPU',
59
+ inside_delivery: 'InsideDelivery',
60
+ inside_pickup: 'InsidePickup',
61
+ jobsite_delivery: 'LimitedAccessLocation',
62
+ jobsite_pickup: 'LimitedAccessLocationPU',
63
+ liftgate_delivery: 'LiftgateService',
64
+ liftgate_pickup: 'LiftgateServicePU',
65
+ marina_delivery: 'LimitedAccessLocation',
66
+ marina_pickup: 'LimitedAccessLocationPU',
67
+ military_site_delivery: 'LimitedAccessLocation',
68
+ military_site_pickup: 'LimitedAccessLocationPU',
69
+ mine_site_delivery: 'LimitedAccessLocation',
70
+ mine_site_pickup: 'LimitedAccessLocationPU',
71
+ prison_delivery: 'LimitedAccessLocation',
72
+ prison_pickup: 'LimitedAccessLocationPU',
73
+ residential_delivery: 'ResidentialDelivery',
74
+ residential_pickup: 'ResidentialPickup',
75
+ school_delivery: 'LimitedAccessLocation',
76
+ school_pickup: 'LimitedAccessLocationPU',
77
+ steel_mill_delivery: 'LimitedAccessLocation',
78
+ steel_mill_pickup: 'LimitedAccessLocationPU',
79
+ storage_facility_delivery: 'LimitedAccessLocation',
80
+ storage_facility_pickup: 'LimitedAccessLocationPU',
81
+ university_delivery: 'LimitedAccessLocation',
82
+ university_pickup: 'LimitedAccessLocationPU',
83
+ utility_site_delivery: 'LimitedAccessLocation',
84
+ utility_site_pickup: 'LimitedAccessLocationPU'
85
+ }
86
+ end
24
87
 
25
- def maximum_weight
26
- Measured::Weight.new(10_000, :pounds)
27
- end
88
+ def maximum_height = Measured::Length.new(105, :inches)
89
+ def maximum_weight = Measured::Weight.new(10_000, :pounds)
90
+ def minimum_length_for_overlength_fees = Measured::Length.new(8, :feet)
91
+ def name = 'Saia'
92
+ def overlength_fees_require_tariff? = false
93
+ def required_credential_types = %i[api]
94
+ def requirements = %i[credentials]
95
+ def scac = 'SAIA'
96
+ def services = %i[standard guaranteed_delivery guaranteed_delivery_am guaranteed_delivery_pm]
97
+
98
+ def unquotable_accessorials
99
+ %i[
100
+ athletic_facility_delivery
101
+ athletic_facility_pickup
102
+ brewery_delivery
103
+ brewery_pickup
104
+ dock_dropoff
105
+ dock_pickup
106
+ farm_delivery
107
+ farm_pickup
108
+ fitness_center_delivery
109
+ fitness_center_pickup
110
+ golf_course_delivery
111
+ golf_course_pickup
112
+ grocery_store_delivery
113
+ grocery_store_pickup
114
+ grocery_warehouse_delivery
115
+ grocery_warehouse_pickup
116
+ hospital_delivery
117
+ hospital_pickup
118
+ hotel_delivery
119
+ hotel_pickup
120
+ inspection_site_delivery
121
+ inspection_site_pickup
122
+ mall_delivery
123
+ mall_pickup
124
+ motel_delivery
125
+ motel_pickup
126
+ nursing_home_delivery
127
+ nursing_home_pickup
128
+ park_delivery
129
+ park_pickup
130
+ ranch_delivery
131
+ ranch_pickup
132
+ reservation_delivery
133
+ reservation_pickup
134
+ resort_delivery
135
+ resort_pickup
136
+ restaurant_delivery
137
+ restaurant_pickup
138
+ winery_delivery
139
+ winery_pickup
140
+ ]
141
+ end
28
142
 
29
- def minimum_length_for_overlength_fees
30
- Measured::Length.new(8, :feet)
31
- end
143
+ def unserviceable_accessorials
144
+ %i[
145
+ afterhours_delivery
146
+ afterhours_pickup
147
+ appointment_pickup
148
+ customs_brokerage
149
+ early_morning_delivery
150
+ early_morning_pickup
151
+ flatbed_delivery
152
+ flatbed_pickup
153
+ guaranteed_delivery
154
+ guaranteed_delivery_am
155
+ guaranteed_delivery_pm
156
+ ]
157
+ end
32
158
 
33
- def overlength_fees_require_tariff?
34
- false
35
- end
159
+ def us_dot_number = 29_124
160
+ def us_mc_number = 87_511
36
161
 
37
- def required_credential_types
38
- %i[api]
39
- end
162
+ def validate_packages(packages, _tariff = nil)
163
+ raise UnserviceableError, 'Must be fewer than 10 items altogether' if packages.sum(&:quantity) > 10
40
164
 
41
- def requirements
42
- %i[credentials]
43
- end
44
- end
165
+ super
166
+ end
45
167
 
46
- # Documents
168
+ def website_url = 'https://www.saia.com'
169
+ end
47
170
 
48
- # Rates
171
+ include FreightKit::Rateable
172
+ include FreightKit::Trackable
173
+
174
+ API = {
175
+ actions: { rates: :create, track: :get_by_pro_number },
176
+ domain: 'www.saiasecure.com',
177
+ endpoints: { rates: '/webservice/ratequote/soap.asmx?wsdl', track: '/webservice/shipment/soap.asmx?wsdl' },
178
+ use_ssl: true
179
+ }.freeze
180
+ EVENTS = {
181
+ types: {
182
+ arrived_at_terminal: 'arrived',
183
+ delivered: 'delivered',
184
+ departed: 'departed from terminal',
185
+ located: 'arrived at breakbulk terminal',
186
+ out_for_delivery: 'dispatched for delivery',
187
+ picked_up: 'pickup from customer',
188
+ trailer_unloaded: 'unload trailer',
189
+ trailer_closed: 'load trailer'
190
+ }
191
+ }.freeze
192
+
193
+ # Documents
194
+
195
+ # Rates
196
+
197
+ protected
198
+
199
+ # Rates
200
+ def build_rate_request(shipment:)
201
+ accessorials = [{ AccessorialItem: { Code: 'SingleShipment' } }]
202
+ if shipment.accessorials.present?
203
+ serviceable_accessorials?(shipment.accessorials)
204
+ shipment.accessorials.each do |a|
205
+ accessorials << { AccessorialItem: { Code: mappable_accessorials[a] } } if unserviceable_accessorials.exclude?(a)
206
+ end
207
+ end
49
208
 
50
- def validate_packages(packages, _tariff = nil)
51
- raise UnserviceableError, 'Must be fewer than 10 items altogether' if packages.sum(&:quantity) > 10
209
+ longest_dimension = shipment.packages.map { |p| [p.width(:inches), p.length(:inches)].max }.max.ceil
210
+ accessorials << { AccessorialItem: { Code: 'ExcessiveLength' } } if longest_dimension >= 96
211
+
212
+ accessorials = accessorials.uniq
213
+
214
+ details = []
215
+ dimensions = []
216
+ shipment.packages.each do |package|
217
+ package.quantity.times do
218
+ details << {
219
+ DetailItem: {
220
+ Weight: package.pounds(:each).ceil,
221
+ Class: package.freight_class.to_s,
222
+ Length: package.length(:in).ceil,
223
+ Width: package.width(:in).ceil,
224
+ Height: package.height(:in).ceil
225
+ }
226
+ }
227
+
228
+ # Keeping this one at a time to match with "details"
229
+ dimensions << {
230
+ DimensionItem: {
231
+ Units: 1,
232
+ Length: package.length(:in).round(2),
233
+ Width: package.width(:in).round(2),
234
+ Height: package.height(:in).round(2),
235
+ Type: 'IN' # inches
236
+ }
237
+ }
238
+ end
239
+ end
52
240
 
53
- super
54
- end
241
+ request = {
242
+ request: {
243
+ Application: 'ThirdParty',
244
+ BillingTerms: 'Prepaid',
245
+ OriginCity: shipment.origin.city,
246
+ OriginState: shipment.origin.province,
247
+ OriginZipcode: shipment.origin.postal_code.to_s.upcase,
248
+ DestinationCity: shipment.destination.city,
249
+ DestinationState: shipment.destination.province,
250
+ DestinationZipcode: shipment.destination.postal_code.to_s.upcase,
251
+ WeightUnits: 'LBS',
252
+ TotalCube: shipment.packages.sum { |p| p.cubic_ft(:each) }.round(2),
253
+ TotalCubeUnits: 'CUFT', # cubic ft
254
+ ExcessiveLengthTotalInches: longest_dimension.to_s,
255
+ Details: details,
256
+ Dimensions: dimensions,
257
+ Accessorials: accessorials
258
+ }
259
+ }
260
+
261
+ declared_value = if shipment.declared_value_cents.blank?
262
+ nil
263
+ else
264
+ (shipment.declared_value_cents.to_f / 100).ceil
265
+ end
266
+
267
+ if declared_value.present?
268
+ request = request.deep_merge(
269
+ { request: { DeclaredValue: declared_value, FullValueCoverage: declared_value } }
270
+ )
271
+ end
55
272
 
56
- protected
57
-
58
- def commit(action, request)
59
- client_args = {
60
- wsdl: request_url(action),
61
- convert_request_keys_to: :none,
62
- env_namespace: :soap,
63
- element_form_default: :qualified
64
- }
65
-
66
- call_args = { message: request_blueprint.deep_merge(request) }
67
-
68
- ::FreightKit::SoapClient.new(
69
- carrier: self,
70
- action:,
71
- client_args:,
72
- call_args:,
73
- soap_operation: @conf.dig(:api, :actions, action),
74
- ).call&.to_hash&.with_indifferent_access
75
- end
273
+ save_request(request)
274
+ request
275
+ end
76
276
 
77
- def request_blueprint
78
- api_credentials = fetch_credential(:api)
79
-
80
- {
81
- request: {
82
- AccountNumber: api_credentials.account,
83
- Application: 'ThirdParty',
84
- Password: api_credentials.password,
85
- TestMode: 'N',
86
- UserID: api_credentials.username
87
- }
88
- }
89
- end
277
+ def build_tracking_request(tracking_number)
278
+ request = { request: { ProNumber: tracking_number } }
279
+ save_request(request)
280
+ request
281
+ end
90
282
 
91
- def request_url(action)
92
- scheme = @conf.dig(:api, :use_ssl) ? 'https://' : 'http://'
93
- "#{scheme}#{@conf.dig(:api, :domain)}#{@conf.dig(:api, :endpoints, action)}"
94
- end
283
+ def commit(action, request)
284
+ client_args = {
285
+ wsdl: request_url(action),
286
+ convert_request_keys_to: :none,
287
+ env_namespace: :soap,
288
+ element_form_default: :qualified
289
+ }
95
290
 
96
- # Documents
291
+ call_args = { message: request_blueprint.deep_merge(request) }
97
292
 
98
- # Rates
99
- def build_rate_request(shipment:)
100
- accessorials = [{ AccessorialItem: { Code: 'SingleShipment' } }]
101
- if shipment.accessorials.present?
102
- serviceable_accessorials?(shipment.accessorials)
103
- shipment.accessorials.each do |a|
104
- if @conf.dig(:accessorials, :unserviceable).exclude?(a)
105
- accessorials << { AccessorialItem: { Code: @conf.dig(:accessorials, :mappable)[a] } }
106
- end
107
- end
293
+ ::FreightKit::SoapClient.new(
294
+ carrier: self,
295
+ action:,
296
+ client_args:,
297
+ call_args:,
298
+ soap_operation: API.dig(:actions, action)
299
+ ).call&.to_hash&.with_indifferent_access
108
300
  end
109
301
 
110
- longest_dimension = shipment.packages.map { |p| [p.width(:inches), p.length(:inches)].max }.max.ceil
111
- accessorials << { AccessorialItem: { Code: 'ExcessiveLength' } } if longest_dimension >= 96
112
-
113
- accessorials = accessorials.uniq
114
-
115
- details = []
116
- dimensions = []
117
- shipment.packages.each do |package|
118
- package.quantity.times do
119
- details << {
120
- DetailItem: {
121
- Weight: package.pounds(:each).ceil,
122
- Class: package.freight_class.to_s,
123
- Length: package.length(:in).ceil,
124
- Width: package.width(:in).ceil,
125
- Height: package.height(:in).ceil
126
- }
127
- }
128
-
129
- # Keeping this one at a time to match with "details"
130
- dimensions << {
131
- DimensionItem: {
132
- Units: 1,
133
- Length: package.length(:in).round(2),
134
- Width: package.width(:in).round(2),
135
- Height: package.height(:in).round(2),
136
- Type: 'IN' # inches
137
- }
138
- }
139
- end
302
+ def parse_api_date_time(date_time, location)
303
+ return if date_time.blank?
304
+
305
+ local_date_time = ::Time.strptime(date_time, '%Y-%m-%d %H:%M:%S').to_fs(:db)
306
+ ::FreightKit::DateTime.new(local_date_time:, location:)
140
307
  end
141
308
 
142
- request = {
143
- request: {
144
- Application: 'ThirdParty',
145
- BillingTerms: 'Prepaid',
146
- OriginCity: shipment.origin.city,
147
- OriginState: shipment.origin.province,
148
- OriginZipcode: shipment.origin.postal_code.to_s.upcase,
149
- DestinationCity: shipment.destination.city,
150
- DestinationState: shipment.destination.province,
151
- DestinationZipcode: shipment.destination.postal_code.to_s.upcase,
152
- WeightUnits: 'LBS',
153
- TotalCube: shipment.packages.sum { |p| p.cubic_ft(:each) }.round(2),
154
- TotalCubeUnits: 'CUFT', # cubic ft
155
- ExcessiveLengthTotalInches: longest_dimension.to_s,
156
- Details: details,
157
- Dimensions: dimensions,
158
- Accessorials: accessorials
159
- }
160
- }
161
-
162
- declared_value = if shipment.declared_value_cents.blank?
163
- nil
164
- else
165
- (shipment.declared_value_cents.to_f / 100).ceil
166
- end
167
-
168
- if declared_value.present?
169
- request = request.deep_merge(
170
- {
171
- request: {
172
- DeclaredValue: declared_value,
173
- FullValueCoverage: declared_value
174
- }
175
- },
309
+ def parse_api_location(api_event)
310
+ Location.new(
311
+ city: api_event[:city]&.titleize,
312
+ province: api_event[:state]&.upcase,
313
+ country: ActiveUtils::Country.find('USA')
176
314
  )
177
315
  end
178
316
 
179
- save_request(request)
180
- request
181
- end
317
+ def parse_rate_response(shipment:, response:)
318
+ rate_response = RateResponse.new(request: last_request, response:)
182
319
 
183
- def parse_rate_response(shipment:, response:)
184
- rate_response = RateResponse.new(request: last_request, response:)
320
+ if response.blank?
321
+ rate_response.error = ResponseError.new('Unknown response')
322
+ return rate_response
323
+ end
185
324
 
186
- if response.blank?
187
- rate_response.error = ResponseError.new('Unknown response')
188
- return rate_response
189
- end
325
+ error = response.dig(:create_response, :create_result, :code)
326
+
327
+ if error.present?
328
+ message = response.dig(:create_response, :create_result, :message)
190
329
 
191
- error = response.dig(:create_response, :create_result, :code)
330
+ case error
331
+ when 'DNF'
332
+ rate_response.error = UnserviceableError.new("#{error}: #{message}")
333
+ return rate_response
334
+ when 'S10'
335
+ rate_response.error = UnserviceableError.new("#{error}: #{message}")
336
+ return rate_response
337
+ end
192
338
 
193
- if error.present?
194
- message = response.dig(:create_response, :create_result, :message)
339
+ if message.downcase.include?('must not exceed 10 lines')
340
+ rate_response.error = UnserviceableError.new("#{error}: #{message}")
341
+ return rate_response
342
+ end
195
343
 
196
- case error
197
- when 'DNF'
198
- rate_response.error = UnserviceableError.new("#{error}: #{message}")
199
- return rate_response
200
- when 'S10'
201
- rate_response.error = UnserviceableError.new("#{error}: #{message}")
344
+ rate_response.error = ResponseError.new("#{error}: #{message}")
202
345
  return rate_response
203
346
  end
204
347
 
205
- if message.downcase.include?('must not exceed 10 lines')
206
- rate_response.error = UnserviceableError.new("#{error}: #{message}")
348
+ result = response.dig(:create_response, :create_result)
349
+
350
+ if result.blank?
351
+ rate_response.error = ResponseError.new('Unknown result')
207
352
  return rate_response
208
353
  end
209
354
 
210
- rate_response.error = ResponseError.new("#{error}: #{message}")
211
- return rate_response
212
- end
213
-
214
- result = response.dig(:create_response, :create_result)
215
-
216
- if result.blank?
217
- rate_response.error = ResponseError.new('Unknown result')
218
- return rate_response
219
- end
220
-
221
- if result[:total_invoice].blank?
222
- rate_response.error = ResponseError.new('Cost is blank')
223
- return rate_response
224
- end
355
+ if result[:total_invoice].blank?
356
+ rate_response.error = ResponseError.new('Cost is blank')
357
+ return rate_response
358
+ end
225
359
 
226
- transit_days = result[:standard_service_days].to_i
227
- estimate_reference = result[:quote_number]
360
+ transit_days = result[:standard_service_days].to_i
361
+ estimate_reference = result[:quote_number]
228
362
 
229
- rate_accessorial_items = result.dig(:rate_accessorials, :rate_accessorial_item)
230
- rate_accessorial_items = [rate_accessorial_items] if rate_accessorial_items.is_a?(Hash)
363
+ rate_accessorial_items = result.dig(:rate_accessorials, :rate_accessorial_item)
364
+ rate_accessorial_items = [rate_accessorial_items] if rate_accessorial_items.is_a?(Hash)
231
365
 
232
- prices = []
366
+ prices = rate_accessorial_items.map do |rate_accessorial_item|
367
+ Price.new(
368
+ blame: :api,
369
+ cents: (rate_accessorial_item[:amount].to_f * 100).to_i,
370
+ description: rate_accessorial_item[:description]&.titleize&.squish
371
+ )
372
+ end
233
373
 
234
- rate_accessorial_items.each do |rate_accessorial_item|
235
- prices << Price.new(
236
- blame: :api,
237
- cents: (rate_accessorial_item[:amount].to_f * 100).to_i,
238
- description: rate_accessorial_item[:description]&.titleize&.squish,
239
- )
240
- end
374
+ standard_ltl_cents = (result[:total_invoice].to_f * 100).to_i - prices.sum(&:cents)
241
375
 
242
- standard_ltl_cents = (result[:total_invoice].to_f * 100).to_i - prices.sum(&:cents)
243
-
244
- rates = []
245
-
246
- rates << Rate.new(
247
- carrier: self,
248
- carrier_name: self.class.name,
249
- currency: 'USD',
250
- estimate_reference:,
251
- scac: self.class.scac.upcase,
252
- service_name: :standard,
253
- shipment:,
254
- prices: [
255
- Price.new(
256
- blame: :api,
257
- cents: standard_ltl_cents,
258
- description: 'Freight',
259
- ),
260
- ] + prices,
261
- transit_days:,
262
- with_excessive_length_fees: @conf.dig(:attributes, :rates, :with_excessive_length_fees),
263
- )
264
-
265
- [
266
- { guaranteed_ltl: result[:guarantee_amount] },
267
- { guaranteed_ltl_am: result[:guarantee_amount12pm] },
268
- { guaranteed_ltl_pm: result[:guarantee_amount2pm] },
269
- ].each do |service|
270
- next if service.values[0] == '0' || service.values[0].blank?
271
-
272
- cents = (service.values[0].to_f * 100).to_i
376
+ rates = []
273
377
 
274
378
  rates << Rate.new(
275
- carrier_name: self.class.name,
276
379
  carrier: self,
380
+ carrier_name: name,
277
381
  currency: 'USD',
278
382
  estimate_reference:,
279
- scac: self.class.scac.upcase,
280
- service_name: service.keys[0],
383
+ scac:,
384
+ service_name: :standard,
281
385
  shipment:,
282
- prices: [
283
- Price.new(
284
- blame: :api,
285
- cents: standard_ltl_cents + cents,
286
- description: 'Freight',
287
- ),
288
- ] + prices,
289
- with_excessive_length_fees: @conf.dig(:attributes, :rates, :with_excessive_length_fees),
386
+ prices: [Price.new(blame: :api, cents: standard_ltl_cents, description: 'Freight')] + prices,
387
+ transit_days:,
388
+ with_excessive_length_fees: rates_with_excessive_length_fees?
290
389
  )
390
+
391
+ [
392
+ { guaranteed_ltl: result[:guarantee_amount] },
393
+ { guaranteed_ltl_am: result[:guarantee_amount12pm] },
394
+ { guaranteed_ltl_pm: result[:guarantee_amount2pm] }
395
+ ].each do |service|
396
+ next if service.values[0] == '0' || service.values[0].blank?
397
+
398
+ cents = (service.values[0].to_f * 100).to_i
399
+
400
+ rates << Rate.new(
401
+ carrier_name: name,
402
+ carrier: self,
403
+ currency: 'USD',
404
+ estimate_reference:,
405
+ scac:,
406
+ service_name: service.keys[0],
407
+ shipment:,
408
+ prices: [Price.new(blame: :api, cents: standard_ltl_cents + cents, description: 'Freight')] + prices,
409
+ with_excessive_length_fees: rates_with_excessive_length_fees?
410
+ )
411
+ end
412
+
413
+ rate_response.rates = rates
414
+ rate_response
291
415
  end
292
416
 
293
- rate_response.rates = rates
294
- rate_response
295
- end
417
+ def parse_tracking_response(response)
418
+ tracking_response = TrackingResponse.new(carrier: self, request: last_request, response:)
296
419
 
297
- # Tracking
420
+ error = if response
421
+ response.dig(:get_by_pro_number_response, :get_by_pro_number_result, :code)
422
+ else
423
+ 'API Error: Unknown response'
424
+ end
298
425
 
299
- def build_tracking_request(tracking_number)
300
- request = {
301
- request: {
302
- ProNumber: tracking_number
303
- }
304
- }
305
- save_request(request)
306
- request
307
- end
426
+ if error.present?
427
+ tracking_response.error = ResponseError.new(error)
428
+ return tracking_response
429
+ end
308
430
 
309
- def parse_api_date_time(date_time, location)
310
- return if date_time.blank?
431
+ search_result = response.dig(:get_by_pro_number_response, :get_by_pro_number_result)
311
432
 
312
- local_date_time = ::Time.strptime(date_time, '%Y-%m-%d %H:%M:%S').to_fs(:db)
313
- ::FreightKit::DateTime.new(local_date_time:, location:)
314
- end
433
+ if search_result.blank?
434
+ tracking_response.error = ShipmentNotFoundError.new
435
+ return tracking_response
436
+ end
315
437
 
316
- def parse_api_location(api_event)
317
- Location.new(
318
- city: api_event[:city]&.titleize,
319
- province: api_event[:state]&.upcase,
320
- country: ActiveUtils::Country.find('USA'),
321
- )
322
- end
438
+ address1 = [search_result.dig(:shipper, :address1), search_result.dig(:shipper, :address2)]
439
+ .select(&:present?)
440
+ .map { |line| line.squish.strip.titleize }
441
+ .join(', ')
442
+
443
+ shipper_location = Location.new(
444
+ address1:,
445
+ city: search_result.dig(:shipper, :city)&.squish&.titleize,
446
+ province: search_result.dig(:shipper, :state)&.strip&.upcase,
447
+ postal_code: search_result.dig(:shipper, :zipcode)&.strip,
448
+ country: ActiveUtils::Country.find('USA')
449
+ )
450
+
451
+ address1 = [search_result.dig(:consignee, :address1), search_result.dig(:consignee, :address2)]
452
+ .select(&:present?)
453
+ .map { |line| line.squish.strip.titleize }
454
+ .join(', ')
455
+
456
+ receiver_location = Location.new(
457
+ address1:,
458
+ city: search_result.dig(:consignee, :city)&.squish&.titleize,
459
+ province: search_result.dig(:consignee, :state)&.strip&.upcase,
460
+ postal_code: search_result.dig(:consignee, :zipcode)&.strip,
461
+ country: ActiveUtils::Country.find('USA')
462
+ )
323
463
 
324
- def parse_tracking_response(response)
325
- tracking_response = TrackingResponse.new(carrier: self, request: last_request, response:)
464
+ api_date_time = search_result[:delivery_date_time_arrive]
465
+ actual_delivery_date = parse_api_date_time(api_date_time, receiver_location)
326
466
 
327
- error = if response
328
- response.dig(:get_by_pro_number_response, :get_by_pro_number_result, :code)
329
- else
330
- 'API Error: Unknown response'
331
- end
467
+ api_date_time = search_result[:pickup_date_time]
468
+ pickup_date = parse_api_date_time(api_date_time, shipper_location)
332
469
 
333
- if error.present?
334
- tracking_response.error = ResponseError.new(error)
335
- return tracking_response
336
- end
470
+ api_date_time = search_result[:delivery_appointment_date_time]
471
+ scheduled_delivery_date = parse_api_date_time(api_date_time, receiver_location)
337
472
 
338
- search_result = response.dig(:get_by_pro_number_response, :get_by_pro_number_result)
473
+ tracking_number = search_result[:pro_number]
339
474
 
340
- if search_result.blank?
341
- tracking_response.error = ShipmentNotFoundError.new
342
- return tracking_response
343
- end
475
+ shipment_events = []
344
476
 
345
- address1 = [
346
- search_result.dig(:shipper, :address1),
347
- search_result.dig(:shipper, :address2),
348
- ]
349
- .select(&:present?)
350
- .map { |line| line.squish.strip.titleize }
351
- .join(', ')
352
-
353
- shipper_location = Location.new(
354
- address1:,
355
- city: search_result.dig(:shipper, :city)&.squish&.strip&.titleize,
356
- province: search_result.dig(:shipper, :state)&.strip&.upcase,
357
- postal_code: search_result.dig(:shipper, :zipcode)&.strip,
358
- country: ActiveUtils::Country.find('USA'),
359
- )
360
-
361
- address1 = [
362
- search_result.dig(:consignee, :address1),
363
- search_result.dig(:consignee, :address2),
364
- ]
365
- .select(&:present?)
366
- .map { |line| line.squish.strip.titleize }
367
- .join(', ')
368
-
369
- receiver_location = Location.new(
370
- address1:,
371
- city: search_result.dig(:consignee, :city)&.squish&.strip&.titleize,
372
- province: search_result.dig(:consignee, :state)&.strip&.upcase,
373
- postal_code: search_result.dig(:consignee, :zipcode)&.strip,
374
- country: ActiveUtils::Country.find('USA'),
375
- )
376
-
377
- api_date_time = search_result[:delivery_date_time_arrive]
378
- actual_delivery_date = parse_api_date_time(api_date_time, receiver_location)
379
-
380
- api_date_time = search_result[:pickup_date_time]
381
- pickup_date = parse_api_date_time(api_date_time, shipper_location)
382
-
383
- api_date_time = search_result[:delivery_appointment_date_time]
384
- scheduled_delivery_date = parse_api_date_time(api_date_time, receiver_location)
385
-
386
- tracking_number = search_result[:pro_number]
387
-
388
- shipment_events = []
389
-
390
- api_events = search_result.dig(:history, :history_item)
391
-
392
- if api_events.blank?
393
- shipment_events << ShipmentEvent.new(
394
- date_time: pickup_date,
395
- location: shipper_location,
396
- type_code: :picked_up,
397
- )
398
- else
399
- api_events = [api_events] if api_events.is_a?(Hash)
477
+ api_events = search_result.dig(:history, :history_item)
400
478
 
401
- api_events.each do |api_event|
402
- event_key = nil
403
- comment = api_event[:activity]
479
+ if api_events.blank?
480
+ shipment_events << ShipmentEvent.new(
481
+ date_time: pickup_date,
482
+ location: shipper_location,
483
+ type_code: :picked_up
484
+ )
485
+ else
486
+ api_events = [api_events] if api_events.is_a?(Hash)
404
487
 
405
- @conf.dig(:events, :types).each do |key, val|
406
- if comment.downcase.include?(val)
407
- event_key = key
408
- break
488
+ api_events.each do |api_event|
489
+ event_key = nil
490
+ comment = api_event[:activity]
491
+
492
+ EVENTS[:types].each do |key, val|
493
+ if comment.downcase.include?(val)
494
+ event_key = key
495
+ break
496
+ end
409
497
  end
410
- end
411
- next if event_key.blank?
498
+ next if event_key.blank?
412
499
 
413
- api_date_time = api_event[:activity_date_time]
500
+ api_date_time = api_event[:activity_date_time]
414
501
 
415
- location = parse_api_location(api_event)
416
- date_time = parse_api_date_time(api_date_time, location)
502
+ location = parse_api_location(api_event)
503
+ date_time = parse_api_date_time(api_date_time, location)
417
504
 
418
- shipment_events << ShipmentEvent.new(date_time:, location:, type_code: event_key)
505
+ shipment_events << ShipmentEvent.new(date_time:, location:, type_code: event_key)
506
+ end
419
507
  end
420
- end
421
508
 
422
- status = shipment_events.last&.type_code
509
+ status = shipment_events.last&.type_code
510
+
511
+ tracking_response.assign_attributes(
512
+ actual_delivery_date:,
513
+ destination: receiver_location,
514
+ origin: shipper_location,
515
+ scheduled_delivery_date:,
516
+ ship_time: pickup_date,
517
+ shipment_events:,
518
+ status:,
519
+ tracking_number:
520
+ )
423
521
 
424
- tracking_response.assign_attributes(
425
- actual_delivery_date:,
426
- destination: receiver_location,
427
- origin: shipper_location,
428
- scheduled_delivery_date:,
429
- ship_time: pickup_date,
430
- shipment_events:,
431
- status:,
432
- tracking_number:,
433
- )
522
+ tracking_response
523
+ end
434
524
 
435
- tracking_response
525
+ def request_blueprint
526
+ api_credentials = fetch_credential(:api)
527
+
528
+ {
529
+ request: {
530
+ AccountNumber: api_credentials.account,
531
+ Application: 'ThirdParty',
532
+ Password: api_credentials.password,
533
+ TestMode: 'N',
534
+ UserID: api_credentials.username
535
+ }
536
+ }
537
+ end
538
+
539
+ def request_url(action)
540
+ scheme = API[:use_ssl] ? 'https://' : 'http://'
541
+ "#{scheme}#{API[:domain]}#{API.dig(:endpoints, action)}"
542
+ end
436
543
  end
437
544
  end
438
545
  end