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.
- checksums.yaml +4 -4
- data/Gemfile +0 -2
- data/README.md +1 -2
- data/Rakefile +6 -0
- data/VERSION +1 -1
- data/configuration/locations/amazon_warehouses.yml +3330 -0
- data/freight_kit.gemspec +13 -13
- data/lib/freight_kit/address_normalizer.rb +26 -0
- data/lib/freight_kit/amazon_warehouse.rb +33 -0
- data/lib/freight_kit/api_clients/soap_client.rb +7 -9
- data/lib/freight_kit/carrier.rb +250 -303
- data/lib/freight_kit/carriers/a1_express.rb +25 -0
- data/lib/freight_kit/carriers/a_duie_pyle.rb +30 -0
- data/lib/freight_kit/carriers/aaa_cooper.rb +11 -0
- data/lib/freight_kit/carriers/aaa_expedited_services.rb +10 -0
- data/lib/freight_kit/carriers/ab_brothers_usa_inc.rb +12 -0
- data/lib/freight_kit/carriers/aberdeen_express_inc.rb +28 -0
- data/lib/freight_kit/carriers/abf_freight_system.rb +492 -0
- data/lib/freight_kit/carriers/access_transport.rb +10 -0
- data/lib/freight_kit/carriers/action_express.rb +10 -0
- data/lib/freight_kit/carriers/adams_and_companies.rb +10 -0
- data/lib/freight_kit/carriers/advance_distribution.rb +28 -0
- data/lib/freight_kit/carriers/alcon_transport.rb +10 -0
- data/lib/freight_kit/carriers/all_freight.rb +10 -0
- data/lib/freight_kit/carriers/alliance_transportation_group.rb +10 -0
- data/lib/freight_kit/carriers/allstate_transport.rb +10 -0
- data/lib/freight_kit/carriers/aloha_freight_forwarders.rb +35 -0
- data/lib/freight_kit/carriers/amado_trucking.rb +35 -0
- data/lib/freight_kit/carriers/american_fast_freight.rb +28 -0
- data/lib/freight_kit/carriers/amigos_service_transportation.rb +10 -0
- data/lib/freight_kit/carriers/anderson_towing_and_transport.rb +10 -0
- data/lib/freight_kit/carriers/apex_transporting.rb +10 -0
- data/lib/freight_kit/carriers/archer_cargo.rb +35 -0
- data/lib/freight_kit/carriers/armstrong_transport_group.rb +10 -0
- data/lib/freight_kit/carriers/autobahn_logistics.rb +10 -0
- data/lib/freight_kit/carriers/averitt_express.rb +30 -0
- data/lib/freight_kit/carriers/ba_transportation.rb +10 -0
- data/lib/freight_kit/carriers/balkin_express.rb +10 -0
- data/lib/freight_kit/carriers/bay_area_express.rb +10 -0
- data/lib/freight_kit/carriers/bc_freightways.rb +11 -0
- data/lib/freight_kit/carriers/benjamin_best_freight_inc.rb +37 -0
- data/lib/freight_kit/carriers/bennett_trucking.rb +10 -0
- data/lib/freight_kit/carriers/best_overnite_express.rb +78 -0
- data/lib/freight_kit/carriers/best_trucking.rb +10 -0
- data/lib/freight_kit/carriers/bestway_transport.rb +10 -0
- data/lib/freight_kit/carriers/bryan_systems.rb +10 -0
- data/lib/freight_kit/carriers/c_and_w_express.rb +10 -0
- data/lib/freight_kit/carriers/campbell_trucking.rb +10 -0
- data/lib/freight_kit/carriers/carde_transportation.rb +10 -0
- data/lib/freight_kit/carriers/cardinal_logistics.rb +28 -0
- data/lib/freight_kit/carriers/cdc_transport.rb +10 -0
- data/lib/freight_kit/carriers/cdo_express_diversified.rb +10 -0
- data/lib/freight_kit/carriers/cedar_supply_trucking.rb +10 -0
- data/lib/freight_kit/carriers/central_freight_lines.rb +12 -0
- data/lib/freight_kit/carriers/central_transport.rb +12 -0
- data/lib/freight_kit/carriers/chicago_suburban_express.rb +28 -0
- data/lib/freight_kit/carriers/city_logistics.rb +11 -0
- data/lib/freight_kit/carriers/clear_lane_freight_systems.rb +483 -0
- data/lib/freight_kit/carriers/cleopatra_trucking.rb +10 -0
- data/lib/freight_kit/carriers/clifford_transportation.rb +10 -0
- data/lib/freight_kit/carriers/cms_domestic.rb +25 -0
- data/lib/freight_kit/carriers/cnd_logistics.rb +10 -0
- data/lib/freight_kit/carriers/coast_to_coast_transport.rb +27 -0
- data/lib/freight_kit/carriers/countrywide_carriers.rb +10 -0
- data/lib/freight_kit/carriers/cpl_express.rb +35 -0
- data/lib/freight_kit/carriers/crosby_trucking_service.rb +29 -0
- data/lib/freight_kit/carriers/cross_country_freight_solutions.rb +419 -0
- data/lib/freight_kit/carriers/crowley.rb +10 -0
- data/lib/freight_kit/carriers/csa_transportation.rb +40 -0
- data/lib/freight_kit/carriers/csx_transportation.rb +40 -0
- data/lib/freight_kit/carriers/custom_global_logistics.rb +14 -0
- data/lib/freight_kit/carriers/d_and_a_transport.rb +10 -0
- data/lib/freight_kit/carriers/dak_transport.rb +10 -0
- data/lib/freight_kit/carriers/dash_courier_and_logistics_north_carolina.rb +10 -0
- data/lib/freight_kit/carriers/daylight_transport.rb +29 -0
- data/lib/freight_kit/carriers/dayton_freight_lines.rb +30 -0
- data/lib/freight_kit/carriers/dbr_logistics.rb +10 -0
- data/lib/freight_kit/carriers/deep_south_freight.rb +27 -0
- data/lib/freight_kit/carriers/delta_express.rb +10 -0
- data/lib/freight_kit/carriers/delta_transport.rb +10 -0
- data/lib/freight_kit/carriers/delta_trucking_logistics.rb +10 -0
- data/lib/freight_kit/carriers/demco_express.rb +10 -0
- data/lib/freight_kit/carriers/dependable_global_express.rb +10 -0
- data/lib/freight_kit/carriers/dependable_hawaiian_express.rb +24 -0
- data/lib/freight_kit/carriers/dependable_highway_express.rb +585 -0
- data/lib/freight_kit/carriers/desert_coastal_transport.rb +10 -0
- data/lib/freight_kit/carriers/dhl.rb +11 -0
- data/lib/freight_kit/carriers/diamond_line_delivery.rb +174 -0
- data/lib/freight_kit/carriers/ding_tai_trucking.rb +10 -0
- data/lib/freight_kit/carriers/diversified_transfer_and_storage.rb +29 -0
- data/lib/freight_kit/carriers/dohrn_transfer_company.rb +30 -0
- data/lib/freight_kit/carriers/dot_line_transportation.rb +29 -0
- data/lib/freight_kit/carriers/drt_transportation.rb +13 -0
- data/lib/freight_kit/carriers/dugan_truck_line.rb +29 -0
- data/lib/freight_kit/carriers/dupont.rb +10 -0
- data/lib/freight_kit/carriers/e_transport_carriers.rb +29 -0
- data/lib/freight_kit/carriers/echo_global_logistics.rb +13 -0
- data/lib/freight_kit/carriers/ecklund_logistics.rb +10 -0
- data/lib/freight_kit/carriers/el_emplumado_transport.rb +10 -0
- data/lib/freight_kit/carriers/elite_carriers.rb +28 -0
- data/lib/freight_kit/carriers/emerald_express.rb +10 -0
- data/lib/freight_kit/carriers/era_transport.rb +10 -0
- data/lib/freight_kit/carriers/estes_express_lines.rb +25 -0
- data/lib/freight_kit/carriers/euro_kam.rb +28 -0
- data/lib/freight_kit/carriers/ew_riverside_trucking.rb +10 -0
- data/lib/freight_kit/carriers/express_2000_inc.rb +12 -0
- data/lib/freight_kit/carriers/express_services_international.rb +10 -0
- data/lib/freight_kit/carriers/f_and_a_express.rb +27 -0
- data/lib/freight_kit/carriers/fairmont_logistics.rb +13 -0
- data/lib/freight_kit/carriers/fargo_cargo.rb +10 -0
- data/lib/freight_kit/carriers/fast_freight_transportation.rb +10 -0
- data/lib/freight_kit/carriers/fast_load_transport.rb +10 -0
- data/lib/freight_kit/carriers/fed_ex_express.rb +30 -0
- data/lib/freight_kit/carriers/fed_ex_ground.rb +24 -0
- data/lib/freight_kit/carriers/fed_ex_ltl_economy.rb +11 -0
- data/lib/freight_kit/carriers/fed_ex_ltl_priority.rb +11 -0
- data/lib/freight_kit/carriers/first_trucking_express.rb +10 -0
- data/lib/freight_kit/carriers/flash_trucking.rb +10 -0
- data/lib/freight_kit/carriers/fort_transportation_and_service_company_inc.rb +37 -0
- data/lib/freight_kit/carriers/forward_air.rb +789 -0
- data/lib/freight_kit/carriers/frahtex.rb +10 -0
- data/lib/freight_kit/carriers/frozen_food_express.rb +10 -0
- data/lib/freight_kit/carriers/gholia_bros_trucking.rb +36 -0
- data/lib/freight_kit/carriers/global_cargo.rb +10 -0
- data/lib/freight_kit/carriers/global_logistics_and_transportation.rb +10 -0
- data/lib/freight_kit/carriers/gls_freight.rb +32 -0
- data/lib/freight_kit/carriers/go_trucking_services.rb +10 -0
- data/lib/freight_kit/carriers/gold_eagle_transportation.rb +11 -0
- data/lib/freight_kit/carriers/golden_drop_trucking.rb +10 -0
- data/lib/freight_kit/carriers/gonzalez_transportation.rb +10 -0
- data/lib/freight_kit/carriers/gps_transport.rb +10 -0
- data/lib/freight_kit/carriers/greene_enterprise.rb +10 -0
- data/lib/freight_kit/carriers/gsa_international.rb +10 -0
- data/lib/freight_kit/carriers/gsp_express.rb +24 -0
- data/lib/freight_kit/carriers/gsv_transportation.rb +10 -0
- data/lib/freight_kit/carriers/gta_transportation.rb +10 -0
- data/lib/freight_kit/carriers/guam_freight_services.rb +10 -0
- data/lib/freight_kit/carriers/harrah_transportation.rb +23 -0
- data/lib/freight_kit/carriers/her_trucking.rb +10 -0
- data/lib/freight_kit/carriers/hercules_freight.rb +20 -0
- data/lib/freight_kit/carriers/highlander_xpress.rb +36 -0
- data/lib/freight_kit/carriers/hn_transport.rb +10 -0
- data/lib/freight_kit/carriers/honolulu_freight_service.rb +10 -0
- data/lib/freight_kit/carriers/hot_line_freight_system_inc.rb +12 -0
- data/lib/freight_kit/carriers/hotshot_freight_of_texas.rb +13 -0
- data/lib/freight_kit/carriers/houser_transport.rb +27 -0
- data/lib/freight_kit/carriers/infiniti_freight_logistics.rb +28 -0
- data/lib/freight_kit/carriers/infinity_trucking.rb +10 -0
- data/lib/freight_kit/carriers/interstate_tma.rb +10 -0
- data/lib/freight_kit/carriers/intrade_industries.rb +10 -0
- data/lib/freight_kit/carriers/jasper_trucking.rb +28 -0
- data/lib/freight_kit/carriers/jb_hunt.rb +11 -0
- data/lib/freight_kit/carriers/jfj_transportation.rb +8 -8
- data/lib/freight_kit/carriers/jkb_express.rb +10 -0
- data/lib/freight_kit/carriers/jlm_transport.rb +10 -0
- data/lib/freight_kit/carriers/johansson_transport.rb +10 -0
- data/lib/freight_kit/carriers/jones_express.rb +10 -0
- data/lib/freight_kit/carriers/jp_logistics.rb +41 -0
- data/lib/freight_kit/carriers/just_in_time_cargo.rb +29 -0
- data/lib/freight_kit/carriers/kengkok_times.rb +10 -0
- data/lib/freight_kit/carriers/kings_express.rb +10 -0
- data/lib/freight_kit/carriers/klc_transportation.rb +10 -0
- data/lib/freight_kit/carriers/km_trucking.rb +10 -0
- data/lib/freight_kit/carriers/kma_logistics.rb +10 -0
- data/lib/freight_kit/carriers/krc_logistics.rb +10 -0
- data/lib/freight_kit/carriers/ktx.rb +10 -0
- data/lib/freight_kit/carriers/landstar.rb +25 -0
- data/lib/freight_kit/carriers/lanter_distributing_llc.rb +30 -0
- data/lib/freight_kit/carriers/ld_trucking.rb +10 -0
- data/lib/freight_kit/carriers/legacy_logistics_solutions.rb +10 -0
- data/lib/freight_kit/carriers/leonards_express.rb +10 -0
- data/lib/freight_kit/carriers/liberty_linehaul_west.rb +28 -0
- data/lib/freight_kit/carriers/liberty_transport.rb +10 -0
- data/lib/freight_kit/carriers/lightning_express.rb +10 -0
- data/lib/freight_kit/carriers/lj_express.rb +24 -0
- data/lib/freight_kit/carriers/lkp_enterprises.rb +10 -0
- data/lib/freight_kit/carriers/ltl_pros.rb +28 -0
- data/lib/freight_kit/carriers/m_and_m_and_sons.rb +10 -0
- data/lib/freight_kit/carriers/mag_lines_transport.rb +10 -0
- data/lib/freight_kit/carriers/magic_messenger.rb +24 -0
- data/lib/freight_kit/carriers/majors_transit.rb +10 -0
- data/lib/freight_kit/carriers/map_global_logistics.rb +10 -0
- data/lib/freight_kit/carriers/matths_trucking.rb +11 -0
- data/lib/freight_kit/carriers/mav_canadian_transport.rb +13 -0
- data/lib/freight_kit/carriers/mc_systems.rb +35 -0
- data/lib/freight_kit/carriers/mega_fleet.rb +10 -0
- data/lib/freight_kit/carriers/mega_trans_group.rb +28 -0
- data/lib/freight_kit/carriers/meta_express.rb +10 -0
- data/lib/freight_kit/carriers/mia_transportation.rb +10 -0
- data/lib/freight_kit/carriers/midwest_motor_express.rb +14 -0
- data/lib/freight_kit/carriers/midwest_transport_and_trucking.rb +10 -0
- data/lib/freight_kit/carriers/mikade_delivery_service.rb +10 -0
- data/lib/freight_kit/carriers/mohoff_freight_lines.rb +23 -0
- data/lib/freight_kit/carriers/montata_travelers_express.rb +10 -0
- data/lib/freight_kit/carriers/morgan_van_lines.rb +29 -0
- data/lib/freight_kit/carriers/moto_transportation.rb +24 -0
- data/lib/freight_kit/carriers/mountain_valley_express.rb +197 -0
- data/lib/freight_kit/carriers/ms_freight.rb +27 -0
- data/lib/freight_kit/carriers/mvg_transport.rb +10 -0
- data/lib/freight_kit/carriers/n_and_m_transfer_co_inc.rb +29 -0
- data/lib/freight_kit/carriers/nabot_transport_solutions.rb +10 -0
- data/lib/freight_kit/carriers/national_freight_xpress.rb +10 -0
- data/lib/freight_kit/carriers/navigation_group.rb +10 -0
- data/lib/freight_kit/carriers/nelson_trucking.rb +10 -0
- data/lib/freight_kit/carriers/network_1_transportation.rb +10 -0
- data/lib/freight_kit/carriers/new_century_transport.rb +28 -0
- data/lib/freight_kit/carriers/new_penn_motor_express.rb +11 -0
- data/lib/freight_kit/carriers/nieves_transportation.rb +10 -0
- data/lib/freight_kit/carriers/nolan_transportation_group.rb +26 -0
- data/lib/freight_kit/carriers/northland_trucking.rb +10 -0
- data/lib/freight_kit/carriers/northwest_carrier_logistics.rb +27 -0
- data/lib/freight_kit/carriers/nt_usa.rb +10 -0
- data/lib/freight_kit/carriers/nu_line_transportation.rb +10 -0
- data/lib/freight_kit/carriers/numark_transportation.rb +80 -0
- data/lib/freight_kit/carriers/nvk_transport.rb +10 -0
- data/lib/freight_kit/carriers/ny_transport.rb +10 -0
- data/lib/freight_kit/carriers/oak_harbor.rb +28 -0
- data/lib/freight_kit/carriers/oakline_transportation.rb +10 -0
- data/lib/freight_kit/carriers/old_dominion_freight_line.rb +30 -0
- data/lib/freight_kit/carriers/on_trac.rb +573 -0
- data/lib/freight_kit/carriers/one_hundred_one_transport.rb +10 -0
- data/lib/freight_kit/carriers/one_way_delivery.rb +10 -0
- data/lib/freight_kit/carriers/oracle_transportation_solutions.rb +10 -0
- data/lib/freight_kit/carriers/orange_courier.rb +27 -0
- data/lib/freight_kit/carriers/ortas_trucking.rb +10 -0
- data/lib/freight_kit/carriers/pac_trux_transportation.rb +10 -0
- data/lib/freight_kit/carriers/pacer.rb +10 -0
- data/lib/freight_kit/carriers/pacific_logistics.rb +10 -0
- data/lib/freight_kit/carriers/pacific_states_truck_lines.rb +10 -0
- data/lib/freight_kit/carriers/paradise_distributing.rb +10 -0
- data/lib/freight_kit/carriers/paramount_freight_systems.rb +10 -0
- data/lib/freight_kit/carriers/peninsula_truck_lines.rb +222 -0
- data/lib/freight_kit/carriers/pg_transport.rb +10 -0
- data/lib/freight_kit/carriers/pgs_360.rb +10 -0
- data/lib/freight_kit/carriers/pilot_freight_services.rb +10 -0
- data/lib/freight_kit/carriers/pious_trans.rb +27 -0
- data/lib/freight_kit/carriers/pitt_ohio_express.rb +30 -0
- data/lib/freight_kit/carriers/pki_logistics.rb +12 -0
- data/lib/freight_kit/carriers/plana_transportation.rb +28 -0
- data/lib/freight_kit/carriers/prestige.rb +10 -0
- data/lib/freight_kit/carriers/pro_trans_solutions.rb +28 -0
- data/lib/freight_kit/carriers/puma_logistics.rb +10 -0
- data/lib/freight_kit/carriers/pwc_international.rb +10 -0
- data/lib/freight_kit/carriers/quality_logistics.rb +10 -0
- data/lib/freight_kit/carriers/queen_star_trucking.rb +27 -0
- data/lib/freight_kit/carriers/r_and_l_carriers.rb +11 -0
- data/lib/freight_kit/carriers/rac_transport.rb +10 -0
- data/lib/freight_kit/carriers/re_logistics.rb +23 -0
- data/lib/freight_kit/carriers/reddaway.rb +11 -0
- data/lib/freight_kit/carriers/reefer_van_network.rb +13 -0
- data/lib/freight_kit/carriers/refrigerated_trucking_and_ltl_transportation_services.rb +10 -0
- data/lib/freight_kit/carriers/ridgeline_express.rb +10 -0
- data/lib/freight_kit/carriers/rist_transport.rb +29 -0
- data/lib/freight_kit/carriers/river_city_transport.rb +10 -0
- data/lib/freight_kit/carriers/roadrunner_transportation_services.rb +675 -0
- data/lib/freight_kit/carriers/roadtex.rb +13 -0
- data/lib/freight_kit/carriers/ronald_transport_services.rb +10 -0
- data/lib/freight_kit/carriers/rose_trucking.rb +24 -0
- data/lib/freight_kit/carriers/rp_and_j_transport.rb +24 -0
- data/lib/freight_kit/carriers/rpm_transportation.rb +11 -0
- data/lib/freight_kit/carriers/rude_transportation.rb +30 -0
- data/lib/freight_kit/carriers/s_and_s_logistics.rb +10 -0
- data/lib/freight_kit/carriers/saia.rb +470 -361
- data/lib/freight_kit/carriers/sb_transportation.rb +27 -0
- data/lib/freight_kit/carriers/schneider_national.rb +29 -0
- data/lib/freight_kit/carriers/schwarz_trucking.rb +10 -0
- data/lib/freight_kit/carriers/sewell_motor_express.rb +29 -0
- data/lib/freight_kit/carriers/shawnee_trucking.rb +28 -0
- data/lib/freight_kit/carriers/shi_logistics.rb +10 -0
- data/lib/freight_kit/carriers/sinbad_transport.rb +10 -0
- data/lib/freight_kit/carriers/skyway.rb +10 -0
- data/lib/freight_kit/carriers/smith_cargo_transportation_services.rb +23 -0
- data/lib/freight_kit/carriers/sna_transportation.rb +10 -0
- data/lib/freight_kit/carriers/solid_group.rb +10 -0
- data/lib/freight_kit/carriers/solution_carrier_express.rb +10 -0
- data/lib/freight_kit/carriers/southeastern_freight_lines.rb +450 -0
- data/lib/freight_kit/carriers/southwestern_motor_transport.rb +30 -0
- data/lib/freight_kit/carriers/span_alaska.rb +10 -0
- data/lib/freight_kit/carriers/specialize_transportation.rb +27 -0
- data/lib/freight_kit/carriers/ssi_refrigerated_express.rb +10 -0
- data/lib/freight_kit/carriers/standard_forwarding_llc.rb +28 -0
- data/lib/freight_kit/carriers/star_american_enterprise.rb +10 -0
- data/lib/freight_kit/carriers/sterling_transportation.rb +10 -0
- data/lib/freight_kit/carriers/stg.rb +163 -0
- data/lib/freight_kit/carriers/supervan_service.rb +10 -0
- data/lib/freight_kit/carriers/sutton_transport_inc.rb +12 -0
- data/lib/freight_kit/carriers/swift_transportation.rb +28 -0
- data/lib/freight_kit/carriers/t_force_worldwide.rb +617 -0
- data/lib/freight_kit/carriers/tax_airfreight_inc.rb +35 -0
- data/lib/freight_kit/carriers/tforce_freight_inc.rb +30 -0
- data/lib/freight_kit/carriers/the_custom_companies.rb +162 -0
- data/lib/freight_kit/carriers/thk_trucking.rb +28 -0
- data/lib/freight_kit/carriers/tiger_cool_express.rb +11 -0
- data/lib/freight_kit/carriers/tili_logistics.rb +10 -0
- data/lib/freight_kit/carriers/tmt_industries.rb +10 -0
- data/lib/freight_kit/carriers/top_ten_express.rb +28 -0
- data/lib/freight_kit/carriers/total_quality_logistics.rb +338 -0
- data/lib/freight_kit/carriers/total_transportation.rb +258 -0
- data/lib/freight_kit/carriers/trans_international_trucking.rb +29 -0
- data/lib/freight_kit/carriers/treasure_transportation.rb +10 -0
- data/lib/freight_kit/carriers/tri_state_services.rb +10 -0
- data/lib/freight_kit/carriers/tritex_freighters.rb +10 -0
- data/lib/freight_kit/carriers/triways.rb +10 -0
- data/lib/freight_kit/carriers/tsi_kansas.rb +29 -0
- data/lib/freight_kit/carriers/u_and_r_transportation.rb +23 -0
- data/lib/freight_kit/carriers/union_pacific.rb +11 -0
- data/lib/freight_kit/carriers/united_freight_logistics.rb +10 -0
- data/lib/freight_kit/carriers/unlimited_distance_transportation.rb +10 -0
- data/lib/freight_kit/carriers/up_streamline.rb +10 -0
- data/lib/freight_kit/carriers/ups_freight.rb +12 -0
- data/lib/freight_kit/carriers/us_freightways.rb +10 -0
- data/lib/freight_kit/carriers/usa_truck.rb +28 -0
- data/lib/freight_kit/carriers/usf_holland.rb +11 -0
- data/lib/freight_kit/carriers/valley_cartage.rb +11 -0
- data/lib/freight_kit/carriers/vc_transport.rb +10 -0
- data/lib/freight_kit/carriers/vision_express.rb +11 -0
- data/lib/freight_kit/carriers/vision_logistics_group.rb +10 -0
- data/lib/freight_kit/carriers/vmg_transportation_group.rb +10 -0
- data/lib/freight_kit/carriers/volpe_express.rb +10 -0
- data/lib/freight_kit/carriers/ward_trucking.rb +29 -0
- data/lib/freight_kit/carriers/wdwb.rb +10 -0
- data/lib/freight_kit/carriers/western_flyer_express.rb +28 -0
- data/lib/freight_kit/carriers/western_regional_delivery_service.rb +271 -0
- data/lib/freight_kit/carriers/western_specialized_trucking.rb +22 -0
- data/lib/freight_kit/carriers/win_distribution.rb +28 -0
- data/lib/freight_kit/carriers/wlb_transport.rb +10 -0
- data/lib/freight_kit/carriers/x_trux.rb +29 -0
- data/lib/freight_kit/carriers/xpo_logistics.rb +427 -0
- data/lib/freight_kit/carriers/xpress_global_systems.rb +30 -0
- data/lib/freight_kit/carriers/xylo_trucking.rb +10 -0
- data/lib/freight_kit/carriers/yrc_freight.rb +24 -0
- data/lib/freight_kit/carriers/zentner_transportation.rb +28 -0
- data/lib/freight_kit/carriers.rb +331 -34
- data/lib/freight_kit/countries.rb +22 -0
- data/lib/freight_kit/error.rb +0 -2
- data/lib/freight_kit/errors/document_not_found_error.rb +0 -2
- data/lib/freight_kit/errors/expired_credentials_error.rb +0 -2
- data/lib/freight_kit/errors/http_error.rb +0 -2
- data/lib/freight_kit/errors/invalid_credentials_error.rb +0 -2
- data/lib/freight_kit/errors/response_error.rb +0 -2
- data/lib/freight_kit/errors/shipment_not_found_error.rb +0 -2
- data/lib/freight_kit/errors/unserviceable_accessorials_error.rb +2 -4
- data/lib/freight_kit/errors/unserviceable_error.rb +0 -2
- data/lib/freight_kit/helpers/documentable.rb +0 -2
- data/lib/freight_kit/helpers/pickupable.rb +3 -5
- data/lib/freight_kit/helpers/rateable.rb +0 -2
- data/lib/freight_kit/helpers/trackable.rb +0 -2
- data/lib/freight_kit/http_client/cache_store.rb +2 -4
- data/lib/freight_kit/http_client/log_device.rb +0 -2
- data/lib/freight_kit/http_client/response.rb +0 -2
- data/lib/freight_kit/http_client/revalidation.rb +0 -2
- data/lib/freight_kit/http_client/safe_retries.rb +0 -2
- data/lib/freight_kit/http_client/zstd.rb +2 -4
- data/lib/freight_kit/http_client.rb +8 -12
- data/lib/freight_kit/model.rb +1 -3
- data/lib/freight_kit/models/address.rb +15 -0
- data/lib/freight_kit/models/contact.rb +3 -4
- data/lib/freight_kit/models/country.rb +20 -0
- data/lib/freight_kit/models/credential.rb +14 -16
- data/lib/freight_kit/models/date_time.rb +0 -2
- data/lib/freight_kit/models/document_response.rb +0 -2
- data/lib/freight_kit/models/label.rb +0 -2
- data/lib/freight_kit/models/location.rb +10 -25
- data/lib/freight_kit/models/pickup_response.rb +0 -2
- data/lib/freight_kit/models/price.rb +0 -2
- data/lib/freight_kit/models/rate.rb +0 -2
- data/lib/freight_kit/models/rate_response.rb +0 -2
- data/lib/freight_kit/models/region.rb +19 -0
- data/lib/freight_kit/models/response.rb +0 -2
- data/lib/freight_kit/models/shipment.rb +4 -6
- data/lib/freight_kit/models/shipment_event.rb +0 -2
- data/lib/freight_kit/models/terminal.rb +10 -0
- data/lib/freight_kit/models/tracking_response.rb +0 -2
- data/lib/freight_kit/package.rb +51 -53
- data/lib/freight_kit/package_item.rb +14 -14
- data/lib/freight_kit/packaging.rb +21 -26
- data/lib/freight_kit/platform.rb +0 -32
- data/lib/freight_kit/platforms/carrier_logistics.rb +331 -345
- data/lib/freight_kit/platforms/next_tms.rb +93 -0
- data/lib/freight_kit/platforms/the_great_information_factory.rb +500 -425
- data/lib/freight_kit/regions.rb +27 -0
- data/lib/freight_kit/shipment_packer.rb +36 -38
- data/lib/freight_kit/tariff/overlength_rule.rb +1 -5
- data/lib/freight_kit/tariff.rb +0 -2
- data/lib/freight_kit.rb +84 -11
- metadata +361 -51
- data/configuration/carriers/abfs.yml +0 -124
- data/configuration/carriers/btvp.yml +0 -84
- data/configuration/carriers/ccyq.yml +0 -121
- data/configuration/carriers/clni.yml +0 -113
- data/configuration/carriers/cnwy.yml +0 -113
- data/configuration/carriers/ctbv.yml +0 -117
- data/configuration/carriers/dcha.yml +0 -105
- data/configuration/carriers/dlds.yml +0 -111
- data/configuration/carriers/dphe.yml +0 -130
- data/configuration/carriers/drrq.yml +0 -131
- data/configuration/carriers/fcsy.yml +0 -102
- data/configuration/carriers/fwda.yml +0 -137
- data/configuration/carriers/jfj_transportation.yml +0 -2
- data/configuration/carriers/mtvl.yml +0 -12
- data/configuration/carriers/numk.yml +0 -14
- data/configuration/carriers/otcl.yml +0 -124
- data/configuration/carriers/pens.yml +0 -22
- data/configuration/carriers/rdfs.yml +0 -142
- data/configuration/carriers/saia.yml +0 -129
- data/configuration/carriers/sefl.yml +0 -115
- data/configuration/carriers/totl.yml +0 -111
- data/configuration/carriers/tqyl.yml +0 -28
- data/configuration/carriers/wrds.yml +0 -20
- data/configuration/platforms/carrier_logistics.yml +0 -25
- data/configuration/platforms/next.yml +0 -12
- data/configuration/platforms/the_great_information_factory.yml +0 -122
- data/lib/freight_kit/carriers/abfs.rb +0 -421
- data/lib/freight_kit/carriers/btvp.rb +0 -29
- data/lib/freight_kit/carriers/ccyq.rb +0 -310
- data/lib/freight_kit/carriers/clni.rb +0 -396
- data/lib/freight_kit/carriers/cnwy.rb +0 -327
- data/lib/freight_kit/carriers/ctbv.rb +0 -53
- data/lib/freight_kit/carriers/dcha.rb +0 -76
- data/lib/freight_kit/carriers/dlds.rb +0 -49
- data/lib/freight_kit/carriers/dphe.rb +0 -472
- data/lib/freight_kit/carriers/drrq.rb +0 -580
- data/lib/freight_kit/carriers/fcsy.rb +0 -57
- data/lib/freight_kit/carriers/fwda.rb +0 -744
- data/lib/freight_kit/carriers/mtvl.rb +0 -34
- data/lib/freight_kit/carriers/numk.rb +0 -58
- data/lib/freight_kit/carriers/otcl.rb +0 -520
- data/lib/freight_kit/carriers/pens.rb +0 -204
- data/lib/freight_kit/carriers/rdfs.rb +0 -521
- data/lib/freight_kit/carriers/sefl.rb +0 -342
- data/lib/freight_kit/carriers/totl.rb +0 -172
- data/lib/freight_kit/carriers/tqyl.rb +0 -337
- data/lib/freight_kit/carriers/wrds.rb +0 -246
- data/lib/freight_kit/platforms/next.rb +0 -101
data/lib/freight_kit/carrier.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
1
|
module FreightKit
|
|
4
2
|
# Carrier is the abstract base class for all supported carriers.
|
|
5
3
|
#
|
|
@@ -7,7 +5,6 @@ module FreightKit
|
|
|
7
5
|
# implement all the methods that the carrier supports.
|
|
8
6
|
#
|
|
9
7
|
# @see #create_pickup
|
|
10
|
-
# @see #cancel_shipment
|
|
11
8
|
# @see #find_tracking_info
|
|
12
9
|
# @see #find_rates
|
|
13
10
|
#
|
|
@@ -16,32 +13,45 @@ module FreightKit
|
|
|
16
13
|
# @see #save_request
|
|
17
14
|
class Carrier
|
|
18
15
|
class << self
|
|
16
|
+
# Whether the carrier is a broker that hands shipments to other carriers.
|
|
17
|
+
# @return [Boolean]
|
|
18
|
+
def acts_as_broker? = false
|
|
19
|
+
|
|
19
20
|
# Whether bill of lading (BOL) requires tracking number at time of pickup.
|
|
20
21
|
# @return [Boolean]
|
|
21
|
-
def bol_requires_tracking_number?
|
|
22
|
-
false
|
|
23
|
-
end
|
|
22
|
+
def bol_requires_tracking_number? = false
|
|
24
23
|
|
|
25
|
-
# The
|
|
26
|
-
# @return [FreightKit::
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
# The carrier's addresses for mailing checks, so applications need not enter them for each customer.
|
|
25
|
+
# @return [Array<FreightKit::Address>]
|
|
26
|
+
def check_mailing_addresses = []
|
|
27
|
+
|
|
28
|
+
# Whether the carrier's bill of lading (BOL) and proof of delivery (POD) are the same document.
|
|
29
|
+
# @return [Boolean]
|
|
30
|
+
def consider_bol_and_pod_documents_same? = false
|
|
31
|
+
|
|
32
|
+
# The carrier's department contacts, so applications need not enter them for each customer.
|
|
33
|
+
# @return [Array<FreightKit::Contact>]
|
|
34
|
+
def contacts = []
|
|
35
|
+
|
|
36
|
+
# Whether {#create_pickup} is implemented.
|
|
37
|
+
# @return [Boolean]
|
|
38
|
+
def create_pickup_implemented? = implemented?(:create_pickup)
|
|
39
|
+
|
|
40
|
+
# Whether {#find_rates} is implemented.
|
|
41
|
+
# @return [Boolean]
|
|
42
|
+
def find_rates_implemented? = implemented?(:find_rates)
|
|
39
43
|
|
|
40
44
|
# Whether finding rates with declared value (thus insurance) is implemented.
|
|
41
45
|
# @return [Boolean]
|
|
42
|
-
def find_rates_with_declared_value?
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
def find_rates_with_declared_value? = false
|
|
47
|
+
|
|
48
|
+
# The carrier's main office, from its public FMCSA registration.
|
|
49
|
+
# @return [FreightKit::Address, nil]
|
|
50
|
+
def headquarters = nil
|
|
51
|
+
|
|
52
|
+
# The carrier's permanent UUID. Applications store it to refer to the carrier, so never change or reuse one.
|
|
53
|
+
# @return [String]
|
|
54
|
+
def id = nil
|
|
45
55
|
|
|
46
56
|
# Whether instance method is supported
|
|
47
57
|
# @return [Boolean]
|
|
@@ -51,53 +61,114 @@ module FreightKit
|
|
|
51
61
|
false
|
|
52
62
|
end
|
|
53
63
|
|
|
54
|
-
# The
|
|
55
|
-
#
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
# The carrier's registered legal name, with its entity suffix (e.g. "Saia Motor Freight Line LLC"), when known.
|
|
65
|
+
# {.name} is the name the carrier does business as.
|
|
66
|
+
# @return [String, nil]
|
|
67
|
+
def legal_name = nil
|
|
68
|
+
|
|
69
|
+
# The package's longest horizontal dimension (length or width), as a
|
|
70
|
+
# Measured::Length so comparisons stay unit-agnostic.
|
|
71
|
+
#
|
|
72
|
+
# @param package [FreightKit::Package]
|
|
73
|
+
# @return [Measured::Length]
|
|
74
|
+
def longest_dimension(package)
|
|
75
|
+
[
|
|
76
|
+
Measured::Length.new(package.length(:inches), :inches),
|
|
77
|
+
Measured::Length.new(package.width(:inches), :inches)
|
|
78
|
+
].max
|
|
58
79
|
end
|
|
59
80
|
|
|
81
|
+
# FreightKit accessorials the carrier prices, mapped to the carrier's codes.
|
|
82
|
+
# @return [Hash{Symbol => Object}]
|
|
83
|
+
def mappable_accessorials = {}
|
|
84
|
+
|
|
60
85
|
# The maximum height the carrier will accept.
|
|
61
86
|
# @return [Measured::Length]
|
|
62
|
-
def maximum_height
|
|
63
|
-
Measured::Length.new(105, :inches)
|
|
64
|
-
end
|
|
87
|
+
def maximum_height = Measured::Length.new(105, :inches)
|
|
65
88
|
|
|
66
89
|
# The maximum weight the carrier will accept.
|
|
67
90
|
# @return [Measured::Weight]
|
|
68
|
-
def maximum_weight
|
|
69
|
-
Measured::Weight.new(10_000, :pounds)
|
|
70
|
-
end
|
|
91
|
+
def maximum_weight = Measured::Weight.new(10_000, :pounds)
|
|
71
92
|
|
|
72
93
|
# What length overlength fees the carrier begins charging at.
|
|
73
94
|
# @return [Measured::Length]
|
|
74
|
-
def minimum_length_for_overlength_fees
|
|
75
|
-
|
|
95
|
+
def minimum_length_for_overlength_fees = Measured::Length.new(48, :inches)
|
|
96
|
+
|
|
97
|
+
# @param package [FreightKit::Package]
|
|
98
|
+
# @return [Boolean] whether the package is long enough to incur overlength fees.
|
|
99
|
+
def overlength?(package) = longest_dimension(package) >= minimum_length_for_overlength_fees
|
|
100
|
+
|
|
101
|
+
def overlength_fee(tariff, package)
|
|
102
|
+
overlength_rule = overlength_rule_for(tariff, package)
|
|
103
|
+
return 0 if overlength_rule.nil?
|
|
104
|
+
|
|
105
|
+
package.quantity * overlength_rule.fee_cents
|
|
76
106
|
end
|
|
77
107
|
|
|
78
108
|
# Whether or not the carrier quotes overlength fees via API.
|
|
79
109
|
# @note Should the API not calculate these fees, they should be calculated some other way outside of FreightKit.
|
|
80
110
|
# @return [Boolean]
|
|
81
|
-
def overlength_fees_require_tariff?
|
|
82
|
-
|
|
111
|
+
def overlength_fees_require_tariff? = true
|
|
112
|
+
|
|
113
|
+
# Returns the overlength rule from +tariff+ that applies to +package+, or
|
|
114
|
+
# +nil+ when the package is not overlength, or no configured rule covers it.
|
|
115
|
+
#
|
|
116
|
+
# This is the single source of truth for "does a rule cover this package?"
|
|
117
|
+
# shared by {#overlength_fee} and {#validate_packages} so the two can never
|
|
118
|
+
# disagree (e.g. a package quoting $0 overlength while also being treated as
|
|
119
|
+
# serviceable).
|
|
120
|
+
#
|
|
121
|
+
# @param tariff [FreightKit::Tariff, nil]
|
|
122
|
+
# @param package [FreightKit::Package]
|
|
123
|
+
# @return [FreightKit::Tariff::OverlengthRule, nil]
|
|
124
|
+
def overlength_rule_for(tariff, package)
|
|
125
|
+
return unless tariff.is_a?(FreightKit::Tariff) && overlength?(package)
|
|
126
|
+
|
|
127
|
+
tariff.overlength_rules.find { |overlength_rule| overlength_rule.cover?(longest_dimension(package)) }
|
|
83
128
|
end
|
|
84
129
|
|
|
85
130
|
# Whether carrier considers pickup number the same as the tracking number.
|
|
86
|
-
def pickup_number_is_tracking_number?
|
|
87
|
-
|
|
88
|
-
|
|
131
|
+
def pickup_number_is_tracking_number? = false
|
|
132
|
+
|
|
133
|
+
# Whether the rates the carrier's API returns include excessive length fees. Carriers without rates, or that need
|
|
134
|
+
# a tariff to price overlength fees, return rates without them.
|
|
135
|
+
# @return [Boolean]
|
|
136
|
+
def rates_with_excessive_length_fees? = find_rates_implemented? && requirements.exclude?(:tariff)
|
|
137
|
+
|
|
138
|
+
# Returns the `Credential` methods (passed to `#initialize`) that cannot respond with blank values.
|
|
139
|
+
# @return [Array<Symbol>]
|
|
140
|
+
def required_credential_types = []
|
|
89
141
|
|
|
90
142
|
# Returns the keywords passed to `#initialize` that cannot be blank.
|
|
91
143
|
# @return [Array<Symbol>]
|
|
92
|
-
def requirements
|
|
93
|
-
|
|
144
|
+
def requirements = []
|
|
145
|
+
|
|
146
|
+
# @return [String, nil]
|
|
147
|
+
def scac = nil
|
|
148
|
+
|
|
149
|
+
# Raises {UnserviceableAccessorialsError} for accessorials the carrier refuses, or that it neither maps nor serves
|
|
150
|
+
# unpriced. Returns false when the carrier maps no accessorials.
|
|
151
|
+
# @return [Boolean]
|
|
152
|
+
def serviceable_accessorials?(accessorials)
|
|
153
|
+
return true if accessorials.blank?
|
|
154
|
+
return false if mappable_accessorials.blank?
|
|
155
|
+
|
|
156
|
+
refused = accessorials.select do |accessorial|
|
|
157
|
+
unserviceable_accessorials.include?(accessorial) ||
|
|
158
|
+
(mappable_accessorials.keys.exclude?(accessorial) && unquotable_accessorials.exclude?(accessorial))
|
|
159
|
+
end
|
|
160
|
+
raise FreightKit::UnserviceableAccessorialsError.new(accessorials: refused) if refused.any?
|
|
161
|
+
|
|
162
|
+
true
|
|
94
163
|
end
|
|
95
164
|
|
|
96
|
-
#
|
|
165
|
+
# The services {#find_rates} quotes (e.g. `:standard`, `:guaranteed_delivery`).
|
|
97
166
|
# @return [Array<Symbol>]
|
|
98
|
-
def
|
|
99
|
-
|
|
100
|
-
|
|
167
|
+
def services = []
|
|
168
|
+
|
|
169
|
+
# The carrier's terminals, so applications need not enter them for each customer.
|
|
170
|
+
# @return [Array<FreightKit::Terminal>]
|
|
171
|
+
def terminals = []
|
|
101
172
|
|
|
102
173
|
# The template URL for tracking one of carrier's `NUMBERS` publicly. A template URL is a URL containing the token
|
|
103
174
|
# "%s" that can be replaced to generate a valid URL.
|
|
@@ -112,11 +183,29 @@ module FreightKit
|
|
|
112
183
|
# @raise [ArgumentError]
|
|
113
184
|
# @return [String, nil] The template URL or nil if no template is available for the given key.
|
|
114
185
|
def tracking_url_template(key)
|
|
115
|
-
raise ArgumentError, "key must be one of: #{NUMBERS.join(
|
|
186
|
+
raise ArgumentError, "key must be one of: #{NUMBERS.join(', ')}" if NUMBERS.exclude?(key)
|
|
116
187
|
|
|
117
|
-
|
|
188
|
+
tracking_url_templates[key]
|
|
118
189
|
end
|
|
119
190
|
|
|
191
|
+
# The template URLs for {.tracking_url_template}, by `NUMBERS` key.
|
|
192
|
+
# @return [Hash{Symbol => String}]
|
|
193
|
+
def tracking_url_templates = {}
|
|
194
|
+
|
|
195
|
+
# FreightKit accessorials the carrier serves but does not price.
|
|
196
|
+
# @return [Array<Symbol>]
|
|
197
|
+
def unquotable_accessorials = []
|
|
198
|
+
|
|
199
|
+
# FreightKit accessorials the carrier refuses.
|
|
200
|
+
# @return [Array<Symbol>]
|
|
201
|
+
def unserviceable_accessorials = []
|
|
202
|
+
|
|
203
|
+
# @return [Integer, nil]
|
|
204
|
+
def us_dot_number = nil
|
|
205
|
+
|
|
206
|
+
# @return [Integer, nil]
|
|
207
|
+
def us_mc_number = nil
|
|
208
|
+
|
|
120
209
|
# Regular expression to use for validating carrier's `NUMBERS`.
|
|
121
210
|
#
|
|
122
211
|
# Returns the regular expression used for validating the carrier's number based on the provided `key`.
|
|
@@ -125,30 +214,87 @@ module FreightKit
|
|
|
125
214
|
# @see `NUMBERS`
|
|
126
215
|
# @param [Symbol] key The symbol representing the carrier number type for which the regular expression is needed.
|
|
127
216
|
# @raise [ArgumentError] Raised if the provided key is not one of the specified carrier number types.
|
|
128
|
-
# @return [Regexp] The regular expression for validating the specified carrier number type.
|
|
217
|
+
# @return [Regexp, nil] The regular expression for validating the specified carrier number type.
|
|
129
218
|
def valid_number_regex(key)
|
|
130
|
-
raise ArgumentError, "key must be one of: #{NUMBERS.join(
|
|
219
|
+
raise ArgumentError, "key must be one of: #{NUMBERS.join(', ')}" if NUMBERS.exclude?(key)
|
|
131
220
|
|
|
132
|
-
|
|
221
|
+
valid_number_regexes[key]
|
|
133
222
|
end
|
|
134
|
-
end
|
|
135
223
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
224
|
+
# The regular expressions for {.valid_number_regex}, by `NUMBERS` key.
|
|
225
|
+
# @return [Hash{Symbol => Regexp}]
|
|
226
|
+
def valid_number_regexes = {}
|
|
227
|
+
|
|
228
|
+
# Determine whether the carrier will accept the packages based on credentials and/or tariff.
|
|
229
|
+
# @param packages [Array<FreightKit::Package>]
|
|
230
|
+
# @param tariff [FreightKit::Tariff]
|
|
231
|
+
# @return [Boolean]
|
|
232
|
+
def validate_packages(packages, tariff = nil)
|
|
233
|
+
return false if packages.blank?
|
|
234
|
+
|
|
235
|
+
message = []
|
|
236
|
+
|
|
237
|
+
max_height_inches = maximum_height.convert_to(:inches).value
|
|
238
|
+
if packages.map { |p| p.height(:inches) }.max > max_height_inches
|
|
239
|
+
message << "items must be #{max_height_inches.to_f} inches tall or less"
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
max_weight_pounds = maximum_weight.convert_to(:pounds).value
|
|
243
|
+
message << "items must weigh #{max_weight_pounds.to_f} lbs or less" if packages.sum { |p| p.pounds(:total) } > max_weight_pounds
|
|
244
|
+
|
|
245
|
+
# Carriers that don't quote overlength fees via their API rely on the
|
|
246
|
+
# tariff to price them. Fail closed rather than silently under-quoting: a
|
|
247
|
+
# missing, empty, or non-covering tariff for an overlength package must
|
|
248
|
+
# make the carrier unserviceable. We key off rule *coverage* (via
|
|
249
|
+
# #overlength_rule_for) rather than the tariff object's mere presence,
|
|
250
|
+
# because a present-but-empty FreightKit::Tariff is not `blank?` and would
|
|
251
|
+
# otherwise slip past this check.
|
|
252
|
+
if overlength_fees_require_tariff?
|
|
253
|
+
missing_dimensions = packages.any? do |package|
|
|
254
|
+
[package.height(:inches), package.length(:inches), package.width(:inches)].any?(&:zero?)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
uncovered_overlength = packages.any? do |package|
|
|
258
|
+
overlength?(package) && overlength_rule_for(tariff, package).nil?
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
if missing_dimensions
|
|
262
|
+
message << 'item dimensions are required'
|
|
263
|
+
elsif uncovered_overlength
|
|
264
|
+
message << 'tariff must be defined to calculate overlength fees'
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
raise UnserviceableError, message.join(', ').capitalize if message.present?
|
|
269
|
+
|
|
270
|
+
true
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# The carrier's homepage, verified to load over HTTPS and to name the carrier (e.g. "https://abf.com").
|
|
274
|
+
# @return [String, nil]
|
|
275
|
+
def website_url = nil
|
|
276
|
+
end
|
|
146
277
|
|
|
147
|
-
NUMBERS = %i[bol_number order_number pickup_number po_number tracking_number]
|
|
278
|
+
NUMBERS = %i[bol_number order_number pickup_number po_number tracking_number].freeze
|
|
148
279
|
|
|
149
|
-
attr_accessor :conf, :rates_with_excessive_length_fees, :tmpdir
|
|
150
280
|
attr_reader :credentials, :customer_location, :last_request, :tariff
|
|
151
281
|
|
|
282
|
+
delegate :id,
|
|
283
|
+
:longest_dimension,
|
|
284
|
+
:mappable_accessorials,
|
|
285
|
+
:name,
|
|
286
|
+
:overlength?,
|
|
287
|
+
:overlength_fee,
|
|
288
|
+
:overlength_rule_for,
|
|
289
|
+
:rates_with_excessive_length_fees?,
|
|
290
|
+
:scac,
|
|
291
|
+
:serviceable_accessorials?,
|
|
292
|
+
:unquotable_accessorials,
|
|
293
|
+
:unserviceable_accessorials,
|
|
294
|
+
:valid_number_regex,
|
|
295
|
+
:validate_packages,
|
|
296
|
+
to: :class
|
|
297
|
+
|
|
152
298
|
# @param credentials [Array<Credential>]
|
|
153
299
|
# @param customer_location [Location]
|
|
154
300
|
# @param tariff [Tariff]
|
|
@@ -156,14 +302,14 @@ module FreightKit
|
|
|
156
302
|
credentials = [credentials] if credentials.is_a?(Credential)
|
|
157
303
|
|
|
158
304
|
if credentials.map(&:class).uniq != [Credential]
|
|
159
|
-
message = "#{
|
|
305
|
+
message = "#{name}#new: `credentials` must be a Credential or Array of Credential"
|
|
160
306
|
raise ArgumentError, message
|
|
161
307
|
end
|
|
162
308
|
|
|
163
309
|
missing_credential_types = self.class.required_credential_types.uniq - credentials.map(&:type).uniq
|
|
164
310
|
|
|
165
311
|
if missing_credential_types.any?
|
|
166
|
-
message = "#{
|
|
312
|
+
message = "#{name}#new: `Credential` of type(s) missing: #{missing_credential_types.join(', ')}"
|
|
167
313
|
raise ArgumentError, message
|
|
168
314
|
end
|
|
169
315
|
|
|
@@ -171,38 +317,17 @@ module FreightKit
|
|
|
171
317
|
|
|
172
318
|
if customer_location.present?
|
|
173
319
|
unless customer_location.is_a?(Location)
|
|
174
|
-
message = "#{
|
|
320
|
+
message = "#{name}#new: `customer_location` must be a Location"
|
|
175
321
|
raise ArgumentError, message
|
|
176
322
|
end
|
|
177
323
|
|
|
178
324
|
@customer_location = customer_location
|
|
179
325
|
end
|
|
180
326
|
|
|
181
|
-
if tariff.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
@tariff = tariff
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
conf_path = File
|
|
188
|
-
.join(
|
|
189
|
-
File.expand_path(
|
|
190
|
-
'../../../../configuration/carriers',
|
|
191
|
-
self.class.const_source_location(:REACTIVE_FREIGHT_CARRIER).first,
|
|
192
|
-
),
|
|
193
|
-
"#{self.class.to_s.split("::")[1].underscore}.yml",
|
|
194
|
-
)
|
|
195
|
-
@conf = YAML.safe_load_file(conf_path, permitted_classes: [Symbol])
|
|
196
|
-
|
|
197
|
-
@rates_with_excessive_length_fees = @conf.dig(:attributes, :rates, :with_excessive_length_fees)
|
|
198
|
-
end
|
|
327
|
+
return if tariff.blank?
|
|
328
|
+
raise ArgumentError, "#{name}#new: `tariff` must be a Tariff" unless tariff.is_a?(Tariff)
|
|
199
329
|
|
|
200
|
-
|
|
201
|
-
#
|
|
202
|
-
# @param [String] tracking_number Tracking number.
|
|
203
|
-
# @return [DocumentResponse]
|
|
204
|
-
def pod(tracking_number)
|
|
205
|
-
raise NotImplementedError, "#{self.class.name}: #pod not supported"
|
|
330
|
+
@tariff = tariff
|
|
206
331
|
end
|
|
207
332
|
|
|
208
333
|
# Asks the carrier for the bill of lading that the carrier would provide before shipping.
|
|
@@ -211,46 +336,7 @@ module FreightKit
|
|
|
211
336
|
#
|
|
212
337
|
# @param [String] tracking_number Tracking number.
|
|
213
338
|
# @return [DocumentResponse]
|
|
214
|
-
def bol(tracking_number)
|
|
215
|
-
raise NotImplementedError, "#{self.class.name}: #bol not supported"
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
# Asks the carrier for the scanned bill of lading that the carrier would provide after shipping.
|
|
219
|
-
#
|
|
220
|
-
# @see #bol
|
|
221
|
-
#
|
|
222
|
-
# @param [String] tracking_number Tracking number.
|
|
223
|
-
# @return [DocumentResponse]
|
|
224
|
-
def scanned_bol(tracking_number)
|
|
225
|
-
raise NotImplementedError, "#{self.class.name}: #scanned_bol not supported"
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
def find_estimate(*)
|
|
229
|
-
raise NotImplementedError, "#{self.class.name}: #find_estimate not supported"
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
# Asks the carrier for a list of locations (terminals) for a given country
|
|
233
|
-
#
|
|
234
|
-
# @param [ActiveUtils::Country] country
|
|
235
|
-
# @return [Array<Location>]
|
|
236
|
-
def find_locations(country)
|
|
237
|
-
raise NotImplementedError, "#{self.class.name}: #find_locations not supported"
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
def find_tracking_number_from_pickup_number(pickup_number, date)
|
|
241
|
-
raise NotImplementedError, "#{self.class.name}: #find_tracking_number_from_pickup_number not supported"
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
# Asks the carrier for rate estimates for a given shipment.
|
|
245
|
-
#
|
|
246
|
-
# @note Override with whatever you need to get the rates from the carrier.
|
|
247
|
-
#
|
|
248
|
-
# @param shipment [FreightKit::Shipment] Shipment details.
|
|
249
|
-
# @return [FreightKit::RateResponse] The response from the carrier, which
|
|
250
|
-
# includes 0 or more rate estimates for different shipping products
|
|
251
|
-
def find_rates(shipment:)
|
|
252
|
-
raise NotImplementedError, "#find_rates is not supported by #{self.class.name}."
|
|
253
|
-
end
|
|
339
|
+
def bol(tracking_number) = raise NotImplementedError, "#{name}: #bol not supported"
|
|
254
340
|
|
|
255
341
|
# Registers a new pickup with the carrier, to get a tracking number and
|
|
256
342
|
# potentially shipping labels
|
|
@@ -283,19 +369,29 @@ module FreightKit
|
|
|
283
369
|
service:,
|
|
284
370
|
shipment:
|
|
285
371
|
)
|
|
286
|
-
raise NotImplementedError, "#create_pickup is not supported by #{
|
|
372
|
+
raise NotImplementedError, "#create_pickup is not supported by #{name}."
|
|
287
373
|
end
|
|
288
374
|
|
|
289
|
-
#
|
|
375
|
+
# Fetch credential of given type.
|
|
290
376
|
#
|
|
291
|
-
# @
|
|
377
|
+
# @param type [Symbol] Type of credential to find, should be one of: `:api`, `:selenoid`, `:website`.
|
|
378
|
+
# @return [FreightKit::Credential|NilClass]
|
|
379
|
+
def fetch_credential(type) = credentials.find { |credential| credential.type == type }
|
|
380
|
+
|
|
381
|
+
# Asks the carrier for a list of locations (terminals) for a given country
|
|
292
382
|
#
|
|
293
|
-
# @param
|
|
294
|
-
# @return [
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
383
|
+
# @param [ActiveUtils::Country] country
|
|
384
|
+
# @return [Array<Location>]
|
|
385
|
+
def find_locations(country) = raise NotImplementedError, "#{name}: #find_locations not supported"
|
|
386
|
+
|
|
387
|
+
# Asks the carrier for rate estimates for a given shipment.
|
|
388
|
+
#
|
|
389
|
+
# @note Override with whatever you need to get the rates from the carrier.
|
|
390
|
+
#
|
|
391
|
+
# @param shipment [FreightKit::Shipment] Shipment details.
|
|
392
|
+
# @return [FreightKit::RateResponse] The response from the carrier, which
|
|
393
|
+
# includes 0 or more rate estimates for different shipping products
|
|
394
|
+
def find_rates(shipment:) = raise NotImplementedError, "#find_rates is not supported by #{name}."
|
|
299
395
|
|
|
300
396
|
# Retrieves tracking information for a previous shipment
|
|
301
397
|
#
|
|
@@ -305,189 +401,40 @@ module FreightKit
|
|
|
305
401
|
# @return [FreightKit::TrackingResponse] The response from the carrier. This
|
|
306
402
|
# response should a list of shipment tracking events if successful.
|
|
307
403
|
def find_tracking_info(tracking_number)
|
|
308
|
-
raise NotImplementedError, "#find_tracking_info is not supported by #{
|
|
404
|
+
raise NotImplementedError, "#find_tracking_info is not supported by #{name}."
|
|
309
405
|
end
|
|
310
406
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
# @param origin [Location] The origin location.
|
|
314
|
-
# @param destination [Location] The destination location.
|
|
315
|
-
# @return [Array<Symbol>] A list of service type symbols for the available services.
|
|
316
|
-
#
|
|
317
|
-
def available_services(origin, destination)
|
|
318
|
-
raise NotImplementedError, "#available_services is not supported by #{self.class.name}."
|
|
407
|
+
def find_tracking_number_from_pickup_number(pickup_number, date)
|
|
408
|
+
raise NotImplementedError, "#{name}: #find_tracking_number_from_pickup_number not supported"
|
|
319
409
|
end
|
|
320
410
|
|
|
321
|
-
#
|
|
411
|
+
# Asks the carrier for the scanned proof of delivery that the carrier would provide after delivery.
|
|
322
412
|
#
|
|
323
|
-
# @param
|
|
324
|
-
# @return [
|
|
325
|
-
def
|
|
326
|
-
@fetch_credentials ||= {}
|
|
327
|
-
return @fetch_credentials[type] if @fetch_credentials[type].present?
|
|
328
|
-
|
|
329
|
-
@fetch_credentials[type] ||= credentials.find { |credential| credential.type == type }
|
|
330
|
-
end
|
|
413
|
+
# @param [String] tracking_number Tracking number.
|
|
414
|
+
# @return [DocumentResponse]
|
|
415
|
+
def pod(tracking_number) = raise NotImplementedError, "#{name}: #pod not supported"
|
|
331
416
|
|
|
332
|
-
#
|
|
417
|
+
# Asks the carrier for the scanned bill of lading that the carrier would provide after shipping.
|
|
333
418
|
#
|
|
334
|
-
#
|
|
335
|
-
# the carrier's default_location. Override to provide alternate functionality.
|
|
419
|
+
# @see #bol
|
|
336
420
|
#
|
|
337
|
-
# @
|
|
338
|
-
#
|
|
339
|
-
def
|
|
340
|
-
location = self.class.default_location
|
|
341
|
-
find_rates(location, location, Package.new(100, [5, 15, 30]))
|
|
342
|
-
rescue FreightKit::ResponseError
|
|
343
|
-
false
|
|
344
|
-
else
|
|
345
|
-
true
|
|
346
|
-
end
|
|
421
|
+
# @param [String] tracking_number Tracking number.
|
|
422
|
+
# @return [DocumentResponse]
|
|
423
|
+
def scanned_bol(tracking_number) = raise NotImplementedError, "#{name}: #scanned_bol not supported"
|
|
347
424
|
|
|
348
425
|
# Validate the tracking number (may call API).
|
|
349
426
|
#
|
|
350
427
|
# @param [String] tracking_number Tracking number.
|
|
351
428
|
# @return [Boolean] Should return `true` if the provided pro is valid.
|
|
352
429
|
def valid_tracking_number?(tracking_number)
|
|
353
|
-
raise NotImplementedError, "#
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
# The package's longest horizontal dimension (length or width), as a
|
|
357
|
-
# Measured::Length so comparisons stay unit-agnostic.
|
|
358
|
-
#
|
|
359
|
-
# @param package [FreightKit::Package]
|
|
360
|
-
# @return [Measured::Length]
|
|
361
|
-
def longest_dimension(package)
|
|
362
|
-
[
|
|
363
|
-
Measured::Length.new(package.length(:inches), :inches),
|
|
364
|
-
Measured::Length.new(package.width(:inches), :inches),
|
|
365
|
-
].max
|
|
366
|
-
end
|
|
367
|
-
|
|
368
|
-
# @param package [FreightKit::Package]
|
|
369
|
-
# @return [Boolean] whether the package is long enough to incur overlength fees.
|
|
370
|
-
def overlength?(package) = longest_dimension(package) >= self.class.minimum_length_for_overlength_fees
|
|
371
|
-
|
|
372
|
-
def overlength_fee(tariff, package)
|
|
373
|
-
overlength_rule = overlength_rule_for(tariff, package)
|
|
374
|
-
return 0 if overlength_rule.nil?
|
|
375
|
-
|
|
376
|
-
package.quantity * overlength_rule.fee_cents
|
|
377
|
-
end
|
|
378
|
-
|
|
379
|
-
# Returns the overlength rule from +tariff+ that applies to +package+, or
|
|
380
|
-
# +nil+ when the package is not overlength, or no configured rule covers it.
|
|
381
|
-
#
|
|
382
|
-
# This is the single source of truth for "does a rule cover this package?"
|
|
383
|
-
# shared by {#overlength_fee} and {#validate_packages} so the two can never
|
|
384
|
-
# disagree (e.g. a package quoting $0 overlength while also being treated as
|
|
385
|
-
# serviceable).
|
|
386
|
-
#
|
|
387
|
-
# @param tariff [FreightKit::Tariff, nil]
|
|
388
|
-
# @param package [FreightKit::Package]
|
|
389
|
-
# @return [FreightKit::Tariff::OverlengthRule, nil]
|
|
390
|
-
def overlength_rule_for(tariff, package)
|
|
391
|
-
return unless tariff.is_a?(FreightKit::Tariff) && overlength?(package)
|
|
392
|
-
|
|
393
|
-
tariff.overlength_rules.find { |overlength_rule| overlength_rule.cover?(longest_dimension(package)) }
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
# Determine whether the carrier will accept the packages based on credentials and/or tariff.
|
|
397
|
-
# @param packages [Array<FreightKit::Package>]
|
|
398
|
-
# @param tariff [FreightKit::Tariff]
|
|
399
|
-
# @return [Boolean]
|
|
400
|
-
def validate_packages(packages, tariff = nil)
|
|
401
|
-
return false if packages.blank?
|
|
402
|
-
|
|
403
|
-
message = []
|
|
404
|
-
|
|
405
|
-
max_height_inches = self.class.maximum_height.convert_to(:inches).value
|
|
406
|
-
if packages.map { |p| p.height(:inches) }.max > max_height_inches
|
|
407
|
-
message << "items must be #{max_height_inches.to_f} inches tall or less"
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
max_weight_pounds = self.class.maximum_weight.convert_to(:pounds).value
|
|
411
|
-
if packages.sum { |p| p.pounds(:total) } > max_weight_pounds
|
|
412
|
-
message << "items must weigh #{max_weight_pounds.to_f} lbs or less"
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
# Carriers that don't quote overlength fees via their API rely on the
|
|
416
|
-
# tariff to price them. Fail closed rather than silently under-quoting: a
|
|
417
|
-
# missing, empty, or non-covering tariff for an overlength package must
|
|
418
|
-
# make the carrier unserviceable. We key off rule *coverage* (via
|
|
419
|
-
# #overlength_rule_for) rather than the tariff object's mere presence,
|
|
420
|
-
# because a present-but-empty FreightKit::Tariff is not `blank?` and would
|
|
421
|
-
# otherwise slip past this check.
|
|
422
|
-
if self.class.overlength_fees_require_tariff?
|
|
423
|
-
missing_dimensions = packages.any? do |package|
|
|
424
|
-
[
|
|
425
|
-
package.height(:inches),
|
|
426
|
-
package.length(:inches),
|
|
427
|
-
package.width(:inches),
|
|
428
|
-
].any?(&:zero?)
|
|
429
|
-
end
|
|
430
|
-
|
|
431
|
-
uncovered_overlength = packages.any? do |package|
|
|
432
|
-
overlength?(package) && overlength_rule_for(tariff, package).nil?
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
if missing_dimensions
|
|
436
|
-
message << 'item dimensions are required'
|
|
437
|
-
elsif uncovered_overlength
|
|
438
|
-
message << 'tariff must be defined to calculate overlength fees'
|
|
439
|
-
end
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
raise UnserviceableError, message.join(', ').capitalize if message.present?
|
|
443
|
-
|
|
444
|
-
true
|
|
445
|
-
end
|
|
446
|
-
|
|
447
|
-
def serviceable_accessorials?(accessorials)
|
|
448
|
-
return true if accessorials.blank?
|
|
449
|
-
|
|
450
|
-
unless self.class::REACTIVE_FREIGHT_CARRIER
|
|
451
|
-
raise NotImplementedError, "#{self.class.name}: #serviceable_accessorials? not supported"
|
|
452
|
-
end
|
|
453
|
-
|
|
454
|
-
return false if @conf.dig(:accessorials, :mappable).blank?
|
|
455
|
-
|
|
456
|
-
conf_mappable_accessorials = @conf.dig(:accessorials, :mappable)
|
|
457
|
-
conf_unquotable_accessorials = @conf.dig(:accessorials, :unquotable)
|
|
458
|
-
conf_unserviceable_accessorials = @conf.dig(:accessorials, :unserviceable)
|
|
459
|
-
|
|
460
|
-
unserviceable_accessorials = []
|
|
461
|
-
|
|
462
|
-
accessorials.each do |accessorial|
|
|
463
|
-
if conf_unserviceable_accessorials.present? && conf_unserviceable_accessorials.any?(accessorial)
|
|
464
|
-
unserviceable_accessorials << accessorial
|
|
465
|
-
next
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
next if conf_mappable_accessorials.present? && conf_mappable_accessorials.keys.any?(accessorial)
|
|
469
|
-
next if conf_unquotable_accessorials.present? && conf_unquotable_accessorials.any?(accessorial)
|
|
470
|
-
|
|
471
|
-
unserviceable_accessorials << accessorial
|
|
472
|
-
end
|
|
473
|
-
|
|
474
|
-
if unserviceable_accessorials.present?
|
|
475
|
-
raise FreightKit::UnserviceableAccessorialsError.new(accessorials: unserviceable_accessorials)
|
|
476
|
-
end
|
|
477
|
-
|
|
478
|
-
true
|
|
430
|
+
raise NotImplementedError, "#valid_tracking_number? is not supported by #{name}."
|
|
479
431
|
end
|
|
480
432
|
|
|
481
433
|
protected
|
|
482
434
|
|
|
483
|
-
include ActiveUtils::RequiresParameters
|
|
484
|
-
include ActiveUtils::PostsData
|
|
485
|
-
|
|
486
435
|
# Use after building the request to save for later inspection.
|
|
487
436
|
# @return [void]
|
|
488
|
-
def save_request(request)
|
|
489
|
-
@last_request = request
|
|
490
|
-
end
|
|
437
|
+
def save_request(request) = @last_request = request
|
|
491
438
|
|
|
492
439
|
# Calculates a timestamp that corresponds a given number of business days in the future
|
|
493
440
|
#
|