Remove trial support

This commit is contained in:
Eric Schultz 2019-11-05 13:38:36 -06:00
parent 6667eb6fac
commit 51ef25b3af
30 changed files with 3 additions and 241 deletions

View file

@ -10,7 +10,6 @@ class ApplicationController < ActionController::Base
:current_role?,
:current_nonprofit_user?,
:administered_nonprofit,
:nonprofit_in_trial?,
:current_plan_tier # int
def set_locale
@ -125,14 +124,6 @@ class ApplicationController < ActionController::Base
QueryRoles.user_has_role?(current_user.id, role_names, host_id)
end
def nonprofit_in_trial?(npo_id = nil)
return false if !npo_id && !administered_nonprofit
npo_id ||= administered_nonprofit.id
key = "in_trial_user_#{current_user_id}_nonprofit_#{npo_id}"
QueryBillingSubscriptions.currently_in_trial?(npo_id)
end
def current_plan_tier(npo_id = nil)
return 0 if !npo_id && !administered_nonprofit

View file

@ -22,7 +22,6 @@ module Nonprofits
requires(:holder_type).one_of('Supporter', 'Nonprofit')
end
end.when_valid do |d|
UpdateBillingSubscriptions.activate_from_trial(d[:nonprofit_id])
InsertCard.with_stripe(d[:card])
end
)

View file

@ -5,7 +5,7 @@ class BillingSubscription < ApplicationRecord
# :nonprofit_id, :nonprofit,
# :billing_plan_id, :billing_plan,
# :stripe_subscription_id,
# :status # trialing, active, past_due, canceled, or unpaid
# :status # active, past_due, canceled, or unpaid
attr_accessor :stripe_plan_id, :manual
belongs_to :nonprofit

View file

@ -12,8 +12,6 @@
<%= IncludeAsset.js '/client/js/campaigns/index/page.js' %>
<% end %>
<%= render '/components/trial_bar' if QueryBillingSubscriptions.currently_in_trial?(@nonprofit.id) %>
<%= render 'components/header',
icon_class: 'icon-thermometer-medium',
title: 'Campaigns',

View file

@ -59,8 +59,6 @@
<%= render 'admin_top_nav' %>
<% end %>
<%= render '/components/trial_bar' if QueryBillingSubscriptions.currently_in_trial?(@nonprofit.id) %>
<%= render 'components/fundraising_pages/header',
image_url: @campaign_background_image,
is_editor: current_campaign_editor?,

View file

@ -15,8 +15,6 @@
<%= stylesheet_link_tag 'campaigns/supporters/index/page' %>
<% end %>
<%= render '/components/trial_bar' if QueryBillingSubscriptions.currently_in_trial?(@nonprofit.id) %>
<header class='header'>
<div class='container'>
<i class='icon-check-list header-icon'></i>

View file

@ -1,10 +0,0 @@
<%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%>
<!-- partial start: componenets/trial_bar -->
<div class='is-showing announcementBar--grey'>
<div class='container transparent centered'>
You have <%= QueryBillingSubscriptions.days_left_in_trial(@nonprofit.id) %> days left in your free trial. You can
<a href="/nonprofits/<%= @nonprofit.id%>/card/edit" class='u-underline'>activate your account at anytime.
</a>
</div>
</div>
<!-- partial end: componenets/trial_bar -->

View file

@ -43,8 +43,6 @@
<%= render 'admin_top_nav' %>
<% end %>
<%= render '/components/trial_bar' if QueryBillingSubscriptions.currently_in_trial?(@nonprofit.id) %>
<%= render 'components/fundraising_pages/header',
image_url: @event_background_image,
is_editor: current_event_editor?,

View file

@ -1,37 +0,0 @@
<%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%>
<div class='modal skinny' id='newNonprofitModal'>
<%= render 'common/modal_header', title: 'Register Your Organization' %>
<div class='modal-body'>
<form parsley-validate>
<!--= on 'submit' (create_admin_and_nonprofit form_object) -->
<input type='text' name='name' placeholder='Organization name' required parsley-trigger='change'>
<select>
<!--= show_if is_onboarding_with_trial -->
<!--= set_attr_if is_onboarding_with_trial 'name' 'tier' -->
<!--= set_attr_if is_onboarding_with_trial 'required' '' -->
<option value='' selected>Organization Budget</option>
<option value='1'>less than $250K</option>
<option value='2'>$250K ~ $5M</option>
<option value='3'>$5M+</option>
</select>
<input type='text' name='city' placeholder='City' required parsley-trigger='change' class='input--half'>
<input type='hidden' name='referrer' value="<%= params[:referrer] %>">
<select name='state_code' class='input--half u-floatR' required>
<option value='' selected>State</option>
<% us_states.each do |state| %>
<option value='<%= state[1] %>'><%= state[1] %></option>
<% end %>
</select>
<input type='text' name='website' parsley-trigger='change' placeholder='Nonprofit website'>
<%= render 'components/forms/submit_button', button_text: 'Create', scope: 'new_nonprofit' %>
</form>
<p class='finePrint u-marginTop--20 u-marginBottom--0 u-centered'>By clicking Create, you agree to our <%= link_to "terms of service & privacy policy", (root_url + "help/terms-of-service-and-privacy-policy"), target: :blank %></p>
</div>
</div>

