freight_kit 0.1.20 → 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 (434) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/README.md +1 -2
  4. data/Rakefile +6 -0
  5. data/VERSION +1 -1
  6. data/configuration/locations/amazon_warehouses.yml +3330 -0
  7. data/freight_kit.gemspec +13 -13
  8. data/lib/freight_kit/address_normalizer.rb +26 -0
  9. data/lib/freight_kit/amazon_warehouse.rb +33 -0
  10. data/lib/freight_kit/api_clients/soap_client.rb +7 -9
  11. data/lib/freight_kit/carrier.rb +250 -303
  12. data/lib/freight_kit/carriers/a1_express.rb +25 -0
  13. data/lib/freight_kit/carriers/a_duie_pyle.rb +30 -0
  14. data/lib/freight_kit/carriers/aaa_cooper.rb +11 -0
  15. data/lib/freight_kit/carriers/aaa_expedited_services.rb +10 -0
  16. data/lib/freight_kit/carriers/ab_brothers_usa_inc.rb +12 -0
  17. data/lib/freight_kit/carriers/aberdeen_express_inc.rb +28 -0
  18. data/lib/freight_kit/carriers/abf_freight_system.rb +492 -0
  19. data/lib/freight_kit/carriers/access_transport.rb +10 -0
  20. data/lib/freight_kit/carriers/action_express.rb +10 -0
  21. data/lib/freight_kit/carriers/adams_and_companies.rb +10 -0
  22. data/lib/freight_kit/carriers/advance_distribution.rb +28 -0
  23. data/lib/freight_kit/carriers/alcon_transport.rb +10 -0
  24. data/lib/freight_kit/carriers/all_freight.rb +10 -0
  25. data/lib/freight_kit/carriers/alliance_transportation_group.rb +10 -0
  26. data/lib/freight_kit/carriers/allstate_transport.rb +10 -0
  27. data/lib/freight_kit/carriers/aloha_freight_forwarders.rb +35 -0
  28. data/lib/freight_kit/carriers/amado_trucking.rb +35 -0
  29. data/lib/freight_kit/carriers/american_fast_freight.rb +28 -0
  30. data/lib/freight_kit/carriers/amigos_service_transportation.rb +10 -0
  31. data/lib/freight_kit/carriers/anderson_towing_and_transport.rb +10 -0
  32. data/lib/freight_kit/carriers/apex_transporting.rb +10 -0
  33. data/lib/freight_kit/carriers/archer_cargo.rb +35 -0
  34. data/lib/freight_kit/carriers/armstrong_transport_group.rb +10 -0
  35. data/lib/freight_kit/carriers/autobahn_logistics.rb +10 -0
  36. data/lib/freight_kit/carriers/averitt_express.rb +30 -0
  37. data/lib/freight_kit/carriers/ba_transportation.rb +10 -0
  38. data/lib/freight_kit/carriers/balkin_express.rb +10 -0
  39. data/lib/freight_kit/carriers/bay_area_express.rb +10 -0
  40. data/lib/freight_kit/carriers/bc_freightways.rb +11 -0
  41. data/lib/freight_kit/carriers/benjamin_best_freight_inc.rb +37 -0
  42. data/lib/freight_kit/carriers/bennett_trucking.rb +10 -0
  43. data/lib/freight_kit/carriers/best_overnite_express.rb +78 -0
  44. data/lib/freight_kit/carriers/best_trucking.rb +10 -0
  45. data/lib/freight_kit/carriers/bestway_transport.rb +10 -0
  46. data/lib/freight_kit/carriers/bryan_systems.rb +10 -0
  47. data/lib/freight_kit/carriers/c_and_w_express.rb +10 -0
  48. data/lib/freight_kit/carriers/campbell_trucking.rb +10 -0
  49. data/lib/freight_kit/carriers/carde_transportation.rb +10 -0
  50. data/lib/freight_kit/carriers/cardinal_logistics.rb +28 -0
  51. data/lib/freight_kit/carriers/cdc_transport.rb +10 -0
  52. data/lib/freight_kit/carriers/cdo_express_diversified.rb +10 -0
  53. data/lib/freight_kit/carriers/cedar_supply_trucking.rb +10 -0
  54. data/lib/freight_kit/carriers/central_freight_lines.rb +12 -0
  55. data/lib/freight_kit/carriers/central_transport.rb +12 -0
  56. data/lib/freight_kit/carriers/chicago_suburban_express.rb +28 -0
  57. data/lib/freight_kit/carriers/city_logistics.rb +11 -0
  58. data/lib/freight_kit/carriers/clear_lane_freight_systems.rb +483 -0
  59. data/lib/freight_kit/carriers/cleopatra_trucking.rb +10 -0
  60. data/lib/freight_kit/carriers/clifford_transportation.rb +10 -0
  61. data/lib/freight_kit/carriers/cms_domestic.rb +25 -0
  62. data/lib/freight_kit/carriers/cnd_logistics.rb +10 -0
  63. data/lib/freight_kit/carriers/coast_to_coast_transport.rb +27 -0
  64. data/lib/freight_kit/carriers/countrywide_carriers.rb +10 -0
  65. data/lib/freight_kit/carriers/cpl_express.rb +35 -0
  66. data/lib/freight_kit/carriers/crosby_trucking_service.rb +29 -0
  67. data/lib/freight_kit/carriers/cross_country_freight_solutions.rb +419 -0
  68. data/lib/freight_kit/carriers/crowley.rb +10 -0
  69. data/lib/freight_kit/carriers/csa_transportation.rb +40 -0
  70. data/lib/freight_kit/carriers/csx_transportation.rb +40 -0
  71. data/lib/freight_kit/carriers/custom_global_logistics.rb +14 -0
  72. data/lib/freight_kit/carriers/d_and_a_transport.rb +10 -0
  73. data/lib/freight_kit/carriers/dak_transport.rb +10 -0
  74. data/lib/freight_kit/carriers/dash_courier_and_logistics_north_carolina.rb +10 -0
  75. data/lib/freight_kit/carriers/daylight_transport.rb +29 -0
  76. data/lib/freight_kit/carriers/dayton_freight_lines.rb +30 -0
  77. data/lib/freight_kit/carriers/dbr_logistics.rb +10 -0
  78. data/lib/freight_kit/carriers/deep_south_freight.rb +27 -0
  79. data/lib/freight_kit/carriers/delta_express.rb +10 -0
  80. data/lib/freight_kit/carriers/delta_transport.rb +10 -0
  81. data/lib/freight_kit/carriers/delta_trucking_logistics.rb +10 -0
  82. data/lib/freight_kit/carriers/demco_express.rb +10 -0
  83. data/lib/freight_kit/carriers/dependable_global_express.rb +10 -0
  84. data/lib/freight_kit/carriers/dependable_hawaiian_express.rb +24 -0
  85. data/lib/freight_kit/carriers/dependable_highway_express.rb +585 -0
  86. data/lib/freight_kit/carriers/desert_coastal_transport.rb +10 -0
  87. data/lib/freight_kit/carriers/dhl.rb +11 -0
  88. data/lib/freight_kit/carriers/diamond_line_delivery.rb +174 -0
  89. data/lib/freight_kit/carriers/ding_tai_trucking.rb +10 -0
  90. data/lib/freight_kit/carriers/diversified_transfer_and_storage.rb +29 -0
  91. data/lib/freight_kit/carriers/dohrn_transfer_company.rb +30 -0
  92. data/lib/freight_kit/carriers/dot_line_transportation.rb +29 -0
  93. data/lib/freight_kit/carriers/drt_transportation.rb +13 -0
  94. data/lib/freight_kit/carriers/dugan_truck_line.rb +29 -0
  95. data/lib/freight_kit/carriers/dupont.rb +10 -0
  96. data/lib/freight_kit/carriers/e_transport_carriers.rb +29 -0
  97. data/lib/freight_kit/carriers/echo_global_logistics.rb +13 -0
  98. data/lib/freight_kit/carriers/ecklund_logistics.rb +10 -0
  99. data/lib/freight_kit/carriers/el_emplumado_transport.rb +10 -0
  100. data/lib/freight_kit/carriers/elite_carriers.rb +28 -0
  101. data/lib/freight_kit/carriers/emerald_express.rb +10 -0
  102. data/lib/freight_kit/carriers/era_transport.rb +10 -0
  103. data/lib/freight_kit/carriers/estes_express_lines.rb +25 -0
  104. data/lib/freight_kit/carriers/euro_kam.rb +28 -0
  105. data/lib/freight_kit/carriers/ew_riverside_trucking.rb +10 -0
  106. data/lib/freight_kit/carriers/express_2000_inc.rb +12 -0
  107. data/lib/freight_kit/carriers/express_services_international.rb +10 -0
  108. data/lib/freight_kit/carriers/f_and_a_express.rb +27 -0
  109. data/lib/freight_kit/carriers/fairmont_logistics.rb +13 -0
  110. data/lib/freight_kit/carriers/fargo_cargo.rb +10 -0
  111. data/lib/freight_kit/carriers/fast_freight_transportation.rb +10 -0
  112. data/lib/freight_kit/carriers/fast_load_transport.rb +10 -0
  113. data/lib/freight_kit/carriers/fed_ex_express.rb +30 -0
  114. data/lib/freight_kit/carriers/fed_ex_ground.rb +24 -0
  115. data/lib/freight_kit/carriers/fed_ex_ltl_economy.rb +11 -0
  116. data/lib/freight_kit/carriers/fed_ex_ltl_priority.rb +11 -0
  117. data/lib/freight_kit/carriers/first_trucking_express.rb +10 -0
  118. data/lib/freight_kit/carriers/flash_trucking.rb +10 -0
  119. data/lib/freight_kit/carriers/fort_transportation_and_service_company_inc.rb +37 -0
  120. data/lib/freight_kit/carriers/forward_air.rb +789 -0
  121. data/lib/freight_kit/carriers/frahtex.rb +10 -0
  122. data/lib/freight_kit/carriers/frozen_food_express.rb +10 -0
  123. data/lib/freight_kit/carriers/gholia_bros_trucking.rb +36 -0
  124. data/lib/freight_kit/carriers/global_cargo.rb +10 -0
  125. data/lib/freight_kit/carriers/global_logistics_and_transportation.rb +10 -0
  126. data/lib/freight_kit/carriers/gls_freight.rb +32 -0
  127. data/lib/freight_kit/carriers/go_trucking_services.rb +10 -0
  128. data/lib/freight_kit/carriers/gold_eagle_transportation.rb +11 -0
  129. data/lib/freight_kit/carriers/golden_drop_trucking.rb +10 -0
  130. data/lib/freight_kit/carriers/gonzalez_transportation.rb +10 -0
  131. data/lib/freight_kit/carriers/gps_transport.rb +10 -0
  132. data/lib/freight_kit/carriers/greene_enterprise.rb +10 -0
  133. data/lib/freight_kit/carriers/gsa_international.rb +10 -0
  134. data/lib/freight_kit/carriers/gsp_express.rb +24 -0
  135. data/lib/freight_kit/carriers/gsv_transportation.rb +10 -0
  136. data/lib/freight_kit/carriers/gta_transportation.rb +10 -0
  137. data/lib/freight_kit/carriers/guam_freight_services.rb +10 -0
  138. data/lib/freight_kit/carriers/harrah_transportation.rb +23 -0
  139. data/lib/freight_kit/carriers/her_trucking.rb +10 -0
  140. data/lib/freight_kit/carriers/hercules_freight.rb +20 -0
  141. data/lib/freight_kit/carriers/highlander_xpress.rb +36 -0
  142. data/lib/freight_kit/carriers/hn_transport.rb +10 -0
  143. data/lib/freight_kit/carriers/honolulu_freight_service.rb +10 -0
  144. data/lib/freight_kit/carriers/hot_line_freight_system_inc.rb +12 -0
  145. data/lib/freight_kit/carriers/hotshot_freight_of_texas.rb +13 -0
  146. data/lib/freight_kit/carriers/houser_transport.rb +27 -0
  147. data/lib/freight_kit/carriers/infiniti_freight_logistics.rb +28 -0
  148. data/lib/freight_kit/carriers/infinity_trucking.rb +10 -0
  149. data/lib/freight_kit/carriers/interstate_tma.rb +10 -0
  150. data/lib/freight_kit/carriers/intrade_industries.rb +10 -0
  151. data/lib/freight_kit/carriers/jasper_trucking.rb +28 -0
  152. data/lib/freight_kit/carriers/jb_hunt.rb +11 -0
  153. data/lib/freight_kit/carriers/jfj_transportation.rb +8 -8
  154. data/lib/freight_kit/carriers/jkb_express.rb +10 -0
  155. data/lib/freight_kit/carriers/jlm_transport.rb +10 -0
  156. data/lib/freight_kit/carriers/johansson_transport.rb +10 -0
  157. data/lib/freight_kit/carriers/jones_express.rb +10 -0
  158. data/lib/freight_kit/carriers/jp_logistics.rb +41 -0
  159. data/lib/freight_kit/carriers/just_in_time_cargo.rb +29 -0
  160. data/lib/freight_kit/carriers/kengkok_times.rb +10 -0
  161. data/lib/freight_kit/carriers/kings_express.rb +10 -0
  162. data/lib/freight_kit/carriers/klc_transportation.rb +10 -0
  163. data/lib/freight_kit/carriers/km_trucking.rb +10 -0
  164. data/lib/freight_kit/carriers/kma_logistics.rb +10 -0
  165. data/lib/freight_kit/carriers/krc_logistics.rb +10 -0
  166. data/lib/freight_kit/carriers/ktx.rb +10 -0
  167. data/lib/freight_kit/carriers/landstar.rb +25 -0
  168. data/lib/freight_kit/carriers/lanter_distributing_llc.rb +30 -0
  169. data/lib/freight_kit/carriers/ld_trucking.rb +10 -0
  170. data/lib/freight_kit/carriers/legacy_logistics_solutions.rb +10 -0
  171. data/lib/freight_kit/carriers/leonards_express.rb +10 -0
  172. data/lib/freight_kit/carriers/liberty_linehaul_west.rb +28 -0
  173. data/lib/freight_kit/carriers/liberty_transport.rb +10 -0
  174. data/lib/freight_kit/carriers/lightning_express.rb +10 -0
  175. data/lib/freight_kit/carriers/lj_express.rb +24 -0
  176. data/lib/freight_kit/carriers/lkp_enterprises.rb +10 -0
  177. data/lib/freight_kit/carriers/ltl_pros.rb +28 -0
  178. data/lib/freight_kit/carriers/m_and_m_and_sons.rb +10 -0
  179. data/lib/freight_kit/carriers/mag_lines_transport.rb +10 -0
  180. data/lib/freight_kit/carriers/magic_messenger.rb +24 -0
  181. data/lib/freight_kit/carriers/majors_transit.rb +10 -0
  182. data/lib/freight_kit/carriers/map_global_logistics.rb +10 -0
  183. data/lib/freight_kit/carriers/matths_trucking.rb +11 -0
  184. data/lib/freight_kit/carriers/mav_canadian_transport.rb +13 -0
  185. data/lib/freight_kit/carriers/mc_systems.rb +35 -0
  186. data/lib/freight_kit/carriers/mega_fleet.rb +10 -0
  187. data/lib/freight_kit/carriers/mega_trans_group.rb +28 -0
  188. data/lib/freight_kit/carriers/meta_express.rb +10 -0
  189. data/lib/freight_kit/carriers/mia_transportation.rb +10 -0
  190. data/lib/freight_kit/carriers/midwest_motor_express.rb +14 -0
  191. data/lib/freight_kit/carriers/midwest_transport_and_trucking.rb +10 -0
  192. data/lib/freight_kit/carriers/mikade_delivery_service.rb +10 -0
  193. data/lib/freight_kit/carriers/mohoff_freight_lines.rb +23 -0
  194. data/lib/freight_kit/carriers/montata_travelers_express.rb +10 -0
  195. data/lib/freight_kit/carriers/morgan_van_lines.rb +29 -0
  196. data/lib/freight_kit/carriers/moto_transportation.rb +24 -0
  197. data/lib/freight_kit/carriers/mountain_valley_express.rb +197 -0
  198. data/lib/freight_kit/carriers/ms_freight.rb +27 -0
  199. data/lib/freight_kit/carriers/mvg_transport.rb +10 -0
  200. data/lib/freight_kit/carriers/n_and_m_transfer_co_inc.rb +29 -0
  201. data/lib/freight_kit/carriers/nabot_transport_solutions.rb +10 -0
  202. data/lib/freight_kit/carriers/national_freight_xpress.rb +10 -0
  203. data/lib/freight_kit/carriers/navigation_group.rb +10 -0
  204. data/lib/freight_kit/carriers/nelson_trucking.rb +10 -0
  205. data/lib/freight_kit/carriers/network_1_transportation.rb +10 -0
  206. data/lib/freight_kit/carriers/new_century_transport.rb +28 -0
  207. data/lib/freight_kit/carriers/new_penn_motor_express.rb +11 -0
  208. data/lib/freight_kit/carriers/nieves_transportation.rb +10 -0
  209. data/lib/freight_kit/carriers/nolan_transportation_group.rb +26 -0
  210. data/lib/freight_kit/carriers/northland_trucking.rb +10 -0
  211. data/lib/freight_kit/carriers/northwest_carrier_logistics.rb +27 -0
  212. data/lib/freight_kit/carriers/nt_usa.rb +10 -0
  213. data/lib/freight_kit/carriers/nu_line_transportation.rb +10 -0
  214. data/lib/freight_kit/carriers/numark_transportation.rb +80 -0
  215. data/lib/freight_kit/carriers/nvk_transport.rb +10 -0
  216. data/lib/freight_kit/carriers/ny_transport.rb +10 -0
  217. data/lib/freight_kit/carriers/oak_harbor.rb +28 -0
  218. data/lib/freight_kit/carriers/oakline_transportation.rb +10 -0
  219. data/lib/freight_kit/carriers/old_dominion_freight_line.rb +30 -0
  220. data/lib/freight_kit/carriers/on_trac.rb +573 -0
  221. data/lib/freight_kit/carriers/one_hundred_one_transport.rb +10 -0
  222. data/lib/freight_kit/carriers/one_way_delivery.rb +10 -0
  223. data/lib/freight_kit/carriers/oracle_transportation_solutions.rb +10 -0
  224. data/lib/freight_kit/carriers/orange_courier.rb +27 -0
  225. data/lib/freight_kit/carriers/ortas_trucking.rb +10 -0
  226. data/lib/freight_kit/carriers/pac_trux_transportation.rb +10 -0
  227. data/lib/freight_kit/carriers/pacer.rb +10 -0
  228. data/lib/freight_kit/carriers/pacific_logistics.rb +10 -0
  229. data/lib/freight_kit/carriers/pacific_states_truck_lines.rb +10 -0
  230. data/lib/freight_kit/carriers/paradise_distributing.rb +10 -0
  231. data/lib/freight_kit/carriers/paramount_freight_systems.rb +10 -0
  232. data/lib/freight_kit/carriers/peninsula_truck_lines.rb +222 -0
  233. data/lib/freight_kit/carriers/pg_transport.rb +10 -0
  234. data/lib/freight_kit/carriers/pgs_360.rb +10 -0
  235. data/lib/freight_kit/carriers/pilot_freight_services.rb +10 -0
  236. data/lib/freight_kit/carriers/pious_trans.rb +27 -0
  237. data/lib/freight_kit/carriers/pitt_ohio_express.rb +30 -0
  238. data/lib/freight_kit/carriers/pki_logistics.rb +12 -0
  239. data/lib/freight_kit/carriers/plana_transportation.rb +28 -0
  240. data/lib/freight_kit/carriers/prestige.rb +10 -0
  241. data/lib/freight_kit/carriers/pro_trans_solutions.rb +28 -0
  242. data/lib/freight_kit/carriers/puma_logistics.rb +10 -0
  243. data/lib/freight_kit/carriers/pwc_international.rb +10 -0
  244. data/lib/freight_kit/carriers/quality_logistics.rb +10 -0
  245. data/lib/freight_kit/carriers/queen_star_trucking.rb +27 -0
  246. data/lib/freight_kit/carriers/r_and_l_carriers.rb +11 -0
  247. data/lib/freight_kit/carriers/rac_transport.rb +10 -0
  248. data/lib/freight_kit/carriers/re_logistics.rb +23 -0
  249. data/lib/freight_kit/carriers/reddaway.rb +11 -0
  250. data/lib/freight_kit/carriers/reefer_van_network.rb +13 -0
  251. data/lib/freight_kit/carriers/refrigerated_trucking_and_ltl_transportation_services.rb +10 -0
  252. data/lib/freight_kit/carriers/ridgeline_express.rb +10 -0
  253. data/lib/freight_kit/carriers/rist_transport.rb +29 -0
  254. data/lib/freight_kit/carriers/river_city_transport.rb +10 -0
  255. data/lib/freight_kit/carriers/roadrunner_transportation_services.rb +675 -0
  256. data/lib/freight_kit/carriers/roadtex.rb +13 -0
  257. data/lib/freight_kit/carriers/ronald_transport_services.rb +10 -0
  258. data/lib/freight_kit/carriers/rose_trucking.rb +24 -0
  259. data/lib/freight_kit/carriers/rp_and_j_transport.rb +24 -0
  260. data/lib/freight_kit/carriers/rpm_transportation.rb +11 -0
  261. data/lib/freight_kit/carriers/rude_transportation.rb +30 -0
  262. data/lib/freight_kit/carriers/s_and_s_logistics.rb +10 -0
  263. data/lib/freight_kit/carriers/saia.rb +470 -361
  264. data/lib/freight_kit/carriers/sb_transportation.rb +27 -0
  265. data/lib/freight_kit/carriers/schneider_national.rb +29 -0
  266. data/lib/freight_kit/carriers/schwarz_trucking.rb +10 -0
  267. data/lib/freight_kit/carriers/sewell_motor_express.rb +29 -0
  268. data/lib/freight_kit/carriers/shawnee_trucking.rb +28 -0
  269. data/lib/freight_kit/carriers/shi_logistics.rb +10 -0
  270. data/lib/freight_kit/carriers/sinbad_transport.rb +10 -0
  271. data/lib/freight_kit/carriers/skyway.rb +10 -0
  272. data/lib/freight_kit/carriers/smith_cargo_transportation_services.rb +23 -0
  273. data/lib/freight_kit/carriers/sna_transportation.rb +10 -0
  274. data/lib/freight_kit/carriers/solid_group.rb +10 -0
  275. data/lib/freight_kit/carriers/solution_carrier_express.rb +10 -0
  276. data/lib/freight_kit/carriers/southeastern_freight_lines.rb +450 -0
  277. data/lib/freight_kit/carriers/southwestern_motor_transport.rb +30 -0
  278. data/lib/freight_kit/carriers/span_alaska.rb +10 -0
  279. data/lib/freight_kit/carriers/specialize_transportation.rb +27 -0
  280. data/lib/freight_kit/carriers/ssi_refrigerated_express.rb +10 -0
  281. data/lib/freight_kit/carriers/standard_forwarding_llc.rb +28 -0
  282. data/lib/freight_kit/carriers/star_american_enterprise.rb +10 -0
  283. data/lib/freight_kit/carriers/sterling_transportation.rb +10 -0
  284. data/lib/freight_kit/carriers/stg.rb +163 -0
  285. data/lib/freight_kit/carriers/supervan_service.rb +10 -0
  286. data/lib/freight_kit/carriers/sutton_transport_inc.rb +12 -0
  287. data/lib/freight_kit/carriers/swift_transportation.rb +28 -0
  288. data/lib/freight_kit/carriers/t_force_worldwide.rb +617 -0
  289. data/lib/freight_kit/carriers/tax_airfreight_inc.rb +35 -0
  290. data/lib/freight_kit/carriers/tforce_freight_inc.rb +30 -0
  291. data/lib/freight_kit/carriers/the_custom_companies.rb +162 -0
  292. data/lib/freight_kit/carriers/thk_trucking.rb +28 -0
  293. data/lib/freight_kit/carriers/tiger_cool_express.rb +11 -0
  294. data/lib/freight_kit/carriers/tili_logistics.rb +10 -0
  295. data/lib/freight_kit/carriers/tmt_industries.rb +10 -0
  296. data/lib/freight_kit/carriers/top_ten_express.rb +28 -0
  297. data/lib/freight_kit/carriers/total_quality_logistics.rb +338 -0
  298. data/lib/freight_kit/carriers/total_transportation.rb +258 -0
  299. data/lib/freight_kit/carriers/trans_international_trucking.rb +29 -0
  300. data/lib/freight_kit/carriers/treasure_transportation.rb +10 -0
  301. data/lib/freight_kit/carriers/tri_state_services.rb +10 -0
  302. data/lib/freight_kit/carriers/tritex_freighters.rb +10 -0
  303. data/lib/freight_kit/carriers/triways.rb +10 -0
  304. data/lib/freight_kit/carriers/tsi_kansas.rb +29 -0
  305. data/lib/freight_kit/carriers/u_and_r_transportation.rb +23 -0
  306. data/lib/freight_kit/carriers/union_pacific.rb +11 -0
  307. data/lib/freight_kit/carriers/united_freight_logistics.rb +10 -0
  308. data/lib/freight_kit/carriers/unlimited_distance_transportation.rb +10 -0
  309. data/lib/freight_kit/carriers/up_streamline.rb +10 -0
  310. data/lib/freight_kit/carriers/ups_freight.rb +12 -0
  311. data/lib/freight_kit/carriers/us_freightways.rb +10 -0
  312. data/lib/freight_kit/carriers/usa_truck.rb +28 -0
  313. data/lib/freight_kit/carriers/usf_holland.rb +11 -0
  314. data/lib/freight_kit/carriers/valley_cartage.rb +11 -0
  315. data/lib/freight_kit/carriers/vc_transport.rb +10 -0
  316. data/lib/freight_kit/carriers/vision_express.rb +11 -0
  317. data/lib/freight_kit/carriers/vision_logistics_group.rb +10 -0
  318. data/lib/freight_kit/carriers/vmg_transportation_group.rb +10 -0
  319. data/lib/freight_kit/carriers/volpe_express.rb +10 -0
  320. data/lib/freight_kit/carriers/ward_trucking.rb +29 -0
  321. data/lib/freight_kit/carriers/wdwb.rb +10 -0
  322. data/lib/freight_kit/carriers/western_flyer_express.rb +28 -0
  323. data/lib/freight_kit/carriers/western_regional_delivery_service.rb +271 -0
  324. data/lib/freight_kit/carriers/western_specialized_trucking.rb +22 -0
  325. data/lib/freight_kit/carriers/win_distribution.rb +28 -0
  326. data/lib/freight_kit/carriers/wlb_transport.rb +10 -0
  327. data/lib/freight_kit/carriers/x_trux.rb +29 -0
  328. data/lib/freight_kit/carriers/xpo_logistics.rb +427 -0
  329. data/lib/freight_kit/carriers/xpress_global_systems.rb +30 -0
  330. data/lib/freight_kit/carriers/xylo_trucking.rb +10 -0
  331. data/lib/freight_kit/carriers/yrc_freight.rb +24 -0
  332. data/lib/freight_kit/carriers/zentner_transportation.rb +28 -0
  333. data/lib/freight_kit/carriers.rb +331 -34
  334. data/lib/freight_kit/countries.rb +22 -0
  335. data/lib/freight_kit/error.rb +0 -2
  336. data/lib/freight_kit/errors/document_not_found_error.rb +0 -2
  337. data/lib/freight_kit/errors/expired_credentials_error.rb +0 -2
  338. data/lib/freight_kit/errors/http_error.rb +0 -2
  339. data/lib/freight_kit/errors/invalid_credentials_error.rb +0 -2
  340. data/lib/freight_kit/errors/response_error.rb +0 -2
  341. data/lib/freight_kit/errors/shipment_not_found_error.rb +0 -2
  342. data/lib/freight_kit/errors/unserviceable_accessorials_error.rb +2 -4
  343. data/lib/freight_kit/errors/unserviceable_error.rb +0 -2
  344. data/lib/freight_kit/helpers/documentable.rb +0 -2
  345. data/lib/freight_kit/helpers/pickupable.rb +3 -5
  346. data/lib/freight_kit/helpers/rateable.rb +0 -2
  347. data/lib/freight_kit/helpers/trackable.rb +0 -2
  348. data/lib/freight_kit/http_client/cache_store.rb +2 -4
  349. data/lib/freight_kit/http_client/log_device.rb +0 -2
  350. data/lib/freight_kit/http_client/response.rb +0 -2
  351. data/lib/freight_kit/http_client/revalidation.rb +0 -2
  352. data/lib/freight_kit/http_client/safe_retries.rb +0 -2
  353. data/lib/freight_kit/http_client/zstd.rb +2 -4
  354. data/lib/freight_kit/http_client.rb +8 -12
  355. data/lib/freight_kit/model.rb +1 -3
  356. data/lib/freight_kit/models/address.rb +15 -0
  357. data/lib/freight_kit/models/contact.rb +3 -4
  358. data/lib/freight_kit/models/country.rb +20 -0
  359. data/lib/freight_kit/models/credential.rb +14 -16
  360. data/lib/freight_kit/models/date_time.rb +0 -2
  361. data/lib/freight_kit/models/document_response.rb +0 -2
  362. data/lib/freight_kit/models/label.rb +0 -2
  363. data/lib/freight_kit/models/location.rb +10 -25
  364. data/lib/freight_kit/models/pickup_response.rb +0 -2
  365. data/lib/freight_kit/models/price.rb +0 -2
  366. data/lib/freight_kit/models/rate.rb +0 -2
  367. data/lib/freight_kit/models/rate_response.rb +0 -2
  368. data/lib/freight_kit/models/region.rb +19 -0
  369. data/lib/freight_kit/models/response.rb +0 -2
  370. data/lib/freight_kit/models/shipment.rb +4 -6
  371. data/lib/freight_kit/models/shipment_event.rb +0 -2
  372. data/lib/freight_kit/models/terminal.rb +10 -0
  373. data/lib/freight_kit/models/tracking_response.rb +0 -2
  374. data/lib/freight_kit/package.rb +51 -53
  375. data/lib/freight_kit/package_item.rb +14 -14
  376. data/lib/freight_kit/packaging.rb +21 -26
  377. data/lib/freight_kit/platform.rb +0 -32
  378. data/lib/freight_kit/platforms/carrier_logistics.rb +331 -345
  379. data/lib/freight_kit/platforms/next_tms.rb +93 -0
  380. data/lib/freight_kit/platforms/the_great_information_factory.rb +500 -425
  381. data/lib/freight_kit/regions.rb +27 -0
  382. data/lib/freight_kit/shipment_packer.rb +36 -38
  383. data/lib/freight_kit/tariff/overlength_rule.rb +1 -5
  384. data/lib/freight_kit/tariff.rb +0 -2
  385. data/lib/freight_kit.rb +84 -11
  386. metadata +361 -51
  387. data/configuration/carriers/abfs.yml +0 -124
  388. data/configuration/carriers/btvp.yml +0 -84
  389. data/configuration/carriers/ccyq.yml +0 -121
  390. data/configuration/carriers/clni.yml +0 -113
  391. data/configuration/carriers/cnwy.yml +0 -113
  392. data/configuration/carriers/ctbv.yml +0 -117
  393. data/configuration/carriers/dcha.yml +0 -105
  394. data/configuration/carriers/dlds.yml +0 -111
  395. data/configuration/carriers/dphe.yml +0 -130
  396. data/configuration/carriers/drrq.yml +0 -131
  397. data/configuration/carriers/fcsy.yml +0 -102
  398. data/configuration/carriers/fwda.yml +0 -137
  399. data/configuration/carriers/jfj_transportation.yml +0 -2
  400. data/configuration/carriers/mtvl.yml +0 -12
  401. data/configuration/carriers/numk.yml +0 -14
  402. data/configuration/carriers/otcl.yml +0 -124
  403. data/configuration/carriers/pens.yml +0 -22
  404. data/configuration/carriers/rdfs.yml +0 -142
  405. data/configuration/carriers/saia.yml +0 -129
  406. data/configuration/carriers/sefl.yml +0 -115
  407. data/configuration/carriers/totl.yml +0 -111
  408. data/configuration/carriers/tqyl.yml +0 -28
  409. data/configuration/carriers/wrds.yml +0 -20
  410. data/configuration/platforms/carrier_logistics.yml +0 -25
  411. data/configuration/platforms/next.yml +0 -12
  412. data/configuration/platforms/the_great_information_factory.yml +0 -122
  413. data/lib/freight_kit/carriers/abfs.rb +0 -421
  414. data/lib/freight_kit/carriers/btvp.rb +0 -29
  415. data/lib/freight_kit/carriers/ccyq.rb +0 -310
  416. data/lib/freight_kit/carriers/clni.rb +0 -396
  417. data/lib/freight_kit/carriers/cnwy.rb +0 -327
  418. data/lib/freight_kit/carriers/ctbv.rb +0 -53
  419. data/lib/freight_kit/carriers/dcha.rb +0 -76
  420. data/lib/freight_kit/carriers/dlds.rb +0 -49
  421. data/lib/freight_kit/carriers/dphe.rb +0 -472
  422. data/lib/freight_kit/carriers/drrq.rb +0 -580
  423. data/lib/freight_kit/carriers/fcsy.rb +0 -57
  424. data/lib/freight_kit/carriers/fwda.rb +0 -744
  425. data/lib/freight_kit/carriers/mtvl.rb +0 -34
  426. data/lib/freight_kit/carriers/numk.rb +0 -58
  427. data/lib/freight_kit/carriers/otcl.rb +0 -520
  428. data/lib/freight_kit/carriers/pens.rb +0 -204
  429. data/lib/freight_kit/carriers/rdfs.rb +0 -521
  430. data/lib/freight_kit/carriers/sefl.rb +0 -342
  431. data/lib/freight_kit/carriers/totl.rb +0 -172
  432. data/lib/freight_kit/carriers/tqyl.rb +0 -337
  433. data/lib/freight_kit/carriers/wrds.rb +0 -246
  434. data/lib/freight_kit/platforms/next.rb +0 -101
