Module: ReferralBox

Defined in:
lib/referral_box.rb,
lib/referral_box/engine.rb,
lib/referral_box/version.rb,
lib/referral_box/configuration.rb,
lib/referral_box/models/transaction.rb,
lib/referral_box/models/referral_log.rb,
app/helpers/referral_box/dashboard_helper.rb,
app/helpers/referral_box/application_helper.rb,
app/controllers/referral_box/tracking_controller.rb,
app/controllers/referral_box/dashboard_controller.rb,
lib/generators/referral_box/install/install_generator.rb

Defined Under Namespace

Modules: ApplicationHelper, DashboardHelper, Generators Classes: Configuration, DashboardController, Engine, ReferralLog, TrackingController, Transaction

Constant Summary collapse

VERSION =
"0.1.10"

Class Method Summary collapse

Class Method Details

.balance(user) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/referral_box.rb', line 82

def balance(user)
  return 0 unless user

  Transaction.where(user: user)
            .where("expires_at IS NULL OR expires_at > ?", Time.current)
            .sum(:points)
end

.configurationObject



20
21
22
# File 'lib/referral_box.rb', line 20

def configuration
  @configuration ||= Configuration.new
end

.configure {|configuration| ... } ⇒ Object

Yields:



16
17
18
# File 'lib/referral_box.rb', line 16

def configure
  yield configuration
end

.earn_points(user, amount, event: nil) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/referral_box.rb', line 24

def earn_points(user, amount, event: nil)
  return false unless user && amount.positive?

  # Apply reward modifier based on tier
  modifier = configuration.reward_modifier&.call(user) || 1.0
  final_amount = (amount * modifier).round

  # Calculate expiration date
  expiry_days = configuration.points_expiry_days
  expires_at = expiry_days ? Time.current + expiry_days.days : nil

  # Create transaction
  transaction = Transaction.create!(
    user: user,
    points: final_amount,
    transaction_type: "earn",
    event_data: event&.as_json,
    expires_at: expires_at,
    description: "Earned #{final_amount} points"
  )

  # Update user tier if needed
  update_user_tier(user)

  transaction
rescue => e
  Rails.logger.error "ReferralBox: Failed to earn points: #{e.message}"
  false
end

.process_referral_signup(referee, ref_code) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/referral_box.rb', line 129

def (referee, ref_code)
  return false unless referee && ref_code.present?

  # Find the referral log
  referral_log = ReferralLog.where(referral_code: ref_code)
                           .where(referee_id: nil)
                           .order(clicked_at: :desc)
                           .first

  return false unless referral_log

  # Find the referrer
  referrer = find_user_by_referral_code(ref_code)
  return false unless referrer

  # Update referral log
  referral_log.update!(
    referee: referee,
    signed_up_at: Time.current
  )

  # Update referee's referrer
  referee.update!(referrer: referrer)

  # Process referral rewards
  if configuration.referral_reward
    configuration.referral_reward.call(referrer, referee)
  end

  true
rescue => e
  Rails.logger.error "ReferralBox: Failed to process referral signup: #{e.message}"
  false
end

.redeem_points(user, points, offer: nil) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/referral_box.rb', line 54

def redeem_points(user, points, offer: nil)
  return false unless user && points.positive?

  current_balance = balance(user)
  return false if current_balance < points

  # Calculate cost using custom rule if provided
  cost = if configuration.redeem_rule
    configuration.redeem_rule.call(user, offer)
  else
    points
  end

  # Create transaction
  transaction = Transaction.create!(
    user: user,
    points: -cost,
    transaction_type: "redeem",
    offer_data: offer&.as_json,
    description: "Redeemed #{cost} points"
  )

  transaction
rescue => e
  Rails.logger.error "ReferralBox: Failed to redeem points: #{e.message}"
  false
end

.tier(user) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/referral_box.rb', line 90

def tier(user)
  return nil unless user && configuration.tier_thresholds.present?

  balance = self.balance(user)
  thresholds = configuration.tier_thresholds

  # Find the highest tier the user qualifies for
  thresholds.sort_by { |_, points| points }.reverse.each do |tier_name, required_points|
    return tier_name if balance >= required_points
  end

  nil
end

.track_referral(ref_code:, user_agent: nil, ip_address: nil, referrer: nil, device_data: nil) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/referral_box.rb', line 104

def track_referral(ref_code:, user_agent: nil, ip_address: nil, referrer: nil, device_data: nil)
  return false unless ref_code.present?

  # Extract device and geo data from device_data parameter
  device_type = device_data&.dig("device_type")
  browser = device_data&.dig("browser")
  geo_data = device_data&.dig("geo_data")
  device_info = device_data&.except("device_type", "browser", "geo_data", "collected_at")

  ReferralLog.create!(
    referral_code: ref_code,
    user_agent: user_agent,
    ip_address: ip_address,
    referrer: referrer,
    clicked_at: Time.current,
    device_type: device_type,
    browser: browser,
    geo_data: geo_data,
    device_data: device_info
  )
rescue => e
  Rails.logger.error "ReferralBox: Failed to track referral: #{e.message}"
  false
end