View file

@ -8,8 +8,6 @@
<%= IncludeAsset.js '/client/js/nonprofits/button/page.js' %>
<% end %>
<%= render '/components/trial_bar' if nonprofit_in_trial?(@nonprofit.id) %>
<header class='header'>
<div class='container--mid'>
<i class='header-icon icon-credit-card'></i>

View file

@ -22,8 +22,6 @@ document.addEventListener("DOMContentLoaded", function(event) {
})
</script>
<%= render '/components/trial_bar' if nonprofit_in_trial?(@nonprofit.id) %>
<header class='header'>
<div class='container--mid'>
<i class='header-icon icon-credit-card'></i>

View file

@ -8,8 +8,6 @@
<%= IncludeAsset.js '/client/js/nonprofits/button/page.js' %>
<% end %>
<%= render '/components/trial_bar' if nonprofit_in_trial?(@nonprofit.id) %>
<header class='header'>
<div class='container--mid'>
<i class='header-icon icon-credit-card'></i>

View file

@ -6,7 +6,6 @@
card: <%= @nonprofit.active_card ? raw(@nonprofit.active_card.to_json) : '{}' %>
, plan: <%= raw(@nonprofit.billing_plan.to_json) %>
, subscription: <%= raw(@nonprofit.billing_subscription.to_json) %>
, daysLeft : <%= QueryBillingSubscriptions.days_left_in_trial(@nonprofit.id) %>
}
</script>
<%= IncludeAsset.js '/client/js/nonprofits/cards/edit/page.js' %>

View file

@ -10,8 +10,6 @@
<%= IncludeAsset.js '/client/js/nonprofits/dashboard/page.js' %>
<% end %>
<%= render '/components/trial_bar' if nonprofit_in_trial? %>
<%= render 'components/header',
icon_class: 'icon-camera-graph-2',
title: 'Dashboard',

View file

@ -42,8 +42,6 @@
</script>
<% end %>
<%= render '/components/trial_bar' if QueryBillingSubscriptions.currently_in_trial?(@nonprofit.id) %>
<%= render 'nonprofits/transaction_title',
active: :payments,
icon_class: 'icon-piggy-bank',

View file

@ -11,8 +11,6 @@
</script>
<% end %>
<%= render '/components/trial_bar' if QueryBillingSubscriptions.currently_in_trial?(@nonprofit.id) %>
<%= render 'nonprofits/transaction_title',
active: :payouts,
icon_class: 'icon-bank-1',

View file

@ -9,8 +9,6 @@
<%= IncludeAsset.js '/client/js/nonprofits/recurring_donations/index/page.js' %>
<% end %>
<%= render '/components/trial_bar' if nonprofit_in_trial?(@nonprofit.id) %>
<%= render 'nonprofits/transaction_title',
active: :recurring,
icon_class: 'icon-return',

View file

@ -59,8 +59,6 @@
<%= render 'admin_top_nav' %>
<% end %>
<%= render '/components/trial_bar' if nonprofit_in_trial?(@nonprofit.id) %>
<%= render 'components/fundraising_pages/header',
image_url: @nonprofit_background_image,
is_editor: current_nonprofit_user?,

View file

@ -40,8 +40,6 @@
</script>
<% end %>
<%= render '/components/trial_bar' if nonprofit_in_trial?(@nonprofit.id) %>
<%= render 'header'%>
<%= render 'table_meta' %>

View file

@ -15,14 +15,8 @@
</strong><br>
<em><small>Our processor (Stripe) assesses an additional 2.2% + $0.30 for each online payment.</small></em></p>
<% if @nonprofit.billing_subscription.status == 'trialing' %>
<p>
To ensure that your account stays active after your trial,
<a href='/nonprofits/<%=@nonprofit.id%>/card/edit'><strong> add a payment method.</strong></a>
</p>
<% end %>
<% if @nonprofit.billing_plan.amount > 0 && @nonprofit.billing_subscription.status != 'trialing' %>
<% if @nonprofit.billing_plan.amount > 0 %>
<p><a class='u-color--red u-small' href='/nonprofits/<%=@nonprofit.id%>/billing_subscription/cancellation'>Unsubscribe from plan</a></p>
<p>