@@ -1,436 +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)
190
326
 
191
- error = response.dig(:create_response, :create_result, :code)
327
+ if error.present?
328
+ message = response.dig(:create_response, :create_result, :message)
192
329
 
193
- if error.present?
194
- message = response.dig(:create_response, :create_result, :message)
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
195
338
 
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}")
202
- return rate_response
203
- end
339
+ if message.downcase.include?('must not exceed 10 lines')
340
+ rate_response.error = UnserviceableError.new("#{error}: #{message}")
341
+ return rate_response
342
+ end
204
343
 
205
- if message.downcase.include?('must not exceed 10 lines')
206
- rate_response.error = UnserviceableError.new("#{error}: #{message}")
344
+ rate_response.error = ResponseError.new("#{error}: #{message}")
207
345
  return rate_response
208
346
  end
209
347
 
210
- rate_response.error = ResponseError.new("#{error}: #{message}")
211
- return rate_response
212
- end
348
+ result = response.dig(:create_response, :create_result)
213
349
 
214
- result = response.dig(:create_response, :create_result)
350
+ if result.blank?
351
+ rate_response.error = ResponseError.new('Unknown result')
352
+ return rate_response
353
+ end
215
354
 
216
- if result.blank?
217
- rate_response.error = ResponseError.new('Unknown result')
218
- return rate_response
219
- end
355
+ if result[:total_invoice].blank?
356
+ rate_response.error = ResponseError.new('Cost is blank')
357
+ return rate_response
358
+ end
220
359
 
