mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-12-01 12:24:28 +01:00
143 lines
4.2 KiB
Ruby
143 lines
4.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Subscription is an active or archived subscription of an User to a Plan
|
|
class Subscription < ApplicationRecord
|
|
include NotifyWith::NotificationAttachedObject
|
|
|
|
belongs_to :plan
|
|
belongs_to :statistic_profile
|
|
|
|
has_one :payment_schedule, as: :scheduled, dependent: :destroy
|
|
has_one :payment_gateway_object, as: :item
|
|
has_many :invoice_items, as: :object, dependent: :destroy
|
|
has_many :offer_days, dependent: :destroy
|
|
|
|
validates_presence_of :plan_id
|
|
validates_with SubscriptionGroupValidator
|
|
|
|
# creation
|
|
before_create :set_expiration_date
|
|
after_save :notify_member_subscribed_plan
|
|
after_save :notify_admin_subscribed_plan
|
|
after_save :notify_partner_subscribed_plan, if: :of_partner_plan?
|
|
after_commit :update_credits, on: :create
|
|
|
|
def generate_and_save_invoice(operator_profile_id)
|
|
generate_invoice(operator_profile_id).save
|
|
end
|
|
|
|
def expire(time)
|
|
if !expired?
|
|
update_columns(expiration_date: time, canceled_at: time)
|
|
notify_admin_subscription_canceled
|
|
notify_member_subscription_canceled
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
def expired?
|
|
expired_at <= DateTime.current
|
|
end
|
|
|
|
def expired_at
|
|
last_offered = offer_days.order(:end_at).last
|
|
return last_offered.end_at if last_offered
|
|
|
|
expiration_date
|
|
end
|
|
|
|
def free_extend(expiration, operator_profile_id)
|
|
return false if expiration <= expired_at
|
|
|
|
od = offer_days.create(start_at: expired_at, end_at: expiration)
|
|
invoice = Invoice.new(
|
|
invoicing_profile: user.invoicing_profile,
|
|
statistic_profile: user.statistic_profile,
|
|
operator_profile_id: operator_profile_id,
|
|
total: 0
|
|
)
|
|
invoice.invoice_items.push InvoiceItem.new(amount: 0, description: plan.name, subscription_id: id, object: od)
|
|
invoice.save
|
|
|
|
if save
|
|
notify_subscription_extended(true)
|
|
return true
|
|
end
|
|
false
|
|
end
|
|
|
|
def user
|
|
statistic_profile.user
|
|
end
|
|
|
|
def original_payment_schedule
|
|
# if the payment schedule was associated with this subscription, return it directly
|
|
return payment_schedule if payment_schedule
|
|
|
|
# if it was associated with a reservation, query payment schedule from one of its items
|
|
PaymentScheduleItem.where("cast(details->>'subscription_id' AS int) = ?", id).first&.payment_schedule
|
|
end
|
|
|
|
private
|
|
|
|
def notify_member_subscribed_plan
|
|
NotificationCenter.call type: 'notify_member_subscribed_plan',
|
|
receiver: user,
|
|
attached_object: self
|
|
end
|
|
|
|
def notify_admin_subscribed_plan
|
|
NotificationCenter.call type: 'notify_admin_subscribed_plan',
|
|
receiver: User.admins,
|
|
attached_object: self
|
|
end
|
|
|
|
def notify_admin_subscription_canceled
|
|
NotificationCenter.call type: 'notify_admin_subscription_canceled',
|
|
receiver: User.admins_and_managers,
|
|
attached_object: self
|
|
end
|
|
|
|
def notify_member_subscription_canceled
|
|
NotificationCenter.call type: 'notify_member_subscription_canceled',
|
|
receiver: user,
|
|
attached_object: self
|
|
end
|
|
|
|
def notify_partner_subscribed_plan
|
|
NotificationCenter.call type: 'notify_partner_subscribed_plan',
|
|
receiver: plan.partners,
|
|
attached_object: self
|
|
end
|
|
|
|
def notify_subscription_extended(free_days)
|
|
meta_data = {}
|
|
meta_data[:free_days] = true if free_days
|
|
NotificationCenter.call type: :notify_member_subscription_extended,
|
|
receiver: user,
|
|
attached_object: self,
|
|
meta_data: meta_data
|
|
|
|
NotificationCenter.call type: :notify_admin_subscription_extended,
|
|
receiver: User.admins_and_managers,
|
|
attached_object: self,
|
|
meta_data: meta_data
|
|
end
|
|
|
|
def set_expiration_date
|
|
start_at = DateTime.current.in_time_zone
|
|
self.expiration_date = start_at + plan.duration
|
|
end
|
|
|
|
def of_partner_plan?
|
|
plan.is_a?(PartnerPlan)
|
|
end
|
|
|
|
# init the user's credits
|
|
def update_credits
|
|
UsersCredits::Manager.new(user: user).reset_credits
|
|
end
|
|
end
|