View file

@ -14,8 +14,6 @@
<%= IncludeAsset.js '/client/js/settings/index/page.js' %>
<% end %>
<%= render '/components/trial_bar' if @nonprofit && nonprofit_in_trial?(@nonprofit.id) %>
<header class='header stripe--mosaic'>
<div class='container--mid'>
<i class='header-icon icon-setting-gear'></i>

View file

@ -18,8 +18,6 @@
<%= stylesheet_link_tag 'tickets/index/page' %>
<% end %>
<%= render '/components/trial_bar' if QueryBillingSubscriptions.currently_in_trial?(@nonprofit.id) %>
<header class='header'>
<div class='container'>
<i class='icon-check-list header-icon'></i>

View file

@ -38,9 +38,6 @@ const view = state =>
h('div.u-centered.u-maxWidth--600.u-margin--auto.u-marginTop--50.u-padding--15.js-view-confirm', [
h('h4', `Payment Method for ${app.nonprofit.name}`)
, state.card.name ? h('p', `Current card: ${state.card.name}`) : ''
, h('p', [
state.subscription.status === 'trialing' ? `You have ${state.daysLeft} days left in your free trial. If you add a payment method now, your account will stay active after your trial, and you will get your remaining trial days for free.` : ''
])
, h('p.u-strong', `Tier: ${state.plan.name} ($${format.centsToDollars(state.plan.amount)} ${state.plan.interval})`)
, h('hr')
, h('h5', 'Update Your Card:')

View file

@ -8,11 +8,9 @@ module ConstructBillingSubscription
def self.with_stripe(np, billing_plan)
raise ArgumentError, 'Billing plan not found' if billing_plan.nil?
trial_end = QueryBillingSubscriptions.currently_in_trial?(np.id) ? (np.created_at + 15.days).to_i : nil
customer = Stripe::Customer.retrieve np.active_card.stripe_customer_id
stripe_subscription = customer.subscriptions.create(
plan: billing_plan.stripe_plan_id,
trial_end: trial_end
plan: billing_plan.stripe_plan_id
)
{
billing_plan_id: billing_plan.id,

View file

@ -1,30 +0,0 @@
# frozen_string_literal: true
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
require 'qx'
require 'delayed_job_helper'
require 'active_support/core_ext'
module InsertBillingSubscriptions
def self.trial(np_id, stripe_plan_id)
nonprofit = Nonprofit.includes(:billing_subscription).find(np_id)
billing_plan = BillingPlan.where('stripe_plan_id = ?', stripe_plan_id).last
sub = nonprofit.create_billing_subscription(billing_plan: billing_plan, status: 'trialing')
n = 10
DelayedJobHelper.enqueue_job(self, :check_trial, [sub['id']], run_at: n.days.from_now)
{ json: sub }
rescue ActiveRecord::RecordNotFound => e
{ json: { error: e }, status: :unprocessable_entity }
end
def self.check_trial(bs_id)
sub = Qx.fetch(:billing_subscriptions, bs_id).last
if sub['status'] == 'trialing'
Qx.update(:billing_subscriptions)
.set(status: 'inactive')
.timestamps
.where('id = $id', id: bs_id)
.execute
end
end
end

View file

@ -5,22 +5,10 @@ require 'qx'
require 'active_support/core_ext'
module QueryBillingSubscriptions
def self.days_left_in_trial(np_id)
sub = Qx.fetch(:billing_subscriptions, nonprofit_id: np_id).last
return 0 if sub.nil?
sub['status'] == 'trialing' ? (((sub['created_at'] + 10.days) - Time.current) / 86_400).floor : 0
end
def self.plan_tier(np_id)
sub = Qx.fetch(:billing_subscriptions, nonprofit_id: np_id).last
return 2 if sub && sub['status'] != 'inactive'
0
end
def self.currently_in_trial?(np_id)
sub = Qx.fetch(:billing_subscriptions, nonprofit_id: np_id).last
sub && sub['status'] == 'trialing'
end
end

View file

@ -1,13 +0,0 @@
# frozen_string_literal: true
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
module UpdateBillingSubscriptions
def self.activate_from_trial(np_id)
Qx.update(:billing_subscriptions)
.set(status: 'active')
.timestamps
.where('nonprofit_id=$id', id: np_id)
.execute
end
end

View file

@ -7,9 +7,6 @@ require 'controllers/support/shared_user_context'
describe BillingSubscriptionsController, type: :controller do
describe 'authorization' do
include_context :shared_user_context
describe 'create_trial' do
include_context :open_to_np_admin, :post, :create_trial, nonprofit_id: :__our_np
end
describe 'create' do
include_context :open_to_np_admin, :post, :create, nonprofit_id: :__our_np

View file

@ -1,35 +0,0 @@
# frozen_string_literal: true
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
require 'rails_helper'
describe InsertBillingSubscriptions, skip: true do
let(:sub) do
# billing_plan = Qx.insert_into(:billing_plans).values({name: 'test_bp', amount: 0, stripe_plan_id: 'stripe_bp', created_at: Time.current, updated_at: Time.current}).returning('*').execute.last
# InsertBillingSubscriptions.trial(3624, billing_plan['stripe_plan_id'])[:json]
end
describe '.trial' do
it 'creates the record' do
sub
expect(sub['id']).to be_present
end
end
describe '.check_trial' do
it 'marks as inactive after 10 days' do
sub
Timecop.freeze(10.days.from_now) { InsertBillingSubscriptions.check_trial(sub['id']) }
updated = Qx.fetch(:billing_subscriptions, sub['id']).last
expect(updated['status']).to eq('inactive')
end
it 'does not change the status if not still trialing after 10 days' do
sub
Qx.update(:billing_subscriptions).set(status: 'active').where('id = $id', id: sub['id']).execute
Timecop.freeze(10.days.from_now) { InsertBillingSubscriptions.check_trial(sub['id']) }
updated = Qx.fetch(:billing_subscriptions, sub['id']).last
expect(updated['status']).to eq('active')
end
end
end

View file

@ -7,36 +7,9 @@ require 'query/query_billing_subscriptions'
describe QueryBillingSubscriptions, pending: true do
before(:each) do
# Qx.delete_from(:billing_plans).where("stripe_plan_id = $id", id: 'stripe_bp').execute
# Qx.delete_from(:billing_subscriptions).where("nonprofit_id = $id", id: 3624).execute
# @billing_plan = Qx.insert_into(:billing_plans).values({name: 'test_bp', amount: 0, stripe_plan_id: 'stripe_bp', created_at: Time.current, updated_at: Time.current}).returning('*').execute.last
# @sub = InsertBillingSubscriptions.trial(3624, @billing_plan['stripe_plan_id'])[:json]
end
describe '.days_left_in_trial' do
it 'gives days left in trial, rounded down' do
expect(QueryBillingSubscriptions.days_left_in_trial(3624)).to eq(9)
raise
end
it 'gives 0 if not trialing' do
Qx.update(:billing_subscriptions).set(status: 'active').where('id = $id', id: @sub['id']).execute
expect(QueryBillingSubscriptions.days_left_in_trial(3624)).to eq(0)
raise
end
it 'gives negative if past expiration' do
Qx.update(:billing_subscriptions).set(status: 'trialing', created_at: 20.days.ago).where('id = $id', id: @sub['id']).execute
expect(QueryBillingSubscriptions.days_left_in_trial(3624)).to eq(-11)
raise
end
end
describe '.plan_tier' do
it 'gives tier 2 if status=trialing' do
Qx.update(:billing_subscriptions).set(status: 'trialing').where('id = $id', id: @sub['id']).execute
expect(QueryBillingSubscriptions.plan_tier(3624)).to eq(2)
end
it 'gives tier 0 if status=inactive' do
Qx.update(:billing_subscriptions).set(status: 'inactive').where('id = $id', id: @sub['id']).execute
expect(QueryBillingSubscriptions.plan_tier(3624)).to eq(0)
@ -52,23 +25,4 @@ describe QueryBillingSubscriptions, pending: true do
raise
end
end
describe '.currently_in_trial?' do
it 'gives true if status=trialing' do
Qx.update(:billing_subscriptions).set(status: 'trialing').where('id = $id', id: @sub['id']).execute
expect(QueryBillingSubscriptions.currently_in_trial?(3624)).to eq(true)
raise
end
it 'gives false if status!=trialing' do
Qx.update(:billing_subscriptions).set(status: 'active').where('id = $id', id: @sub['id']).execute
expect(QueryBillingSubscriptions.currently_in_trial?(3624)).to eq(false)
raise
end
it 'gives false if no subscription' do
expect(QueryBillingSubscriptions.currently_in_trial?(666)).to be_falsey
raise
end
end
end