Class: Reward
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Reward
- Extended by:
- Enumerize
- Includes:
- IdentityCache
- Defined in:
- app/models/reward.rb
Overview
typed: ignore frozen_string_literal: true
Constant Summary collapse
- MINIMUM_REWARD_REDEMPTION =
100- CODE =
'REDEEMCODE'
Class Method Summary collapse
- .count_credits(user_id, country_id = nil) ⇒ Object
- .effective_date(reservation, today) ⇒ Object
- .last_reservation(last_reservation_payonsite, last_reservation_prepaid, current_date) ⇒ Object
-
.last_reservation_payonsite(current_date, reservations) ⇒ Object
Get the last reservation pay onsite.
-
.last_reservation_prepaid(current_date, reservations) ⇒ Object
Get the last reservation prepaid.
- .points_expiry_date(user) ⇒ Object
-
.user_points_by_country(user_id) ⇒ Object
get total points by country for a user.
- .user_redeemed_total(user) ⇒ Object
Instance Method Summary collapse
- #cancelled? ⇒ Boolean
- #confirmed? ⇒ Boolean
- #redeemed_amount ⇒ Object
- #to_api ⇒ Object
- #touch_relations ⇒ Object
- #unconfirmed? ⇒ Boolean
-
#update_journal_entry ⇒ Object
Update the journal entry for the user.
Methods inherited from ApplicationRecord
Class Method Details
.count_credits(user_id, country_id = nil) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'app/models/reward.rb', line 118 def count_credits(user_id, country_id = nil) # set default country_id 218, which is Thailand user = User.fetch(user_id) country_id = country_id.presence || user.country_id query = "SELECT GREATEST(SUM(rewards.points_total) - SUM(rewards.points_pending),0) AS total FROM rewards WHERE rewards.user_id = #{user_id} AND rewards.country_id = #{country_id}" # query = "SELECT COALESCE((SUM(t.points_total) - SUM(t.points_pending)), 0) as total FROM ( # SELECT SUM(points_total) as points_total, 0 as points_pending FROM rewards WHERE points_total <= 0 AND user_id = #{user_id} # union # SELECT SUM(points_total) as points_total, 0 as points_pending FROM rewards WHERE points_total > 0 AND user_id = #{user_id} and expiry_date >= #{Time.current.to_date} # union # SELECT 0 as points_total, SUM(points_pending) as points_pending FROM rewards WHERE user_id = #{user_id} and expiry_date >= #{Time.current.to_date} # ) as t" Reward.find_by_sql([query]).first['total'].to_i rescue StandardError => e APMErrorHandler.report 'failed calculate user rewards credit', error: e, user_id: user_id 0 end |
.effective_date(reservation, today) ⇒ Object
171 172 173 174 175 176 177 |
# File 'app/models/reward.rb', line 171 def effective_date(reservation, today) if reservation.date.present? && reservation.date < today reservation.date else reservation.created_at.to_date end end |
.last_reservation(last_reservation_payonsite, last_reservation_prepaid, current_date) ⇒ Object
179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'app/models/reward.rb', line 179 def last_reservation(last_reservation_payonsite, last_reservation_prepaid, current_date) if last_reservation_payonsite.present? && last_reservation_prepaid.present? if effective_date(last_reservation_payonsite, current_date) < effective_date(last_reservation_prepaid, current_date) last_reservation_prepaid else last_reservation_payonsite end else last_reservation_payonsite || last_reservation_prepaid end end |
.last_reservation_payonsite(current_date, reservations) ⇒ Object
Get the last reservation pay onsite
148 149 150 151 152 153 154 155 156 157 |
# File 'app/models/reward.rb', line 148 def last_reservation_payonsite(current_date, reservations) reservations.past.order('reservations.id DESC').limit(30). max_by do |res| if res.date.present? && res.date < current_date res.date else res.created_at.to_date end end end |
.last_reservation_prepaid(current_date, reservations) ⇒ Object
Get the last reservation prepaid
160 161 162 163 164 165 166 167 168 169 |
# File 'app/models/reward.rb', line 160 def last_reservation_prepaid(current_date, reservations) reservations.joins(:charges).order('reservations.id DESC').limit(30). max_by do |res| if res.date.present? && res.date < current_date res.date else res.created_at.to_date end end end |
.points_expiry_date(user) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'app/models/reward.rb', line 192 def points_expiry_date(user) # Get the last reservation user_reservations = user.reservations.reached_goal_scope current_date = Time.use_zone(user.time_zone) { Date.current } last_reservation = last_reservation(last_reservation_payonsite(current_date, user_reservations), last_reservation_prepaid(current_date, user_reservations), current_date) # Set the minimum expiry date # Since this rules will be announced at 1st september 2024, # all of the expiration dates in august will be extended until 30th september 2024 # https://app.clickup.com/9003122396/v/dc/8ca1fpw-7922/8ca1fpw-40216 min_expiry_date = Date.new(2024, 10, 31) return user.get_credits.positive? ? min_expiry_date : nil if last_reservation.blank? time_zone = last_reservation.restaurant.time_zone if last_reservation.payment_type_provider.present? reservation_time_past = (last_reservation.reservation_time + 24.hours).past? start_date = reservation_time_past ? last_reservation.date : last_reservation.created_at.in_time_zone(time_zone).to_date else start_date = last_reservation.date end # Calculate expiry date as end of the month 4 months after the last booking date points_expiry_date = [(start_date + 4.months).in_time_zone(time_zone).end_of_month.to_date, min_expiry_date.to_date].max # Check if last downgrade date should override the calculated points expiry date last_downgrade_date = user.user_benefit_expiry&.expires_at&.to_date [points_expiry_date, last_downgrade_date].compact.max end |
.user_points_by_country(user_id) ⇒ Object
get total points by country for a user
109 110 111 112 113 114 115 116 |
# File 'app/models/reward.rb', line 109 def user_points_by_country(user_id) rewards_map = grouped_rewards_by_country(user_id) build_country_credits(rewards_map) rescue StandardError => e APMErrorHandler.report 'failed calculate user rewards credit', error: e, user_id: user_id [] end |
.user_redeemed_total(user) ⇒ Object
142 143 144 145 |
# File 'app/models/reward.rb', line 142 def user_redeemed_total(user) amount = user.rewards.redeemed_points.inject(0) { |n, r| n + r.points_total.to_i - r.points_pending.to_i } amount * -1 end |
Instance Method Details
#cancelled? ⇒ Boolean
60 61 62 |
# File 'app/models/reward.rb', line 60 def cancelled? points_total.negative? && points_pending.negative? end |
#confirmed? ⇒ Boolean
52 53 54 |
# File 'app/models/reward.rb', line 52 def confirmed? redeemed == true end |
#redeemed_amount ⇒ Object
96 97 98 |
# File 'app/models/reward.rb', line 96 def redeemed_amount points_total * -1 end |
#to_api ⇒ Object
100 101 102 103 104 105 |
# File 'app/models/reward.rb', line 100 def to_api data = attributes.dup excluded_attributes = %w[created_at updated_at] data.delete_if { |k, _v| excluded_attributes.include?(k) } data.merge(credits: user.get_credits) end |
#touch_relations ⇒ Object
46 47 48 49 50 |
# File 'app/models/reward.rb', line 46 def touch_relations TouchWorker.perform_async('User', user_id) if user_id.present? TouchWorker.perform_async('Reservation', reservation_id) if reservation_id.present? TouchWorker.perform_async('TicketTransaction', ticket_transaction_id) if ticket_transaction_id.present? end |
#unconfirmed? ⇒ Boolean
56 57 58 |
# File 'app/models/reward.rb', line 56 def unconfirmed? !confirmed? end |
#update_journal_entry ⇒ Object
Update the journal entry for the user
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'app/models/reward.rb', line 65 def update_journal_entry return if user.blank? entry = journal_entry.presence || {} previous_total = calculate_previous_total new_points_pending = points_pending.to_i # there's possibility that the points_pending (total points) is not valid # when race condition happens # points_pending (total points) already calculated in PointsExpired # so we need to check if the points_pending is not equal to the total points is_inactive_points = description&.include?('Inactive account points expiry') points_total_not_match = new_points_pending != total_from_previous_rewards if is_inactive_points && points_total_not_match new_points_pending = total_from_previous_rewards end reward_points = points_total.to_i - new_points_pending total = [previous_total + reward_points, 0].max entry[Time.zone.now] = { previous_points: previous_total, this_reward_point: reward_points, total: total, } update_column(:journal_entry, entry) end |