From d0fc9ac8986d28a6dbb3874aa78dcc1b8c4169bc Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Feb 2015 10:35:55 -0500 Subject: [PATCH 01/37] configuration tweaks, daemonize unicorn, makefile for easy restarting, unicorn config for logging and pid file --- Makefile | 7 +++++++ Procfile | 2 +- config/database.yml | 15 ++++++++++----- config/unicorn.rb | 7 +++++++ 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..91758d01 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +all: + bundle exec foreman start + + +restart: + cat tmp/unicorn.pid | xargs kill -QUIT ; + make diff --git a/Procfile b/Procfile index 9c823741..b7578160 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb +web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb -D diff --git a/config/database.yml b/config/database.yml index d151f711..5edb538e 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,7 +1,9 @@ development: adapter: postgresql database: <%= ENV['APP_NAME'].to_s + '_dev' %> - host: localhost + host: <%= ENV['DATABASE_HOST'] %> + username: <%= ENV['DATABASE_USERNAME'] %> + password: <%= ENV['DATABASE_PASSWORD'] %> # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". @@ -9,11 +11,14 @@ development: test: adapter: postgresql database: <%= ENV['APP_NAME'].to_s + '_test' %> - host: localhost + host: <%= ENV['DATABASE_HOST'] %> + username: <%= ENV['DATABASE_USERNAME'] %> + password: <%= ENV['DATABASE_PASSWORD'] %> production: adapter: postgresql database: <%= ENV['APP_NAME'] %> - host: localhost - username: <%= ENV['PRODUCTION_DATABASE_USERNAME'] %> - password: <%= ENV['PRODUCTION_DATABASE_PASSWORD'] %> + host: <%= ENV['DATABASE_HOST'] %> + username: <%= ENV['DATABASE_USERNAME'] %> + password: <%= ENV['DATABASE_PASSWORD'] %> + diff --git a/config/unicorn.rb b/config/unicorn.rb index cf8dea9e..39849355 100644 --- a/config/unicorn.rb +++ b/config/unicorn.rb @@ -3,6 +3,13 @@ timeout Integer(ENV['WEB_TIMEOUT'] || 30) preload_app true +APP_ROOT = File.expand_path("../..", __FILE__) +stdout_path "#{APP_ROOT}/log/unicorn.log" +stderr_path "#{APP_ROOT}/log/unicorn.log" +pid "#{APP_ROOT}/tmp/unicorn.pid" + + + before_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn master intercepting TERM and sending myself QUIT instead' From e1406a41031e2a1bed630dea833a9f74c572a83b Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Feb 2015 10:37:58 -0500 Subject: [PATCH 02/37] make command for tail -f unicorn logs --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 91758d01..20b84cbc 100644 --- a/Makefile +++ b/Makefile @@ -5,3 +5,6 @@ all: restart: cat tmp/unicorn.pid | xargs kill -QUIT ; make + +logs: + tail -f log/unicorn.log; From e421076f23d1c121ebdbf9ecf2828dc2020eb74a Mon Sep 17 00:00:00 2001 From: root Date: Fri, 20 Feb 2015 13:32:33 -0500 Subject: [PATCH 03/37] stuff needed to get running in production mode --- Gemfile | 2 +- Gemfile.lock | 2 +- Makefile | 7 ++++--- config/environments/production.rb | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index cb3243ef..8b62c607 100644 --- a/Gemfile +++ b/Gemfile @@ -13,7 +13,7 @@ gem 'nokogiri' gem 'friendly_id', '~> 4.0.9' gem 'iso_country_codes' gem 'paperclip', '~> 3.0' -gem 'ckeditor' +gem 'ckeditor', '4.0.4' gem 'aws-sdk' gem 'active_model_serializers' gem 'momentjs-rails' diff --git a/Gemfile.lock b/Gemfile.lock index e56ab3ff..4f66b88e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -249,7 +249,7 @@ DEPENDENCIES aws-sdk bootstrap-sass (= 2.1) capybara - ckeditor + ckeditor (= 4.0.4) coffee-rails (~> 3.2.1) crowdtilt! devise (~> 3.2.0) diff --git a/Makefile b/Makefile index 20b84cbc..ab1a68cb 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ all: - bundle exec foreman start + RAILS_ENV=production bundle exec foreman start; +stop: + cat tmp/unicorn.pid | xargs kill -QUIT ; restart: - cat tmp/unicorn.pid | xargs kill -QUIT ; - make + make stop; make; logs: tail -f log/unicorn.log; diff --git a/config/environments/production.rb b/config/environments/production.rb index 67d1ac9d..a058a6b4 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -28,7 +28,7 @@ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - config.force_ssl = true +# config.force_ssl = true # See everything in the log (default is :info) # config.log_level = :debug From 3da73c5d0a7eab38152f6b28cdc720106591643a Mon Sep 17 00:00:00 2001 From: Ken Koch Date: Fri, 20 Feb 2015 16:44:30 -0500 Subject: [PATCH 04/37] basic foundation for a referral system --- app/controllers/pages_controller.rb | 5 +++ app/mixins/checkout_mixin.rb | 3 ++ app/models/payment.rb | 3 +- app/models/user.rb | 3 +- app/views/campaigns/checkout_payment.html.erb | 1 + app/views/devise/registrations/edit.html.erb | 9 +++++ app/views/devise/registrations/new.html.erb | 2 +- app/views/theme/views/_footer.html.erb | 8 ++++ config/routes.rb | 3 ++ ...20150220200526_add_referral_id_to_users.rb | 37 +++++++++++++++++++ ...220213450_add_referral_code_to_payments.rb | 5 +++ db/schema.rb | 6 ++- 12 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 db/migrate/20150220200526_add_referral_id_to_users.rb create mode 100644 db/migrate/20150220213450_add_referral_code_to_payments.rb diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 904e9033..0a910b5c 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -2,6 +2,11 @@ class PagesController < ApplicationController before_filter :check_init def index + # Check for referral code + if request[:referral_code] + cookies[:referral_code] = request[:referral_code] + end + if @settings.default_campaign && ((user_signed_in? && current_user.admin?) || @settings.default_campaign.published_flag) redirect_to campaign_home_url(@settings.default_campaign) else diff --git a/app/mixins/checkout_mixin.rb b/app/mixins/checkout_mixin.rb index f2e242cd..aa2366a6 100644 --- a/app/mixins/checkout_mixin.rb +++ b/app/mixins/checkout_mixin.rb @@ -21,6 +21,9 @@ def basic_payment_info(params) billing_postal_code: params[:billing_postal_code], quantity: params[:quantity].to_i, + #Referral + referred_by: params[:referred_by], + #Shipping Info address_one: params.has_key?(:address_one) ? params[:address_one] : '', address_two: params.has_key?(:address_two) ? params[:address_two] : '', diff --git a/app/models/payment.rb b/app/models/payment.rb index 7cec8d77..83b77123 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -5,7 +5,8 @@ class Payment < ActiveRecord::Base :additional_info, :client_timestamp, :ct_charge_request_id, :ct_charge_request_error_id, :ct_tokenize_request_id, :ct_tokenize_request_error_id, - :ct_user_id + :ct_user_id, + :referred_by validates :fullname, :quantity, presence: true validates :email, presence: true, email: true diff --git a/app/models/user.rb b/app/models/user.rb index dfe1d134..f6241e0d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -6,10 +6,9 @@ class User < ActiveRecord::Base # Setup accessible (or protected) attributes for your model attr_accessible :email, :password, :password_confirmation, :remember_me, :fullname, - :wants_admin_payment_notification + :wants_admin_payment_notification, :referred_by # Validate presence of user inputs. # (most in this model are handled by Devise -- email, password, and password_confirmation) validates :fullname, presence: true - end diff --git a/app/views/campaigns/checkout_payment.html.erb b/app/views/campaigns/checkout_payment.html.erb index dd47c24a..95ccd48c 100644 --- a/app/views/campaigns/checkout_payment.html.erb +++ b/app/views/campaigns/checkout_payment.html.erb @@ -8,6 +8,7 @@
+

