Skip to content

Bug invoice generation #392 #240

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

Merged
merged 3 commits into from
Nov 3, 2014
Merged
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: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
.idea
.sass-cache
.vagrant
.rspec
.rspec-local
.yardoc
/.bundle
/config/application.yml
Expand Down
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
--require spec_helper
--require turnip/rspec
--format Fuubar
--color
--profile
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,10 @@ group :test do
# gem 'rspec-its'
gem 'capybara'
gem 'capybara-screenshot'
gem 'turnip' # write rspec feature specs in cucumber style
gem 'rack_session_access' # allows to set session from within Capybara
gem 'poltergeist' # headless js driver for Capybara that uses phantomJs
gem 'selenium-webdriver' # headfull js driver for Capybara
gem 'codeclimate-test-reporter', require: false
gem 'database_cleaner'
gem 'fuubar', '2.0.0.rc1'
Expand Down
15 changes: 15 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ GEM
carrierwave (~> 0.5)
celluloid (0.15.2)
timers (~> 1.1.0)
childprocess (0.5.5)
ffi (~> 1.0, >= 1.0.11)
choice (0.1.6)
chronic (0.10.2)
chunky_png (1.3.1)
Expand Down Expand Up @@ -277,6 +279,8 @@ GEM
multi_json (~> 1.0)
net-http-persistent (>= 2.7)
net-http-pipeline
gherkin (2.12.2)
multi_json (~> 1.3)
github-markdown (0.6.6)
grackle (0.3.0)
json
Expand Down Expand Up @@ -591,6 +595,7 @@ GEM
ruby-progressbar (1.5.1)
ruby_parser (3.6.2)
sexp_processor (~> 4.1)
rubyzip (1.1.6)
safe_yaml (1.0.3)
sanitize (3.0.0)
crass (~> 0.2.0)
Expand All @@ -606,6 +611,11 @@ GEM
faraday (~> 0.8, < 0.10)
sax-machine (0.2.1)
nokogiri (~> 1.6.0)
selenium-webdriver (2.43.0)
childprocess (~> 0.5)
multi_json (~> 1.0)
rubyzip (~> 1.0)
websocket (~> 1.0)
sexp_processor (4.4.4)
shoulda-matchers (2.6.2)
activesupport (>= 3.0.0)
Expand Down Expand Up @@ -686,6 +696,9 @@ GEM
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
turnip (1.2.4)
gherkin (>= 2.5)
rspec (>= 2.14.0, < 4.0)
tweet-button (0.1.0)
twitter (5.5.1)
addressable (~> 2.3)
Expand Down Expand Up @@ -813,6 +826,7 @@ DEPENDENCIES
sanitize
sass (~> 3.2.9)
sass-rails (~> 3.2.6)
selenium-webdriver
shoulda-matchers
sidekiq
simple_form
Expand All @@ -829,6 +843,7 @@ DEPENDENCIES
timecop
tire
travis
turnip
tweet-button
twitter
uglifier (>= 1.0.3)
Expand Down
12 changes: 9 additions & 3 deletions app/controllers/accounts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,15 @@ def webhook
end

def send_invoice
@team = Team.find(params[:team_id])
@team.account.send_invoice_for(1.month.ago)
redirect_to teamname_path(slug: @team.slug), notice: "sent invoice for #{1.month.ago.strftime("%B")} to #{@team.account.admin.email}"
team, period = Team.find(params[:team_id]), 1.month.ago

if team.account.send_invoice_for(period)
flash[:notice] = "sent invoice for #{period.strftime("%B")} to #{team.account.admin.email}"
else
flash[:error] = 'There was an error in sending an invoice'
end

redirect_to teamname_path(slug: team.slug)
end

private
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class ApplicationController < ActionController::Base
after_action :record_visit
after_action :record_location

rescue_from ActiveRecord::RecordNotFound, with: :render_404 unless Rails.env.production?
rescue_from ActionController::RoutingError, with: :render_404 unless Rails.env.production?

protected

def apply_flash_message
Expand Down Expand Up @@ -179,9 +182,6 @@ def not_on_achievements?
params[:controller] != 'achievements'
end

rescue_from ActiveRecord::RecordNotFound, with: :render_404
rescue_from ActionController::RoutingError, with: :render_404

def render_404
render template: 'error/not_found', status: :not_found
end
Expand Down
13 changes: 13 additions & 0 deletions app/helpers/accounts_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,17 @@ def monthly_plan_price(plan)
def purchased_plan(plan)
plan.nil? ? "Monthly" : plan.name
end

