Class: UsageCredits::Fulfillment

Inherits:
ApplicationRecord show all
Defined in:
lib/usage_credits/models/fulfillment.rb

Overview

A Fulfillment represents a credit-giving action triggered by a purchase, including credit pack purchases and subscriptions. Some of this credit-giving actions are repeating in nature (i.e.: subscriptions), some are not (one-time purchases)

Instance Method Summary collapse

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/usage_credits/models/fulfillment.rb', line 73

def active?
  !stopped?
end

#calculate_next_fulfillmentObject



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/usage_credits/models/fulfillment.rb', line 77

def calculate_next_fulfillment
  return nil unless recurring?
  return nil if stopped?
  return nil if next_fulfillment_at.nil?

  # If next_fulfillment_at is in the past (e.g. due to missed fulfillments or errors),
  # we use current time as the base to avoid scheduling multiple rapid fulfillments.
  # This ensures smooth recovery from missed fulfillments by scheduling the next one
  # from the current time rather than the missed fulfillment time.
  base_time = next_fulfillment_at > Time.current ? next_fulfillment_at : Time.current

  base_time + UsageCredits::PeriodParser.parse_period(fulfillment_period)
end

#due_for_fulfillment?Boolean

Returns:

  • (Boolean)


57
58
59
60
61
62
63
# File 'lib/usage_credits/models/fulfillment.rb', line 57

def due_for_fulfillment?
  return false unless next_fulfillment_at.present?
  return false if stopped?
  return false if last_fulfilled_at.present? && next_fulfillment_at <= last_fulfilled_at

  next_fulfillment_at <= Time.current
end

#metadataObject

Get metadata with indifferent access (string/symbol keys) Returns empty hash if nil (for MySQL compatibility where JSON columns can't have defaults)



30
31
32
# File 'lib/usage_credits/models/fulfillment.rb', line 30

def 
  @indifferent_metadata ||= ActiveSupport::HashWithIndifferentAccess.new(super || {})
end

#metadata=(hash) ⇒ Object

Set metadata, ensuring consistent storage format



35
36
37
38
# File 'lib/usage_credits/models/fulfillment.rb', line 35

def metadata=(hash)
  @indifferent_metadata = nil  # Clear cache
  super(hash.is_a?(Hash) ? hash.to_h : {})
end

#recurring?Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/usage_credits/models/fulfillment.rb', line 65

def recurring?
  fulfillment_period.present?
end

#reloadObject

Clear metadata cache on reload to ensure fresh data from database



41
42
43
44
# File 'lib/usage_credits/models/fulfillment.rb', line 41

def reload(*)
  @indifferent_metadata = nil
  super
end

#stopped?Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/usage_credits/models/fulfillment.rb', line 69

def stopped?
  stops_at.present? && stops_at <= Time.current
end