221
- if result[:total_invoice].blank?
222
- rate_response.error = ResponseError.new('Cost is blank')
223
- return rate_response
224
- end
360
+ transit_days = result[:standard_service_days].to_i
361
+ estimate_reference = result[:quote_number]
225
362
 
226
- transit_days = result[:standard_service_days].to_i
227
- estimate_reference = result[:quote_number]
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)
228
365
 
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)
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
231
373
 
232
- prices = rate_accessorial_items.map do |rate_accessorial_item|
233
- Price.new(
234
- blame: :api,
235
- cents: (rate_accessorial_item[:amount].to_f * 100).to_i,
236
- description: rate_accessorial_item[:description]&.titleize&.squish,
237
- )
238
- end
374
+ standard_ltl_cents = (result[:total_invoice].to_f * 100).to_i - prices.sum(&:cents)
239
375
 
240
- standard_ltl_cents = (result[:total_invoice].to_f * 100).to_i - prices.sum(&:cents)
241
-
242
- rates = []
243
-
244
- rates << Rate.new(
245
- carrier: self,
246
- carrier_name: self.class.name,
247
- currency: 'USD',
248
- estimate_reference:,
249
- scac: self.class.scac.upcase,
250
- service_name: :standard,
251
- shipment:,
252
- prices: [
253
- Price.new(
254
- blame: :api,
255
- cents: standard_ltl_cents,
256
- description: 'Freight',
257
- ),
258
- ] + prices,
259
- transit_days:,
260
- with_excessive_length_fees: @conf.dig(:attributes, :rates, :with_excessive_length_fees),
261
- )
262
-
263
- [
264
- { guaranteed_ltl: result[:guarantee_amount] },
265
- { guaranteed_ltl_am: result[:guarantee_amount12pm] },
266
- { guaranteed_ltl_pm: result[:guarantee_amount2pm] },
267
- ].each do |service|
268
- next if service.values[0] == '0' || service.values[0].blank?
269
-
270
- cents = (service.values[0].to_f * 100).to_i
376
+ rates = []
271
377
 