Contact Information

diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 2018bc9d..9a417ae3 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -7,6 +7,15 @@ +
+

+ Your Referral Link:

+ <% link = request.protocol + request.host_with_port + "/u/" + current_user.referral_code %> + <%= link %> +

+
+ + <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %> <%= devise_error_messages! %> diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index d7999352..b518230d 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -12,7 +12,7 @@ <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %> <%= devise_error_messages! %> - + <%= f.hidden_field :referred_by, :value => cookies[:referral_code] %>
<%= f.label :fullname, "Full Name" %> <%= f.text_field :fullname, :autofocus => true %>
diff --git a/app/views/theme/views/_footer.html.erb b/app/views/theme/views/_footer.html.erb index 26278d11..3255d40b 100644 --- a/app/views/theme/views/_footer.html.erb +++ b/app/views/theme/views/_footer.html.erb @@ -1,5 +1,13 @@ diff --git a/config/routes.rb b/config/routes.rb index e1b04900..14ae49cf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,6 +2,9 @@ mount Ckeditor::Engine => '/ckeditor' + # REFERRAL LINKS + match '/u/:referral_code', to: 'pages#index' + # PAGES root to: 'pages#index' diff --git a/db/migrate/20150220200526_add_referral_id_to_users.rb b/db/migrate/20150220200526_add_referral_id_to_users.rb new file mode 100644 index 00000000..d3bd6702 --- /dev/null +++ b/db/migrate/20150220200526_add_referral_id_to_users.rb @@ -0,0 +1,37 @@ +class AddReferralIdToUsers < ActiveRecord::Migration + def up + execute <<-SQL + create or replace function random_string(length integer) returns text as + $$ + declare + chars text[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}'; + result text := ''; + i integer := 0; + begin + if length < 0 then + raise exception 'Given length cannot be less than 0'; + end if; + for i in 1..length loop + result := result || chars[1+random()*(array_length(chars, 1)-1)]; + end loop; + return result; + end; + $$ language plpgsql; + SQL + + execute <<-SQL + ALTER TABLE users ADD COLUMN referral_code TEXT DEFAULT random_string(7) UNIQUE; + SQL + + add_column :users, :referred_by, :text + end + + def down + remove_column :users, :referred_by + remove_column :users, :referral_code + + execute <<-SQL + drop function random_string(length integer) + SQL + end +end diff --git a/db/migrate/20150220213450_add_referral_code_to_payments.rb b/db/migrate/20150220213450_add_referral_code_to_payments.rb new file mode 100644 index 00000000..830f1bf9 --- /dev/null +++ b/db/migrate/20150220213450_add_referral_code_to_payments.rb @@ -0,0 +1,5 @@ +class AddReferralCodeToPayments < ActiveRecord::Migration + def change + add_column :payments, :referred_by, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index fa147eb2..ad32517b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20140307205637) do +ActiveRecord::Schema.define(:version => 20150220213450) do create_table "campaigns", :force => true do |t| t.string "name" @@ -131,6 +131,7 @@ t.string "ct_charge_request_id" t.string "ct_charge_request_error_id" t.string "ct_user_id" + t.text "referred_by" end create_table "rewards", :force => true do |t| @@ -202,9 +203,12 @@ t.string "fullname" t.boolean "admin", :default => false t.boolean "wants_admin_payment_notification", :default => true, :null => false + t.text "referral_code" + t.text "referred_by" end add_index "users", ["email"], :name => "index_users_on_email", :unique => true + add_index "users", ["referral_code"], :name => "users_referral_code_key", :unique => true add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true end From 93738ce1fa1425f07045fe82c7244fe5ee00dbd4 Mon Sep 17 00:00:00 2001 From: Ken Koch Date: Mon, 23 Feb 2015 10:23:08 -0500 Subject: [PATCH 05/37] just hard code the port --- app/views/devise/registrations/edit.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 9a417ae3..05613841 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -10,7 +10,7 @@

