1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-20 14:54:15 +01:00
fab-manager/app/models/subscription.rb
Sylvain c7a59c8cb7 WIP: refactoring to singularize the booking process
We need to achieve only one process for all booking, not one for subscription, one for reservations, etc.
Moreover we must store one object per invoice_item/payment_schedule_object and stop using Invoice.invoiced or PaymentSchedule.scheduled
2021-05-21 18:25:18 +02:00

145 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 :invoices, as: :invoiced, 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(
invoiced_id: od.id,
invoiced_type: 'OfferDay',
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)
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