272
378
  rates << Rate.new(
273
- carrier_name: self.class.name,
274
379
  carrier: self,
380
+ carrier_name: name,
275
381
  currency: 'USD',
276
382
  estimate_reference:,
277
- scac: self.class.scac.upcase,
278
- service_name: service.keys[0],
383
+ scac:,
384
+ service_name: :standard,
279
385
  shipment:,
280
- prices: [
281
- Price.new(
282
- blame: :api,
283
- cents: standard_ltl_cents + cents,
284
- description: 'Freight',
285
- ),
286
- ] + prices,
287
- 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?
288
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
289
415
  end
290
416
 
291
- rate_response.rates = rates
292
- rate_response
293
- end
417
+ def parse_tracking_response(response)
418
+ tracking_response = TrackingResponse.new(carrier: self, request: last_request, response:)
294
419
 
295
- # 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
296
425
 
297
- def build_tracking_request(tracking_number)
298
- request = {
299
- request: {
300
- ProNumber: tracking_number
301
- }
302
- }
303
- save_request(request)
304
- request
305
- end
426
+ if error.present?
427
+ tracking_response.error = ResponseError.new(error)
428
+ return tracking_response
429
+ end
306
430
 
307
- def parse_api_date_time(date_time, location)
308
- return if date_time.blank?
431
+ search_result = response.dig(:get_by_pro_number_response, :get_by_pro_number_result)
309
432
 
310
- local_date_time = ::Time.strptime(date_time, '%Y-%m-%d %H:%M:%S').to_fs(:db)
311
- ::FreightKit::DateTime.new(local_date_time:, location:)
312
- end
433
+ if search_result.blank?
434
+ tracking_response.error = ShipmentNotFoundError.new
435
+ return tracking_response
436
+ end
313
437
 
314
- def parse_api_location(api_event)
315
- Location.new(
316
- city: api_event[:city]&.titleize,
317
- province: api_event[:state]&.upcase,
318
- country: ActiveUtils::Country.find('USA'),
319
- )
320
- 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
+ )
321
463
 