Your Referral Link:

- <% link = request.protocol + request.host_with_port + "/u/" + current_user.referral_code %> + <% link = "https://" + request.host_with_port + "/u/" + current_user.referral_code %> <%= link %>


From 3d0f4dc84665d9116e8577264005cdebfedbfaad Mon Sep 17 00:00:00 2001 From: Ken Koch Date: Mon, 23 Feb 2015 11:45:38 -0500 Subject: [PATCH 06/37] add a function to lookup the referral user --- app/models/payment.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/models/payment.rb b/app/models/payment.rb index 83b77123..27107820 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -79,4 +79,16 @@ def self.display_date(date) date.strftime("%m/%d/%Y") end + # return the referral code for the user who made this payment + # returns nil if no user is found or if they do not have a referral + # source + def get_user_referral_code() + user = User.where(email: self.email) + if(user.length > 0) + return user[0].referred_by + else + return nil + end + end + end From c4be8e5efb842d378133d7c4d741c9bb96cb4e9a Mon Sep 17 00:00:00 2001 From: Ken Koch Date: Mon, 2 Mar 2015 13:57:48 -0500 Subject: [PATCH 07/37] basic tiers and fake users tools --- app/models/campaign.rb | 29 ++++++++++- app/models/campaign_tier.rb | 13 +++++ app/views/layouts/base.html.erb | 8 +-- app/views/theme/views/campaign.html.erb | 51 +++++++------------ ...8_add_fake_users_and_tiers_to_campaigns.rb | 7 +++ .../20150302181907_create_campaign_tiers.rb | 11 ++++ db/schema.rb | 12 ++++- script/rails | 0 spec/factories/campaign_tiers.rb | 9 ++++ spec/models/campaign_tier_spec.rb | 5 ++ 10 files changed, 103 insertions(+), 42 deletions(-) create mode 100644 app/models/campaign_tier.rb create mode 100644 db/migrate/20150302175048_add_fake_users_and_tiers_to_campaigns.rb create mode 100644 db/migrate/20150302181907_create_campaign_tiers.rb mode change 100644 => 100755 script/rails create mode 100644 spec/factories/campaign_tiers.rb create mode 100644 spec/models/campaign_tier_spec.rb diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 5f310f48..c42c546d 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -4,6 +4,7 @@ class Campaign < ActiveRecord::Base has_many :faqs, dependent: :destroy, :order => 'sort_order' has_many :payments has_many :rewards + has_many :campaign_tiers, :order => 'min_users ASC' attr_accessible :name, :goal_type, :goal_dollars, :goal_orders, :expiration_date, :ct_campaign_id, :media_type, :main_image, :main_image_delete, :video_embed_id, :video_placeholder, :video_placeholder_delete, @@ -50,6 +51,32 @@ def update_api_data(campaign) self.is_paid = campaign['is_paid'].to_i == 0 ? false : true end + def stats_raised_amount + self[:stats_raised_amount].to_i + (self.fake_users * self.fixed_payment_amount) + end + + def current_tier_price + price = self.base_price; + if(!self.current_tier.nil?) + price = self.current_tier.price_at_tier + end + + price + end + + def current_tier + max_users = 0; + tier = nil + self.campaign_tiers.each do |t| + if(self.orders >= t.min_users && max_users <= t.min_users) + tier = t + max_users = t.min_users + end + end + + tier + end + def set_goal if self.goal_type == 'orders' self.goal_dollars = ((self.fixed_payment_amount * self.goal_orders)*100).round/100.0 @@ -81,7 +108,7 @@ def number_of_contributions end def tilt_percent - (raised_amount / goal_dollars) * 100.0 + (self.stats_raised_amount / goal_dollars) * 100.0 end private diff --git a/app/models/campaign_tier.rb b/app/models/campaign_tier.rb new file mode 100644 index 00000000..09026876 --- /dev/null +++ b/app/models/campaign_tier.rb @@ -0,0 +1,13 @@ +class CampaignTier < ActiveRecord::Base + attr_accessible :campaign_id, :min_users, :price_at_tier + belongs_to :campaign + + def pct_off + ((self.campaign.base_price - self.price_at_tier) / self.campaign.base_price) * 100.0 + end + + def pct_complete + orders = self.campaign.orders + (1.0 * [orders, self.min_users].min / self.min_users) * 100.0 + end +end diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index 4c75267d..7ab1cb5b 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -30,13 +30,7 @@ <%= yield :footer %> - -
-   A Tilt Open Site -   <%= image_tag 'crowdtiltcircle.png' %>   - Powered by Tilt -
- + <% if Rails.env.development? %>
<%= debug(params) %>
<% end %> diff --git a/app/views/theme/views/campaign.html.erb b/app/views/theme/views/campaign.html.erb index fbb03890..c8b28bb0 100644 --- a/app/views/theme/views/campaign.html.erb +++ b/app/views/theme/views/campaign.html.erb @@ -39,42 +39,30 @@ <% end %> +
+

