Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kelly/Meighan #17

Open
wants to merge 18 commits into
base: fiona/master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@
*.DS_Store
*.keep
coverage

/spec/vcr/*.yml
2 changes: 2 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--color
--require spec_helper
9 changes: 9 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ gem 'sdoc', '~> 0.4.0', group: :doc

gem 'pg'

gem 'active_shipping'

gem 'rails_12factor', group: :production

# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

Expand All @@ -41,6 +45,11 @@ group :development, :test do
gem 'sqlite3'
gem 'pry-rails'
gem 'factory_girl_rails'
gem 'vcr'
end

group :test do
gem 'webmock'
end

group :development do
Expand Down
28 changes: 28 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ GEM
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
active_shipping (1.6.5)
active_utils (~> 3.2.0)
activesupport (>= 3.2, < 5.0.0)
nokogiri (>= 1.6)
quantified (~> 1.0.1)
active_utils (3.2.0)
activesupport (>= 3.2)
i18n
activejob (4.2.5)
activesupport (= 4.2.5)
globalid (>= 0.3.0)
Expand All @@ -36,6 +44,7 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.4.0)
arel (6.0.3)
better_errors (2.1.1)
coderay (>= 1.0.0)
Expand All @@ -54,6 +63,8 @@ GEM
execjs
coffee-script-source (1.10.0)
concurrent-ruby (1.0.0)
crack (0.4.3)
safe_yaml (~> 1.0.0)
debug_inspector (0.0.2)
diff-lcs (1.2.5)
docile (1.1.5)
Expand All @@ -70,6 +81,7 @@ GEM
railties (>= 3.0.0)
globalid (0.3.6)
activesupport (>= 4.1.0)
hashdiff (0.2.3)
i18n (0.7.0)
jbuilder (2.4.0)
activesupport (>= 3.0.0, < 5.1)
Expand Down Expand Up @@ -97,6 +109,7 @@ GEM
slop (~> 3.4)
pry-rails (0.3.4)
pry (>= 0.9.10)
quantified (1.0.1)
rack (1.6.4)
rack-test (0.6.3)
rack (>= 1.0)
Expand All @@ -119,6 +132,11 @@ GEM
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.2)
loofah (~> 2.0)
rails_12factor (0.0.3)
rails_serve_static_assets
rails_stdout_logging
rails_serve_static_assets (0.0.4)
rails_stdout_logging (0.0.4)
railties (4.2.5)
actionpack (= 4.2.5)
activesupport (= 4.2.5)
Expand All @@ -144,6 +162,7 @@ GEM
rspec-mocks (~> 3.4.0)
rspec-support (~> 3.4.0)
rspec-support (3.4.1)
safe_yaml (1.0.4)
sass (3.4.21)
sass-rails (5.0.4)
railties (>= 4.0.0, < 5.0)
Expand Down Expand Up @@ -179,16 +198,22 @@ GEM
uglifier (2.7.2)
execjs (>= 0.3.0)
json (>= 1.8.0)
vcr (3.0.1)
web-console (2.2.1)
activemodel (>= 4.0)
binding_of_caller (>= 0.7.2)
railties (>= 4.0)
sprockets-rails (>= 2.0, < 4.0)
webmock (1.22.6)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff

PLATFORMS
ruby

DEPENDENCIES
active_shipping
better_errors
binding_of_caller
byebug
Expand All @@ -200,6 +225,7 @@ DEPENDENCIES
pg
pry-rails
rails (= 4.2.5)
rails_12factor
rspec-rails
sass-rails (~> 5.0)
sdoc (~> 0.4.0)
Expand All @@ -208,7 +234,9 @@ DEPENDENCIES
sqlite3
turbolinks
uglifier (>= 1.3.0)
vcr
web-console (~> 2.0)
webmock

BUNDLED WITH
1.11.2
3 changes: 3 additions & 0 deletions app/assets/javascripts/estimates.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
3 changes: 3 additions & 0 deletions app/assets/stylesheets/estimates.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Place all the styles related to the estimates controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
84 changes: 84 additions & 0 deletions app/controllers/estimates_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
require 'active_shipping'
require './lib/ups_services'

class EstimatesController < ApplicationController
# create constants for origin object, package grams_or_ounces and package dimensions, and country
# also create carrier constants which is a ups carrier and a fedex carrier?
UPS = ActiveShipping::UPS.new(login: ENV['UPS_LOGIN'], password: ENV['UPS_PASSWORD'], key: ENV['UPS_KEY'])

USPS = ActiveShipping::USPS.new(login: ENV['USPS_LOGIN'])

# assume all packages are being sent within the US
COUNTRY = "US"
# assume all packages are originating from Ada's betsy distribution center
ORIGIN = ActiveShipping::Location.new(country: COUNTRY, state: 'WA', city: 'Seattle', zip: '98101')
# assume all packages have the same ounces and dimensions, for now
OUNCES = 120
DIMENSIONS = [15, 10, 4.5]

def estimate
# only one package for all products in order, for now
package = [ActiveShipping::Package.new(OUNCES, DIMENSIONS, units: :imperial, value: params[:value])]
# destination address info comes from query params provided from betsy app's API call
destination = ActiveShipping::Location.new(country: COUNTRY, state: params[:destination][:state], city: params[:destination][:city], zip: params[:destination][:zip])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It helps readability to put each on its own line.

destination = ActiveShipping::Location.new(
  country: COUNTRY, 
  state:   params[:destination][:state], 
  city:    params[:destination][:city], 
  zip:     params[:destination][:zip]
)

# method call
begin
ups_estimates = UpsServices.transform_codes_into_names(get_ups_estimates(ORIGIN, destination, package))
rescue
return render :json => [], :status => :bad_request
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice to log the errors so that bad requests can easily be fixed.

end
# method call
begin
usps_estimates = get_usps_estimates(ORIGIN, destination, package)
rescue
return render :json => [], :status => :bad_request
end
# response includes rates and dates from both UPS and USPS
response = {"UPS Service Options" => ups_estimates, "USPS Service Options" => usps_estimates }
render :json => response.as_json, :status => :ok
end

private

def get_ups_estimates(origin, destination, package)
rates_response = UPS.find_rates(ORIGIN, destination, package)
delivery_dates_response = UPS.get_delivery_date_estimates(ORIGIN, destination, package)
# shipping_estimate will be a hash made up of service_code keys
# each key points to a hash which contains the cost and delivery date estimate
# for the corresponding service type.
shipping_estimate = Hash.new
rates_response.rates.each do |rate|
# skip this rate if service code is nil
next if rate.service_code.nil?
# otherwise, create a key for the corresponding service code
# the value is a hash containing the corresponding cost
shipping_estimate["#{rate.service_code}"] = { "cost" => "#{rate.total_price}" }
end
delivery_dates_response.delivery_estimates.each do |estimate|
# skip this estimate if service code is nil
next if estimate.service_code.nil?
# otherwise check to see if the service code already exists in the hash
if shipping_estimate["#{estimate.service_code}"].nil?
# if the service code doesn't yet exist in the hash, create a key for it
# with the value being a hash corresponding to the date
shipping_estimate["#{estimate.service_code}"] = { "date" => "#{estimate.date}" }
else
# if it already exists, merge the date corresponding to this estimate into the the
# hash associated with this service code key
shipping_estimate["#{estimate.service_code}"].merge!({ "date" => "#{estimate.date}"})
end
end
return shipping_estimate
end

def get_usps_estimates(origin, destination, package)
rates_response = USPS.find_rates(ORIGIN, destination, package)
usps_rates = rates_response.rates
shipping_estimate = Hash.new
usps_rates.each do |rate|
next if rate.service_name.nil?
shipping_estimate["#{rate.service_name}"] = { "cost" => "#{rate.price}", "date" => "#{rate.delivery_date}"}
end
return shipping_estimate
end
end
2 changes: 2 additions & 0 deletions app/helpers/estimates_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module EstimatesHelper
end
1 change: 1 addition & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
require "action_mailer/railtie"
require "action_view/railtie"
require "sprockets/railtie"
# require "dotenv"
# require "rails/test_unit/railtie"

# Require the gems listed in Gemfile, including any gems
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
get '/' => 'estimates#estimate'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".

Expand Down
16 changes: 16 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 0) do

end
29 changes: 29 additions & 0 deletions lib/ups_services.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class UpsServices
SERVICES = {
"01" => "UPS Next Day Air",
"02" => "UPS Second Day Air",
"03" => "UPS Ground",
"07" => "UPS Worldwide Express",
"08" => "UPS Worldwide Expedited",
"11" => "UPS Standard",
"12" => "UPS Three-Day Select",
"13" => "UPS Next Day Air Saver",
"14" => "UPS Next Day Air Early A.M.",
"54" => "UPS Worldwide Express Plus",
"59" => "UPS Second Day Air A.M.",
"65" => "UPS Saver",
"82" => "UPS Today Standard",
"83" => "UPS Today Dedicated Courier",
"84" => "UPS Today Intercity",
"85" => "UPS Today Express",
"86" => "UPS Today Express Saver"
}

def self.transform_codes_into_names(hash)
mappings = Hash.new
hash.keys.each do |key|
mappings[key] = SERVICES[key]
end
Hash[hash.map {|k, v| [mappings[k], v] }]
end
end
34 changes: 34 additions & 0 deletions spec/controllers/estimates_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require 'rails_helper'
require 'support/vcr_setup'

RSpec.describe EstimatesController, type: :controller do
let!(:package) do
{
value: 2000
}
end

let!(:destination) do
{
destination: {
state: "CA",
city: "San Francisco",
zip: 94104
}
}
end

describe "GET 'estimate'" do

it "is successful", :vcr do
get :estimate, destination.merge(package)
expect(response.response_code).to eq 200
end

# describe 'get_usps_estimates' do
# it 'returns a hash with service names and cost' do
# expect(response.body).to eq ""
# end
# end
end
end
15 changes: 15 additions & 0 deletions spec/helpers/estimates_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require 'rails_helper'

# Specs in this file have access to a helper object that includes
# the EstimatesHelper. For example:
#
# describe EstimatesHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe EstimatesHelper, type: :helper do
# pending "add some examples to (or delete) #{__FILE__}"
end
Loading