Skip to content

Commit

Permalink
updates to how we handle free subscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
robguthrie committed Jun 24, 2024
1 parent 873ba72 commit e6a72dc
Show file tree
Hide file tree
Showing 10 changed files with 40 additions and 93 deletions.
2 changes: 1 addition & 1 deletion app/admin/subscriptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
inputs 'Subscription' do
input :plan, as: :select, collection: SubscriptionService::PLANS.keys
input :payment_method, as: :select, collection: Subscription::PAYMENT_METHODS
input :state, as: :select, collection: ['active', 'canceled', 'trialing']
input :state, as: :select, collection: ['active', 'on_hold', 'pending', 'past_due', 'canceled']
input :expires_at
input :max_threads
input :max_members
Expand Down
9 changes: 7 additions & 2 deletions app/models/subscription.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ class NotActive < StandardError; end
include SubscriptionConcern if Object.const_defined?('SubscriptionConcern')

PAYMENT_METHODS = ["chargify", "manual", "barter", "paypal"]
ACTIVE_STATES = %w[active on_hold pending]

scope :dangling, -> { joins('LEFT JOIN groups ON subscriptions.id = groups.subscription_id').where('groups.id IS NULL') }
scope :active, -> { where(state: ACTIVE_STATES).where("expires_at is null OR expires_at > ?", Time.current) }
scope :expired, -> { where(state: ACTIVE_STATES).where("expires_at < ?", Time.current) }
scope :canceled, -> { where(state: :canceled) }

has_many :groups
belongs_to :owner, class_name: 'User'
Expand Down Expand Up @@ -36,8 +42,7 @@ def config
end

def is_active?
# allow groups in dunning or on hold to continue using the app
self.state == 'active' or self.state == 'past_due' or self.state == 'on_hold' or (self.state == 'trialing' && self.expires_at > Time.current)
ACTIVE_STATES.include?(state) && (self.expires_at.nil? || self.expires_at > Time.current)
end

def management_link
Expand Down
35 changes: 12 additions & 23 deletions app/serializers/group_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,18 @@ def parent
end

def subscription
sub = cache_fetch(:subscriptions_by_group_id, object.id) { Subscription.new }

if (current_user_membership)
{
max_members: sub.max_members,
max_threads: sub.max_threads,
allow_subgroups: sub.allow_subgroups,
plan: sub.plan,
active: sub.is_active?,
renews_at: sub.renews_at,
expires_at: sub.expires_at,
members_count: sub.members_count
}
else
{
max_members: sub.max_members,
max_threads: sub.max_threads,
allow_subgroups: sub.allow_subgroups,
plan: sub.plan,
active: sub.is_active?,
members_count: sub.members_count
}
end
sub = cache_fetch(:subscriptions_by_group_id, object.id) { object.subscription || Subscription.new }
{
max_members: sub.max_members,
max_threads: sub.max_threads,
allow_subgroups: sub.allow_subgroups,
plan: sub.plan,
state: sub.state,
active: sub.is_active?,
renews_at: sub.renews_at,
expires_at: sub.expires_at,
members_count: sub.members_count
}
end