322
- def parse_tracking_response(response)
323
- 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)
324
466
 
325
- error = if response
326
- response.dig(:get_by_pro_number_response, :get_by_pro_number_result, :code)
327
- else
328
- 'API Error: Unknown response'
329
- end
467
+ api_date_time = search_result[:pickup_date_time]
468
+ pickup_date = parse_api_date_time(api_date_time, shipper_location)
330
469
 
331
- if error.present?
332
- tracking_response.error = ResponseError.new(error)
333
- return tracking_response
334
- end
470
+ api_date_time = search_result[:delivery_appointment_date_time]
471
+ scheduled_delivery_date = parse_api_date_time(api_date_time, receiver_location)
335
472
 
336
- search_result = response.dig(:get_by_pro_number_response, :get_by_pro_number_result)
473
+ tracking_number = search_result[:pro_number]
337
474
 
338
- if search_result.blank?
339
- tracking_response.error = ShipmentNotFoundError.new
340
- return tracking_response
341
- end
475
+ shipment_events = []
342
476
 
343
- address1 = [
344
- search_result.dig(:shipper, :address1),
345
- search_result.dig(:shipper, :address2),
346
- ]
347
- .select(&:present?)
348
- .map { |line| line.squish.strip.titleize }
349
- .join(', ')
350
-
351
- shipper_location = Location.new(
352
- address1:,
353
- city: search_result.dig(:shipper, :city)&.squish&.titleize,
354
- province: search_result.dig(:shipper, :state)&.strip&.upcase,
355
- postal_code: search_result.dig(:shipper, :zipcode)&.strip,
356
- country: ActiveUtils::Country.find('USA'),
357
- )
358
-
359
- address1 = [
360
- search_result.dig(:consignee, :address1),
361
- search_result.dig(:consignee, :address2),
362
- ]
363
- .select(&:present?)
364
- .map { |line| line.squish.strip.titleize }
365
- .join(', ')
366
-
367
- receiver_location = Location.new(
368
- address1:,
369
- city: search_result.dig(:consignee, :city)&.squish&.titleize,
370
- province: search_result.dig(:consignee, :state)&.strip&.upcase,
371
- postal_code: search_result.dig(:consignee, :zipcode)&.strip,
372
- country: ActiveUtils::Country.find('USA'),
373
- )
374
-
375
- api_date_time = search_result[:delivery_date_time_arrive]
376
- actual_delivery_date = parse_api_date_time(api_date_time, receiver_location)
377
-
378
- api_date_time = search_result[:pickup_date_time]
379
- pickup_date = parse_api_date_time(api_date_time, shipper_location)
380
-
381
- api_date_time = search_result[:delivery_appointment_date_time]
382
- scheduled_delivery_date = parse_api_date_time(api_date_time, receiver_location)
383
-
384
- tracking_number = search_result[:pro_number]
385
-
386
- shipment_events = []
387
-
388
- api_events = search_result.dig(:history, :history_item)
389
-
390
- if api_events.blank?
391
- shipment_events << ShipmentEvent.new(
392
- date_time: pickup_date,
393
- location: shipper_location,
394
- type_code: :picked_up,
395
- )
396
- else
397
- api_events = [api_events] if api_events.is_a?(Hash)
477
+ api_events = search_result.dig(:history, :history_item)
398
478
 
399
- api_events.each do |api_event|
400
- event_key = nil
401
- 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)
402
487
 
403
- @conf.dig(:events, :types).each do |key, val|
404
- if comment.downcase.include?(val)
405
- event_key = key
406
- 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
407
497
  end
408
- end
409
- next if event_key.blank?
498
+ next if event_key.blank?
410
499
 
411
- api_date_time = api_event[:activity_date_time]
500
+ api_date_time = api_event[:activity_date_time]
412
501
 
413
- location = parse_api_location(api_event)
414
- 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)
415
504
 
416
- 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
417
507
  end
418
- end
419
508
 
420
- 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
+ )
421
521
 
422
- tracking_response.assign_attributes(
423
- actual_delivery_date:,
424
- destination: receiver_location,
425
- origin: shipper_location,
426
- scheduled_delivery_date:,
427
- ship_time: pickup_date,
428
- shipment_events:,
429
- status:,
430
- tracking_number:,
431
- )
522
+ tracking_response
523
+ end
432
524
 
433
- 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
434
543
  end
435
544
  end
436
545
  end