Current Price: <%= number_to_currency @campaign.current_tier_price, :precision => 0 %>

+ <% count = 0 %> + <% @campaign.campaign_tiers.each do |t| %> + <% count = count + 1 %> +

Tier <%= count %> <%= number_to_currency t.price_at_tier, :precision => 0 %> (<%= number_to_human t.pct_off, :precision => 0 %>% off)

+
+
+
+
+
+ <% end %> +
+
    - - <% if @campaign.goal_type == 'dollars' %> -
  • - <%= number_with_delimiter @campaign.number_of_contributions.to_i, :delimiter => "," %> - <%= @campaign.contributor_reference.pluralize(@campaign.number_of_contributions.to_i) %> -
  • -
  • - <%= number_to_currency @campaign.raised_amount.ceil, :precision => 0 %> - of <%= number_to_currency @campaign.goal_dollars.ceil, :precision => 0 %> -
  • - <% else %> -
  • - <%= @campaign.orders %> <%= @campaign.contributor_reference.pluralize(@campaign.orders) %> - of <%= @campaign.goal_orders %> needed -
  • - <% end %> - +
  • + <%= @campaign.orders %> <%= @campaign.contributor_reference.pluralize(@campaign.orders) %> + of <%= @campaign.goal_orders %> needed +
- <% if @campaign.raised_amount < @campaign.goal_dollars %> -
-
-
-
- <% else %> -
-
-
-
<%= @campaign.tilt_percent.ceil %>% <%= @campaign.progress_text %>
-
- <% end %> -
<% if @campaign.expired? %> @@ -96,9 +84,6 @@ <% end %>
-
<%= raw(@campaign.primary_call_to_action_description) %>
diff --git a/db/migrate/20150302175048_add_fake_users_and_tiers_to_campaigns.rb b/db/migrate/20150302175048_add_fake_users_and_tiers_to_campaigns.rb new file mode 100644 index 00000000..9455051c --- /dev/null +++ b/db/migrate/20150302175048_add_fake_users_and_tiers_to_campaigns.rb @@ -0,0 +1,7 @@ +class AddFakeUsersAndTiersToCampaigns < ActiveRecord::Migration + def change + add_column :campaigns, :fake_users, :integer, :default => 0 + + add_column :campaigns, :base_price, :decimal + end +end diff --git a/db/migrate/20150302181907_create_campaign_tiers.rb b/db/migrate/20150302181907_create_campaign_tiers.rb new file mode 100644 index 00000000..e28af4c0 --- /dev/null +++ b/db/migrate/20150302181907_create_campaign_tiers.rb @@ -0,0 +1,11 @@ +class CreateCampaignTiers < ActiveRecord::Migration + def change + create_table :campaign_tiers do |t| + t.integer :campaign_id + t.decimal :price_at_tier + t.integer :min_users + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index ad32517b..24f994ed 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,15 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20150220213450) do +ActiveRecord::Schema.define(:version => 20150302181907) do + + create_table "campaign_tiers", :force => true do |t| + t.integer "campaign_id" + t.decimal "price_at_tier" + t.integer "min_users" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end create_table "campaigns", :force => true do |t| t.string "name" @@ -71,6 +79,8 @@ t.boolean "include_comments", :default => false, :null => false t.string "comments_shortname" t.boolean "include_rewards_claimed" + t.integer "fake_users", :default => 0 + t.decimal "base_price" end add_index "campaigns", ["slug"], :name => "index_campaigns_on_slug", :unique => true diff --git a/script/rails b/script/rails old mode 100644 new mode 100755 diff --git a/spec/factories/campaign_tiers.rb b/spec/factories/campaign_tiers.rb new file mode 100644 index 00000000..69c58b75 --- /dev/null +++ b/spec/factories/campaign_tiers.rb @@ -0,0 +1,9 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl + +FactoryGirl.define do + factory :campaign_tier do + campaign_id 1 + price_at_tier "9.99" + min_users 1 + end +end diff --git a/spec/models/campaign_tier_spec.rb b/spec/models/campaign_tier_spec.rb new file mode 100644 index 00000000..8baab1d1 --- /dev/null +++ b/spec/models/campaign_tier_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe CampaignTier do + pending "add some examples to (or delete) #{__FILE__}" +end From c63ee415d2ddd0849259d1d101c7415ebef708d9 Mon Sep 17 00:00:00 2001 From: Ken Koch Date: Mon, 2 Mar 2015 14:29:12 -0500 Subject: [PATCH 08/37] tier pricing at quantity selection --- app/assets/javascripts/campaigns.js.coffee | 5 +++- app/models/campaign.rb | 17 +++++++++++++- app/views/campaigns/checkout_amount.html.erb | 24 ++++++++++---------- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/campaigns.js.coffee b/app/assets/javascripts/campaigns.js.coffee index 1dddf008..5f462842 100644 --- a/app/assets/javascripts/campaigns.js.coffee +++ b/app/assets/javascripts/campaigns.js.coffee @@ -16,11 +16,14 @@ Crowdhoster.campaigns = $('html,body').animate({scrollTop: $('#header')[0].scrollHeight}) $('#quantity').on "change", (e) -> + unit_price_at_qty = parseFloat($(":selected", this).attr('data-price-at-qty')); quantity = $(this).val() $amount = $('#amount') new_amount = parseFloat($amount.attr('data-original')) * quantity + new_amount_display = unit_price_at_qty * quantity + $("#unit-price-at-qty").html("$" + unit_price_at_qty.toFixed(2)); $amount.val(new_amount) - $('#total').html(new_amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");) + $('#total').html(new_amount_display.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",");) $('#amount').on "keyup", (e) -> $(this).addClass('edited') diff --git a/app/models/campaign.rb b/app/models/campaign.rb index c42c546d..b387d09e 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -55,6 +55,17 @@ def stats_raised_amount self[:stats_raised_amount].to_i + (self.fake_users * self.fixed_payment_amount) end + def price_at_additional_qty(amount) + expected_orders = self.orders + amount + price = self.base_price + tier = self.tier_for_orders expected_orders + if(!tier.nil?) + price = tier.price_at_tier + end + + price + end + def current_tier_price price = self.base_price; if(!self.current_tier.nil?) @@ -65,10 +76,14 @@ def current_tier_price end def current_tier + self.tier_for_orders self.orders + end + + def tier_for_orders(order_amount) max_users = 0; tier = nil self.campaign_tiers.each do |t| - if(self.orders >= t.min_users && max_users <= t.min_users) + if(order_amount >= t.min_users && max_users <= t.min_users) tier = t max_users = t.min_users end diff --git a/app/views/campaigns/checkout_amount.html.erb b/app/views/campaigns/checkout_amount.html.erb index 913e2c5c..b6677ac4 100644 --- a/app/views/campaigns/checkout_amount.html.erb +++ b/app/views/campaigns/checkout_amount.html.erb @@ -12,20 +12,20 @@

Please choose a quantity:


- <%= short_price(@campaign.fixed_payment_amount, '$', 2) %>  x   + <%= short_price(@campaign.price_at_additional_qty(1), '$', 2) %>  x   -   =  $<%= short_price(@campaign.fixed_payment_amount, '', 2) %> +   =  $<%= short_price(@campaign.price_at_additional_qty(1), '', 2) %>
From c31095d315a1b58538850836e411ef24718fcfa1 Mon Sep 17 00:00:00 2001 From: Ken Koch Date: Mon, 2 Mar 2015 14:47:31 -0500 Subject: [PATCH 09/37] tier based data in checkout flow --- Makefile | 5 +++++ app/controllers/campaigns_controller.rb | 2 ++ app/views/campaigns/checkout_confirmation.html.erb | 3 ++- app/views/campaigns/checkout_payment.html.erb | 8 ++++---- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index ab1a68cb..4ae9ceb0 100644 --- a/Makefile +++ b/Makefile @@ -9,3 +9,8 @@ restart: logs: tail -f log/unicorn.log; + + +local: + bundle exec foreman run unicorn -p 5000 -c ./config/unicorn.rb + diff --git a/app/controllers/campaigns_controller.rb b/app/controllers/campaigns_controller.rb index d0093d98..e4a16e76 100644 --- a/app/controllers/campaigns_controller.rb +++ b/app/controllers/campaigns_controller.rb @@ -62,8 +62,10 @@ def checkout_payment return end + @display_subtotal = @campaign.price_at_additional_qty(@quantity) * @quantity @fee = (@campaign.apply_processing_fee)? calculate_processing_fee(@amount * 100)/100.0 : 0 @total = @amount + @fee + @display_total = @display_subtotal + @fee end diff --git a/app/views/campaigns/checkout_confirmation.html.erb b/app/views/campaigns/checkout_confirmation.html.erb index d480f054..45517682 100644 --- a/app/views/campaigns/checkout_confirmation.html.erb +++ b/app/views/campaigns/checkout_confirmation.html.erb @@ -14,7 +14,8 @@ <% end%>

Date:
<%= @payment.created_at.strftime("%m/%d/%Y") %>

- Amount:
<%= short_price(@payment.amount.to_f/100.0 + @payment.user_fee_amount.to_f/100.0, '$', 2) %>

+ Minimum Payment Amount:
<%= short_price(@payment.amount.to_f/100.0 + @payment.user_fee_amount.to_f/100.0, '$', 2) %>

+ Maximum Payment Amount:
<%= short_price(@campaign.price_at_additional_qty(@payment.quantity) * @payment.quantity, '$', 2) %>

Card:
<%= @payment.card_type %> ************<%= @payment.card_last_four %> (<%= @payment.card_expiration_month.to_s + '/' + @payment.card_expiration_year.to_s %>)

<% if @campaign.rewards? %> diff --git a/app/views/campaigns/checkout_payment.html.erb b/app/views/campaigns/checkout_payment.html.erb index 95ccd48c..50469c7c 100644 --- a/app/views/campaigns/checkout_payment.html.erb +++ b/app/views/campaigns/checkout_payment.html.erb @@ -140,7 +140,7 @@

@@ -174,12 +174,12 @@ <% if @campaign.payment_type == "fixed" %> -

Subtotal (<%= "#{@quantity} x #{short_price(@campaign.fixed_payment_amount, '$', 2)}" %>)

+

Subtotal (<%= "#{@quantity} x #{short_price(@campaign.price_at_additional_qty(@quantity), '$', 2)}" %>)

<% else %>

Subtotal

<% end %> -

<%= short_price(@amount, '$', 2) %>

+

<%= short_price(@display_subtotal, '$', 2) %>

<% if @fee > 0 %> @@ -191,7 +191,7 @@

Total

-

<%= short_price(@total, '$', 2) %>

+

<%= short_price(@display_total, '$', 2) %>

<% if !@campaign.production_flag %> From e2822f4eaa44041efc3db7e1805c2dc921942268 Mon Sep 17 00:00:00 2001 From: Ken Koch Date: Mon, 2 Mar 2015 17:59:14 -0500 Subject: [PATCH 10/37] styles on the main campaign --- .../{application.css => application.scss} | 18 +- app/assets/stylesheets/primitives.css.scss | 6 +- app/models/campaign.rb | 16 + app/models/campaign_tier.rb | 8 + app/views/layouts/base.html.erb | 6 +- .../assets/stylesheets/campaign.css.scss | 44 ++- app/views/theme/views/_header.html.erb | 15 +- app/views/theme/views/campaign.html.erb | 327 ++++++------------ 8 files changed, 204 insertions(+), 236 deletions(-) rename app/assets/stylesheets/{application.css => application.scss} (80%) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.scss similarity index 80% rename from app/assets/stylesheets/application.css rename to app/assets/stylesheets/application.scss index fc74c06a..a20ea0d2 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.scss @@ -14,4 +14,20 @@ *= require jquery.ui.all *= require main *= require theme -*/ \ No newline at end of file +*/ + +#header { + font-size: 35px; + + div.container { + color: #ff8e1f; + + a { + color: #ff8e1f; + } + + a:hover { + text-decoration: none; + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/primitives.css.scss b/app/assets/stylesheets/primitives.css.scss index fc007540..9e7582b0 100644 --- a/app/assets/stylesheets/primitives.css.scss +++ b/app/assets/stylesheets/primitives.css.scss @@ -10,7 +10,7 @@ $text_shadow: 0 1px 0px #fff; $font_size: 22px; // Lockitron uses ProximaNova Regular, but that costs money, so we're defaulting to Helveitca Neue instead. -$primary_font: "Helvetica Neue"; +$primary_font: "proxima-nova-alt"; $secondary_font: "Helvetica"; $tertiary_font: "Arial"; @@ -29,7 +29,7 @@ $tertiary_font: "Arial"; h1 { margin: 0 auto; - font-family: Helvetica; + font-family: $primary_font; font-size: 42px; font-weight: bold; color: $h1_color; @@ -76,7 +76,7 @@ h5 { } p { - font-family: "Helvetica Neue","Helvetica","Arial"; + font-family: $primary_font, $secondary_font, $tertiary_font; color: #6b6b6b; font-size: 18px; line-height: 1.5; diff --git a/app/models/campaign.rb b/app/models/campaign.rb index b387d09e..fe1f136d 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -75,6 +75,22 @@ def current_tier_price price end + def next_tier + tier = self.campaign_tiers.first + self.campaign_tiers.each do |t| + if(self.orders < t.min_users) + tier = t + break + end + end + + tier + end + + def until_next_tier + self.next_tier.min_users - self.orders + end + def current_tier self.tier_for_orders self.orders end diff --git a/app/models/campaign_tier.rb b/app/models/campaign_tier.rb index 09026876..c362eb9d 100644 --- a/app/models/campaign_tier.rb +++ b/app/models/campaign_tier.rb @@ -10,4 +10,12 @@ def pct_complete orders = self.campaign.orders (1.0 * [orders, self.min_users].min / self.min_users) * 100.0 end + + def complete + self.pct_complete >= 100 + end + + def remaining + return [0, self.min_users - self.campaign.orders].max + end end diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index 7ab1cb5b..0f2d92c6 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -12,10 +12,14 @@ <%= javascript_include_tag "application" %> <%= yield :scripts %> + + + + - + <%= yield :header %> diff --git a/app/views/theme/assets/stylesheets/campaign.css.scss b/app/views/theme/assets/stylesheets/campaign.css.scss index ec2175df..a6c63ef6 100644 --- a/app/views/theme/assets/stylesheets/campaign.css.scss +++ b/app/views/theme/assets/stylesheets/campaign.css.scss @@ -2,6 +2,36 @@ /************************************* ********** FUNDING AREA ************** **************************************/ + #right-column h3 { + text-align: center; + } + + .tier-list { + .price { + font-size:30px; + float: left; + width:25%; + border-right: 1px solid white; + margin-right:5px; + } + + .list-group-item-success { + .price { + text-decoration: line-through; + } + } + + .people-needed { + float:left; + width:70%; + text-align: center; + } + + .remaining { + font-size:30px; + font-weight: bold; + } + } #funding_area { width: 100%; @@ -22,7 +52,6 @@ #video { float: left; - width: 512px; height: 385px; background: #fff; -moz-box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */ @@ -37,7 +66,6 @@ #image { float: left; - width: 512px; height: 385px; -moz-box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */ -webkit-box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */ @@ -70,10 +98,12 @@ } } + .backing-wrapper { + text-align: center; + } + #backing { - float: left; - width: 392px; - margin: 20px 0 0 34px; + margin-left:15px; ul { margin: 0; @@ -201,8 +231,8 @@ } .share { - margin-left: 100px; - margin-top: 24px; + margin-left: 34px; + margin-bottom: 20px; } } diff --git a/app/views/theme/views/_header.html.erb b/app/views/theme/views/_header.html.erb index 7c6c5a71..21176d11 100644 --- a/app/views/theme/views/_header.html.erb +++ b/app/views/theme/views/_header.html.erb @@ -1,8 +1,12 @@