def card_for(customer)
card = customer[:active_card] || customer[:cards].first
end

def invoice_date(invoice)
Time.at(invoice[:date]).to_date.to_formatted_s(:long_ordinal)
end

def subscription_period_for(invoice, period)
subscription_period = invoice[:lines][:data].first[:period][period]
Time.at(subscription_period).to_date.to_formatted_s(:long_ordinal)
end
end
1 change: 1 addition & 0 deletions app/mailers/notifier_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class NotifierMailer < ActionMailer::Base
add_template_helper(UsersHelper)
add_template_helper(ProtipsHelper)
add_template_helper(ApplicationHelper)
add_template_helper(AccountsHelper)

layout 'email', except: [:weekly_digest, :alert_admin]

Expand Down
6 changes: 3 additions & 3 deletions app/views/notifier_mailer/invoice.html.haml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
%tr
%td.main-content-grey{:style => "padding: 30px 60px; background:#ffffff;font-family:'Helvetica Neue','Helvetica','Arial','sans-serif';"}
%p{:style => "font-size: 16px; font-family:'Helvetica Neue','Helvetica','Arial','sans-serif'; margin-bottom: 10px;"}
==Your card has ending in #{@customer[:active_card][:last4]} been charged
="Your card ending in #{card_for(@customer)[:last4]} has been charged"
%table{:style => "width:600"}
%tr
%td
== Bill Date: #{Time.at(@invoice[:date]).strftime("%B %d, %Y")}
== Bill Date: #{invoice_date(@invoice)}
%tr
%td
%tr
Expand All @@ -20,7 +20,7 @@
%tr
%td
Duration:
==#{Time.at(@invoice[:lines][:subscriptions].first[:period][:start]).strftime("%B %d, %Y")}-#{Time.at(@invoice[:lines][:subscriptions].first[:period][:end]).strftime("%B %d, %Y")}
==#{subscription_period_for(@invoice, :start)}-#{subscription_period_for(@invoice, :end)}
%td
Description:
Enhanced Team Profile (4 job posts anytime)
Expand Down
3 changes: 0 additions & 3 deletions app/views/subscription_mailer/team_upgrade.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,3 @@
%p{:style => "font-size: 14px; margin: 0; font-family:'Helvetica Neue','Helvetica','Arial','sans-serif';"}
If you have any questions or concerns about your account, please contact us:
=mail_to('support@coderwall.com', nil, :style => "color:3D8DCC;")



13 changes: 0 additions & 13 deletions app/views/subscription_mailer/team_upgrade.text.erb

This file was deleted.

2 changes: 1 addition & 1 deletion app/views/teams/premium.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
%ul.legend
%li.team-visitors
=link_to 'Visitors', visitors_team_path(@team)
-if is_admin?
-if is_admin? && @team.account
%li.send-invoice
=link_to 'Send Invoice', send_invoice_team_account_path(@team), :method => :post

Expand Down
7 changes: 3 additions & 4 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@

# Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets
config.assets.allow_debugging = true
config.middleware.use RackSessionAccess::Middleware # allows to set session from within Capybara

config.middleware.use RackSessionAccess::Middleware # alloes to set session from within Capybara

Rails.logger = Logger.new(STDOUT)
Rails.logger.level = Logger::DEBUG # provides more verbose output when testing with headless browsers in case of errors
Rails.logger = Logger.new(STDOUT) # provides more verbose output when testing with headless browsers in case of errors
Rails.logger.level = Logger::DEBUG
end
36 changes: 35 additions & 1 deletion spec/controllers/accounts_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
RSpec.describe AccountsController, :type => :controller do
let(:team) { Fabricate(:team) }
let(:team) { Fabricate(:team, account: nil) }
let(:plan) { Plan.create(amount: 20000, interval: Plan::MONTHLY, name: 'Monthly') }
let(:current_user) { Fabricate(:user) }

Expand Down Expand Up @@ -30,4 +30,38 @@ def valid_params

end
end

describe '#send_inovice' do
before do
team.account = Account.new

allow(Team).to receive(:find) { team }
allow(team.account).to receive(:send_invoice_for) { true }
allow(team.account).to receive(:admin) { current_user }

allow(Time).to receive(:current) { Date.parse('02/11/15').to_time } # so we do not bother with the time portion of the day
end

it 'calls send_invoice for the last month' do
expect(team.account).to receive(:send_invoice_for).with(Date.parse('02/10/15').to_time)
get :send_invoice, id: '123'
end

