Class: SpreeCmCommissioner::VotingCredits::ClaimFreeVotes
- Inherits:
-
Object
- Object
- SpreeCmCommissioner::VotingCredits::ClaimFreeVotes
- Includes:
- Spree::ServiceModule::Base
- Defined in:
- app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb
Instance Attribute Summary collapse
-
#show ⇒ Object
readonly
Returns the value of attribute show.
-
#tenant_id ⇒ Object
readonly
Returns the value of attribute tenant_id.
-
#user ⇒ Object
readonly
Returns the value of attribute user.
-
#votable_id ⇒ Object
readonly
Returns the value of attribute votable_id.
-
#votable_type ⇒ Object
readonly
Returns the value of attribute votable_type.
Instance Method Summary collapse
-
#call ⇒ Object
Returns the VotingCredit after granting free votes, or returns msg if free votes cannot be granted (e.g. limit reached).
-
#initialize(show:, user:, tenant_id:, votable_type: nil, votable_id: nil) ⇒ ClaimFreeVotes
constructor
A new instance of ClaimFreeVotes.
-
#votable ⇒ Object
Always find votable by the show’s credit_votable_type, to ensure consistency with where the credits are allocated.
Constructor Details
#initialize(show:, user:, tenant_id:, votable_type: nil, votable_id: nil) ⇒ ClaimFreeVotes
Returns a new instance of ClaimFreeVotes.
43 44 45 46 47 48 49 |
# File 'app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb', line 43 def initialize(show:, user:, tenant_id:, votable_type: nil, votable_id: nil) @show = show @user = user @tenant_id = tenant_id @votable_type = votable_type @votable_id = votable_id end |
Instance Attribute Details
#show ⇒ Object (readonly)
Returns the value of attribute show.
41 42 43 |
# File 'app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb', line 41 def show @show end |
#tenant_id ⇒ Object (readonly)
Returns the value of attribute tenant_id.
41 42 43 |
# File 'app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb', line 41 def tenant_id @tenant_id end |
#user ⇒ Object (readonly)
Returns the value of attribute user.
41 42 43 |
# File 'app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb', line 41 def user @user end |
#votable_id ⇒ Object (readonly)
Returns the value of attribute votable_id.
41 42 43 |
# File 'app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb', line 41 def votable_id @votable_id end |
#votable_type ⇒ Object (readonly)
Returns the value of attribute votable_type.
41 42 43 |
# File 'app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb', line 41 def votable_type @votable_type end |
Instance Method Details
#call ⇒ Object
Returns the VotingCredit after granting free votes, or returns msg if free votes cannot be granted (e.g. limit reached).
53 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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb', line 53 def call # rubocop:disable Metrics/AbcSize return success(nil) unless show.free_vote_limit_type idempotency_key = show.free_vote_idempotency_key(user_id: user.id, votable_id: votable_id) # idempotency_key is uniquely indexed — faster than scoping through user.voting_transactions association. if SpreeCmCommissioner::VotingCreditTransaction.exists?(idempotency_key: idempotency_key) return failure(nil, 'Free votes have already been claimed') end amount = show.free_vote_limit.to_i return failure(nil, "Free votes are not available for #{show.voting_credit_scope}") if amount <= 0 case show.free_vote_limit_type when 'per_episode', 'per_voting_session' if votable_type.blank? || votable_id.blank? return failure(nil, 'votable_type and votable_id are required for per_episode/per_voting_session') end end credit = nil ActiveRecord::Base.transaction do credit = user.voting_credits.active.find_or_create_by!( tenant_id: tenant_id, votable: votable ) { |c| c.category = :promo } credit.with_lock do credit.free_votes_amount += amount credit.save! end credit.voting_credit_transactions.create!( tenant_id: tenant_id, action: :free_claim, amount: amount, originator: show, free_claim_votable_id: votable_id, user_total_amount: credit.available_votes, memo: "Free claim: #{amount} votes | credit_scope: #{show.voting_credit_scope} | key: #{idempotency_key}" ) end success(credit) rescue ActiveRecord::RecordNotUnique # Two concurrent requests can both pass the existence check before either commits. # The one that loses the unique-index race lands here — treat it as already claimed. failure(nil, 'Free votes have already been claimed') rescue StandardError => e failure(nil, e.) end |
#votable ⇒ Object
Always find votable by the show’s credit_votable_type, to ensure consistency with where the credits are allocated. Resolves through the show association to prevent claiming against unrelated votable_ids.
109 110 111 112 113 114 115 116 |
# File 'app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb', line 109 def votable case show.credit_votable_type when 'SpreeCmCommissioner::Show' then show when 'SpreeCmCommissioner::ShowEpisode' then show.episodes.find(votable_id) when 'SpreeCmCommissioner::VotingSession' then show.voting_sessions.find(votable_id) else raise ActiveRecord::RecordNotFound, "Unknown credit_votable_type: #{show.credit_votable_type}" end end |