2019-10-07 12:08:08 +02:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
# Plan is a generic description of a subscription plan, which can be subscribed by a member to benefit from advantageous prices.
|
|
|
|
# Subscribers can also get some Credits for some reservable items
|
2020-03-25 10:16:47 +01:00
|
|
|
class Plan < ApplicationRecord
|
2016-03-23 18:39:41 +01:00
|
|
|
belongs_to :group
|
|
|
|
|
|
|
|
has_many :credits, dependent: :destroy
|
2018-11-26 15:14:43 +01:00
|
|
|
has_many :training_credits, -> { where(creditable_type: 'Training') }, class_name: 'Credit'
|
|
|
|
has_many :machine_credits, -> { where(creditable_type: 'Machine') }, class_name: 'Credit'
|
|
|
|
has_many :space_credits, -> { where(creditable_type: 'Space') }, class_name: 'Credit'
|
2016-03-23 18:39:41 +01:00
|
|
|
has_many :subscriptions
|
|
|
|
has_one :plan_file, as: :viewable, dependent: :destroy
|
|
|
|
has_many :prices, dependent: :destroy
|
|
|
|
|
2017-01-09 10:54:30 +01:00
|
|
|
extend FriendlyId
|
2017-03-21 15:47:25 +01:00
|
|
|
friendly_id :base_name, use: :slugged
|
2017-01-09 10:54:30 +01:00
|
|
|
|
2016-03-23 18:39:41 +01:00
|
|
|
accepts_nested_attributes_for :prices
|
|
|
|
accepts_nested_attributes_for :plan_file, allow_destroy: true, reject_if: :all_blank
|
|
|
|
|
|
|
|
after_create :create_machines_prices
|
2017-03-01 16:45:05 +01:00
|
|
|
after_create :create_spaces_prices
|
2016-03-23 18:39:41 +01:00
|
|
|
after_create :create_statistic_type
|
2019-09-24 11:41:07 +02:00
|
|
|
after_create :set_name
|
2020-10-27 16:03:20 +01:00
|
|
|
after_create :create_stripe_price
|
2016-03-23 18:39:41 +01:00
|
|
|
|
|
|
|
validates :amount, :group, :base_name, presence: true
|
|
|
|
validates :interval_count, numericality: { only_integer: true, greater_than_or_equal_to: 1 }
|
2019-01-16 12:10:07 +01:00
|
|
|
validates :interval_count, numericality: { less_than: 13 }, if: proc { |plan| plan.interval == 'month' }
|
|
|
|
validates :interval_count, numericality: { less_than: 53 }, if: proc { |plan| plan.interval == 'week' }
|
2018-11-26 11:33:48 +01:00
|
|
|
validates :interval, inclusion: { in: %w[year month week] }
|
2017-03-21 15:47:25 +01:00
|
|
|
validates :base_name, :slug, presence: true
|
2016-03-23 18:39:41 +01:00
|
|
|
|
|
|
|
def self.create_for_all_groups(plan_params)
|
|
|
|
plans = []
|
2018-11-26 11:33:48 +01:00
|
|
|
Group.all_except_admins.each do |group|
|
|
|
|
plan = if plan_params[:type] == 'PartnerPlan'
|
|
|
|
PartnerPlan.new(plan_params.except(:group_id, :type))
|
|
|
|
else
|
|
|
|
Plan.new(plan_params.except(:group_id, :type))
|
|
|
|
end
|
2016-03-23 18:39:41 +01:00
|
|
|
plan.group = group
|
|
|
|
if plan.save
|
|
|
|
plans << plan
|
|
|
|
else
|
|
|
|
plans.each(&:destroy)
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
end
|
2018-11-26 11:33:48 +01:00
|
|
|
plans
|
2016-03-23 18:39:41 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def destroyable?
|
|
|
|
subscriptions.empty?
|
|
|
|
end
|
|
|
|
|
|
|
|
def create_machines_prices
|
|
|
|
Machine.all.each do |machine|
|
2019-09-19 15:34:21 +02:00
|
|
|
Price.create(priceable: machine, plan: self, group_id: group_id, amount: 0)
|
2016-03-23 18:39:41 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-03-01 16:45:05 +01:00
|
|
|
def create_spaces_prices
|
|
|
|
Space.all.each do |space|
|
2019-09-19 15:34:21 +02:00
|
|
|
Price.create(priceable: space, plan: self, group_id: group_id, amount: 0)
|
2017-03-01 16:45:05 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-03-23 18:39:41 +01:00
|
|
|
def duration
|
|
|
|
interval_count.send(interval)
|
|
|
|
end
|
|
|
|
|
|
|
|
def human_readable_duration
|
|
|
|
i18n_key = "duration.#{interval}"
|
2018-11-26 11:33:48 +01:00
|
|
|
I18n.t(i18n_key, count: interval_count).to_s
|
2016-03-23 18:39:41 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def human_readable_name(opts = {})
|
2018-11-26 11:33:48 +01:00
|
|
|
result = base_name.to_s
|
2016-03-23 18:39:41 +01:00
|
|
|
result += " - #{group.slug}" if opts[:group]
|
|
|
|
result + " - #{human_readable_duration}"
|
|
|
|
end
|
|
|
|
|
|
|
|
# must be publicly accessible for the migration
|
|
|
|
def create_statistic_type
|
2018-11-26 11:33:48 +01:00
|
|
|
stat_index = StatisticIndex.where(es_type_key: 'subscription')
|
2020-04-01 17:25:55 +02:00
|
|
|
type = find_statistic_type
|
2018-11-26 11:33:48 +01:00
|
|
|
if type.nil?
|
|
|
|
type = StatisticType.create!(
|
|
|
|
statistic_index_id: stat_index.first.id,
|
|
|
|
key: duration.to_i,
|
2020-04-01 17:25:55 +02:00
|
|
|
label: "#{I18n.t('statistics.duration')} : #{human_readable_duration}",
|
2018-11-26 11:33:48 +01:00
|
|
|
graph: true,
|
|
|
|
simple: true
|
|
|
|
)
|
2016-03-23 18:39:41 +01:00
|
|
|
end
|
|
|
|
subtype = create_statistic_subtype
|
|
|
|
create_statistic_association(type, subtype)
|
|
|
|
end
|
|
|
|
|
2020-04-01 17:25:55 +02:00
|
|
|
def find_statistic_type
|
|
|
|
stat_index = StatisticIndex.where(es_type_key: 'subscription')
|
|
|
|
type = StatisticType.find_by(statistic_index_id: stat_index.first.id, key: duration.to_i)
|
|
|
|
return type if type
|
|
|
|
|
|
|
|
StatisticType.where(statistic_index_id: stat_index.first.id).where('label LIKE ?', "%#{human_readable_duration}%").first
|
|
|
|
end
|
|
|
|
|
2016-03-23 18:39:41 +01:00
|
|
|
private
|
2018-11-26 11:33:48 +01:00
|
|
|
|
2016-03-23 18:39:41 +01:00
|
|
|
def create_statistic_subtype
|
2018-11-26 11:33:48 +01:00
|
|
|
StatisticSubType.create!(key: slug, label: name)
|
2016-03-23 18:39:41 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def create_statistic_association(stat_type, stat_subtype)
|
2018-11-26 11:33:48 +01:00
|
|
|
if !stat_type.nil? && !stat_subtype.nil?
|
|
|
|
StatisticTypeSubType.create!(statistic_type: stat_type, statistic_sub_type: stat_subtype)
|
2016-03-23 18:39:41 +01:00
|
|
|
else
|
2019-10-07 12:08:08 +02:00
|
|
|
puts 'ERROR: Unable to create the statistics association for the new plan. ' \
|
2016-03-23 18:39:41 +01:00
|
|
|
'Possible causes: the type or the subtype were not created successfully.'
|
|
|
|
end
|
|
|
|
end
|
2019-09-24 11:41:07 +02:00
|
|
|
|
|
|
|
def set_name
|
|
|
|
update_columns(name: human_readable_name)
|
|
|
|
end
|
2020-10-27 16:03:20 +01:00
|
|
|
|
|
|
|
def create_stripe_price
|
|
|
|
price = Stripe::Price.create(
|
|
|
|
{
|
|
|
|
currency: Setting.get('currency'),
|
|
|
|
unit_amount: amount,
|
|
|
|
metadata: { plan_id: id }
|
|
|
|
},
|
|
|
|
{ api_key: Setting.get('stripe_secret_key') }
|
|
|
|
)
|
|
|
|
update_columns(stp_price_id: price.id)
|
|
|
|
rescue Stripe::StripeError => e
|
|
|
|
logger.error e
|
|
|
|
end
|
2016-03-23 18:39:41 +01:00
|
|
|
end
|