def include_secret_token?
Expand Down
3 changes: 3 additions & 0 deletions app/services/cleanup_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ def self.delete_orphan_records
[Membership,
MembershipRequest,
Discussion,
Subscription,
DiscussionReader,
Comment,
Poll,
Expand All @@ -17,6 +18,8 @@ def self.delete_orphan_records
end

PaperTrail::Version.where(item_type: 'Motion').delete_all
ActiveStorage::Blob.unattached.where("active_storage_blobs.created_at < ?", 1.day.ago).find_each(&:purge_later)

# ["Comment", "Discussion", "Group", "Membership", "Outcome", "Poll", "Stance", "User"].each do |model|
# table = model.pluralize.downcase
# # puts PaperTrail::Version.joins("left join #{table} on #{table}.id = item_id and item_type = '#{model}'").where("#{table}.id is null").to_sql
Expand Down
1 change: 0 additions & 1 deletion config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ en:
free_trial: Free trial. %{days} days remaining.
trial_expired: Your trial has expired. Upgrade to continue using Loomio.
tooltip: "Our prices are fantastic! Upgrade today and enjoy what Loomio can offer your group."
was_gift_trial: "Your group has been using Loomio for free since %{createdDate}. We are unable to continue providing a free service. Please upgrade to continue using Loomio. <a href='https://help.loomio.org/en/plan-changes/' target='_blank' style='text-decoration: underline;'>Read more.</a>"
was_gift_remaining: "%{days} days remaining."
was_gift_expired: "Your free plan has now expired."

Expand Down
7 changes: 7 additions & 0 deletions db/migrate/20240620003858_simplify_subscriptions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class SimplifySubscriptions < ActiveRecord::Migration[7.0]
def change
Subscription.where(state: :trialing).update_all(state: :active)
Subscription.where(plan: %w[was-gift was-paid]).update_all(plan: :free)
Subscription.where(plan: :free).update_all(payment_method: :none)
end
end
2 changes: 1 addition & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2024_04_14_225428) do
ActiveRecord::Schema[7.0].define(version: 2024_06_20_003858) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "hstore"
Expand Down
45 changes: 0 additions & 45 deletions vue/src/components/group/old_plan_banner.vue

This file was deleted.

4 changes: 0 additions & 4 deletions vue/src/components/group/page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ import AbilityService from '@/shared/services/ability_service';
import GroupService from '@/shared/services/group_service';
import LmoUrlService from '@/shared/services/lmo_url_service';
import { pickBy } from 'lodash-es';
import OldPlanBanner from '@/components/group/old_plan_banner';
export default
{
components: { OldPlanBanner },
data() {
return {
group: null,
Expand Down Expand Up @@ -120,7 +117,6 @@ v-main
span.text--secondary.text--lighten-1 &gt;
space
span.group-page__name.mr-4 {{group.name}}
old-plan-banner(:group="group")
trial-banner(:group="group")
formatted-text.group-page__description(
v-if="group"
Expand Down
25 changes: 9 additions & 16 deletions vue/src/components/group/trial_banner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,12 @@ export default
},
computed: {
hasSubscription() { return this.group.subscription },
isLoggedIn() { return Session.isSignedIn(); },
isWasGift() {
return this.group.subscription.plan === 'was-gift';
},
isTrialing() {
return this.group.membersInclude(Session.user()) && (this.group.subscription.plan === 'trial');
},
isExpired() {
return this.isTrialing && !this.group.subscription.active;
},
isMember() { return this.group.membersInclude(Session.user()) },
isFree() {return this.group.subscription.plan === 'free' },
isTrial() { return this.group.subscription.plan === 'trial' },
isExpired() { return !this.group.subscription.active },
daysRemaining() {
return differenceInDays(parseISO(this.group.subscription.expires_at), new Date) + 1;
},
Expand All @@ -34,16 +30,13 @@ export default
};
</script>
<template lang="pug">
v-alert(outlined color="primary" dense v-if="isTrialing")
v-alert(outlined color="primary" dense v-if="hasSubscription && isLoggedIn && isMember && (isTrial || (isFree && isExpired))")
.d-flex.align-center
div.pr-1(v-if="isWasGift")
span(v-if="isExpired" v-html="$t('current_plan_button.was_gift_expired')")
span(v-if="!isExpired" v-html="$t('current_plan_button.was_gift_remaining', { days: daysRemaining } )")
space
span(v-html="$t('current_plan_button.was_gift_trial', {createdDate: createdDate })")
div.pr-1(v-if="!isWasGift")
div.pr-1(v-if="isTrial")
span(v-if="!isExpired" v-t="{ path: 'current_plan_button.free_trial', args: { days: daysRemaining }}")
span(v-if="isExpired" v-t="'current_plan_button.trial_expired'")
div.pr-1(v-if="isFree")
span(v-html="$t('current_plan_button.was_gift_expired')")
v-spacer
v-btn(
color="primary"
Expand Down

0 comments on commit e6a72dc

Please sign in to comment.