it 'displays success message' do
get :send_invoice, id: '123'
expect(flash[:notice]).to eq("sent invoice for October to #{current_user.email}")
end

it 'redirects to team profile' do
get :send_invoice, id: '123'
expect(response).to redirect_to(teamname_path(slug: team.slug))
end

it 'displays failure message' do
allow(team.account).to receive(:send_invoice_for) { false }
get :send_invoice, id: '123'
expect(flash[:error]).to eq('There was an error in sending an invoice')
end

end
end
4 changes: 4 additions & 0 deletions spec/fabricators/account_fabricator.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
Fabricator(:account) do
name 'test_account'
admin_id 1
stripe_card_token { "tok_14u7LDFs0zmMxCeEU3OGRUa0_#{rand(1000)}" }
stripe_customer_token { "cus_54FsD2W2VkrKpW_#{rand(1000)}" }
end
2 changes: 2 additions & 0 deletions spec/fabricators/plan_fabricator.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Fabricator(:plan) do
name { sequence(:name) { |i| "plan_no_#{i}" } }
amount { rand * 100 }
end

# == Schema Information
Expand Down
3 changes: 2 additions & 1 deletion spec/fabricators/team_fabricator.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Fabricator(:team) do
name { Faker::Company.name }
end
account { Fabricate.build(:account) }
end
43 changes: 43 additions & 0 deletions spec/features/steps/basic_steps.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
step 'I am logged in as :name with email :email' do |name, email|
login_as(username: name, email: email, bypass_ui_login: true)
@logged_in_user = User.where(username: name).first
end

step 'I go/am to/on page for :pupropse' do |purpose|
path = case purpose
when 'team management' then team_path(@logged_in_user.reload.team)
end

visit path
end

step 'show me the page' do
page.save_screenshot('tmp/screenshot.png', full: true)
end

step 'I click :link_name' do |name|
click_link name
end

step 'I am an administrator' do
@logged_in_user.admin = true
@logged_in_user.save
end

step 'I should see :text' do |text|
expect(page).to have_content(text)
end

step 'I should see:' do |table|
table.hashes.each do |text|
expect(page).to have_content(text.values.first)
end
end

step 'the last email should contain:' do |table|
mail = ActionMailer::Base.deliveries.last

table.hashes.each do |text|
expect(mail).to have_content(text.values.first)
end
end
49 changes: 49 additions & 0 deletions spec/features/steps/team_steps.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
step 'a team :team_name exists' do |team_name|
Fabricate(:team, name: team_name)
end

step 'team :team_name is subscribed to plan :plan_name with card :card_no' do |team_name, plan_name, card_no|
plan = Fabricate.build(:plan, name: plan_name)

stripe_plan = JSON.parse(File.read('./spec/fixtures/stripe/stripe_plan.json')).with_indifferent_access.tap do |h|
h[:interval] = plan.interval
h[:name] = plan.name
h[:created] = plan.created_at
h[:amount] = plan.amount
h[:currency] = plan.currency
h[:id] = plan.public_id
end
stub_request(:post, /api.stripe.com\/v1\/plans/).to_return(body: stripe_plan.to_json)

plan.save

team = Team.where(name: team_name).first
team.account.plan_ids = [plan.id]
team.save

stripe_customer = JSON.parse(File.read('./spec/fixtures/stripe/stripe_customer.json')).with_indifferent_access.tap do |h|
h[:id] = team.account.stripe_customer_token
h[:description] = "test@test.com for #{team_name}"
h[:cards][:data].first[:last4] = card_no
end
stub_request(:get, /api.stripe.com\/v1\/customers\/#{team.account.stripe_customer_token}/).to_return(body: stripe_customer.to_json)
end

step 'team :team_name has invoices with data:' do |team_name, table|
team = Team.where(name: team_name).first
data = table.rows_hash

stripe_invoices = JSON.parse(File.read('./spec/fixtures/stripe/stripe_invoices.json')).with_indifferent_access.tap do |h|
h[:data].first[:date] = Date.parse(data['Date']).to_time.to_i
h[:data].first[:lines][:data].first[:period][:start] = Date.parse(data['Start']).to_time.to_i
h[:data].first[:lines][:data].first[:period][:end] = Date.parse(data['End']).to_time.to_i
end
stub_request(:get, /api.stripe.com\/v1\/invoices/).to_return(body: stripe_invoices.to_json)
end

step 'I am member of team :team_name' do |team_name|
team = Team.find_by(name: team_name)
team.add_user(@logged_in_user)
team.account.admin_id = @logged_in_user.id
team.save
end
Loading