Guest User

Untitled

a guest
Jul 19th, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.81 KB | None | 0 0
  1. ## Hold.rb
  2.  
  3. # require 'hold_states'
  4. require 'hold_commands'
  5.  
  6. class Hold < ActiveRecord::Base
  7. acts_as_tree
  8. include AlterEgo
  9.  
  10. state :active, :default => true do
  11. handle(:can_cancel?){|user_or_code|
  12. p("should be user_or_code but is context: #{user_or_code}")
  13. is_owner?(user_or_code) || root.is_owner?(user_or_code)
  14. }
  15. handle(:can_edit?){|user_or_code| is_owner?(user_or_code) || root.is_owner?(user_or_code) }
  16. handle(:state_text){ "Waiting for #{email_address} to purchase" }
  17. handle(:timer_amount){
  18. d = (expires_at.utc - Time.now.utc).to_i
  19. [d/3600, d%3600/60, d%3600%60]
  20. }
  21.  
  22. transition(:to => :expired, :on => :expire!, :if => Proc.new{|r| r.expires_at < Time.now && !r.new_record?})
  23. transition(:to => :deleted, :on => :delete!)
  24. transition(:to => :cancelled, :on => :cancel!)
  25. transition(:to => :purchased, :on => :purchase!)
  26. end
  27.  
  28.  
  29. # include HoldStates # Contains all state based behaviors
  30. include HoldCommands # Contains all of the commands that can be executed
  31.  
  32. MAX_TIMER_AMOUNT = [4.hours, 0.minutes, 0.seconds]
  33.  
  34. attr_accessor :message, :target, :offers_for_transfer, :split_email
  35.  
  36. belongs_to :user
  37. belongs_to :offerset
  38. has_many :held_tickets
  39. named_scope :active, :conditions => "holds.state='active'"
  40.  
  41. before_validation_on_create :generate_invite_code, :set_timer
  42. before_validation Proc.new{|r| r.write_attribute(:state, r.state.to_s) }
  43. after_create Proc.new{|r| HoldMailer.deliver_new_seat_pause(r) if r == r.root}
  44.  
  45. validates_presence_of :expires_at, :offerset_id
  46. validates_presence_of :email_address, :unless => Proc.new{|r| r.user}
  47. validates_presence_of :invite_code, :unless => Proc.new{|r| r.user}
  48. validate_on_create :prior_hold_does_not_exist
  49. validate :offers_are_valid
  50.  
  51. class << self
  52. def assign_owner_by_invite_codes(user, invite_codes)
  53. user.holds << Hold.find(:all, :conditions => {:user_id => nil, :invite_code => invite_codes})
  54. user.save
  55. end
  56.  
  57. def expire_holds!
  58. all(:conditions => ["state='active' AND expires_at < ?", Time.now.utc]).each do |h|
  59. puts("EXPIRE_HOLDS:: expiring hold #{h.id}")
  60. end
  61. end
  62.  
  63. def for_user_and_offerset(user, offerset)
  64. return nil unless user && offerset
  65. user.holds.active.find(:first, :conditions => {:offerset_id => offerset.id})
  66. end
  67. end
  68.  
  69. def auto_start_split_wizard?
  70. read_attribute('hold_type') == 1 && hold_type == 'seat_pause'
  71. end
  72.  
  73. def belongs_to_essential?
  74. ignore_nil{user.essential?}
  75. end
  76.  
  77. def child_of_a?(hold_type)
  78. ignore_nil{parent.hold_type} == hold_type
  79. end
  80.  
  81. def descendants
  82. children.map(&:descendants).flatten + children
  83. end
  84.  
  85. def email_address
  86. read_attribute(:email_address) || ignore_nil{user.email}
  87. end
  88.  
  89. def expires_at=(time)
  90. # we cant allow the specified time to go past the offerset deadline
  91. if offerset && Time.now.utc >= offerset.expires_at.utc
  92. raise HoldError.new("Sorry, we are unable to give you more time for this hold.")
  93. elsif offerset && time.utc >= offerset.expires_at.utc
  94. time = offerset.expires_at.utc
  95. end
  96.  
  97. # if this is a new record, we simply want to set the expires at so the save hits it
  98. if new_record?
  99. write_attribute(:expires_at, time)
  100. else
  101. Hold.connection.execute("UPDATE holds SET expires_at='#{time.utc.to_s(:db)}' WHERE id IN (#{group.map(&:id)*', '})")
  102. end
  103. end
  104.  
  105. def group
  106. ([self, root] + root.descendants).uniq.compact
  107. end
  108.  
  109. def historic_quantity
  110. held_tickets.inject(0){|total, ticket| total += ticket.historic_quantity_held}
  111. end
  112.  
  113. def historic_quantity_for_group
  114. group.inject(0){|total, hold| total += hold.historic_quantity_held}
  115. end
  116.  
  117. def hold_type
  118. if children(true).active.empty?
  119. 'seat_pause'
  120. elsif !children(true).active.empty? && quantity_held == 0
  121. 'transfer'
  122. elsif !children(true).active.empty? && quantity_held > 0
  123. 'group'
  124. end
  125. end
  126.  
  127. def is_owner?(user_or_code)
  128. Array(user_or_code).include?(user) || Array(user_or_code).include?(invite_code)
  129. end
  130.  
  131. def offers
  132. held_tickets.map(&:offer)
  133. end
  134.  
  135. def offers=(offer_hash)
  136. Hold.transaction do
  137. held_tickets.delete_all
  138. offer_hash.each_pair do |offer_id, quantity|
  139. next if quantity.blank?
  140. offer = Offer.find(offer_id)
  141. held_tickets.build(:offer_id => offer_id.to_i, :quantity => quantity.to_i, :our_price => offer.our_price, :service_fee => offer.service_fee)
  142. end
  143. unless held_tickets.all(&:valid?)
  144. errors.add_base('Not all tickets could be saved')
  145. raise ActiveRecord::Rollback.new('Not all tickets could be saved')
  146. end
  147. end
  148. errors.empty?
  149. end
  150.  
  151. def offers_for_transfer=(offers_hash)
  152. @offers_for_transfer = offers_hash.reject{|oid, qty| qty.blank?}
  153. end
  154.  
  155. def on_hold_until
  156. expires_at.strftime("%A, %B %d, %I:%M%p")
  157. end
  158.  
  159. def owner_name
  160. ignore_nil{user.name} || email_address
  161. end
  162.  
  163. def part_of_group?
  164. return (hold_type == 'group' || read_attribute(:hold_type) == 1) if self == root
  165. ancestors.any?{|a| (a.hold_type == 'group' || a.read_attribute(:hold_type) == 1)}
  166. end
  167.  
  168. def pass_back_tickets
  169. run_commands(ReturnHeldTicketsToParent)
  170. end
  171.  
  172. def purchase
  173. return nil unless purchased?
  174. purchased_tickets.first.purchase
  175. end
  176.  
  177. def purchased_tickets
  178. held_tickets.map(&:claim).compact
  179. end
  180.  
  181. def quantity_held
  182. held_tickets.inject(0){|total, ticket| total += ticket.quantity_held}
  183. end
  184.  
  185. def quantity_held_for_group
  186. group.inject(0){|total, hold| total += hold.quantity_held}
  187. end
  188.  
  189. def split(params)
  190. Hold.transaction do
  191. self.offers_for_transfer = params[:offers]
  192. self.message = params[:message]
  193. self.split_email = params[:email_address]
  194. run_commands(SplitHold, TransferTickets, DeliverSplitRecipient)
  195. raise ActiveRecord::Rollback.new('There were errors while trying to split this hold.') unless errors.empty?
  196. end
  197. errors.empty?
  198. end
  199.  
  200. def transfer_tickets(target, offers)
  201. Hold.transaction do
  202. self.target, self.offers_for_transfer = target, offers
  203. run_commands(TransferTickets)
  204. raise ActiveRecord::Rollback.new('There were errors while trying to transfer tickets') unless errors.empty?
  205. end
  206. end
  207.  
  208. private
  209.  
  210. def after_initialize
  211. expire!
  212. end
  213.  
  214. def generate_invite_code
  215. return if user || invite_code
  216. self.invite_code = Digest::SHA1.hexdigest("--#{Time.now.utc.to_s}--#{email_address}--")
  217. end
  218.  
  219. def offers_are_valid
  220. errors.add_to_base('All offers must come from the same offerset.') and return unless offers.empty? || Offer::all_offers_are_for_the_same_offerset?(offers)
  221. errors.add_to_base('All offers must be in the same branch.') and return unless offers.empty? || Offer::all_offers_are_in_the_same_offer_branch_above_parent?(offers)
  222. errors.add_to_base('This date/time has expired, please try another.') and return if offerset && offerset.expired?
  223. errors.add_to_base('This date/time has been cancelled, please try another.') and return if offerset && offerset.cancelled?
  224. errors.add_to_base('This date/time has been closed, please try another.') and return if offerset && offerset.closed?
  225. end
  226.  
  227. def prior_hold_does_not_exist
  228. errors.add_to_base("You already have a hold for this event.") if Hold.for_user_and_offerset(user, offerset)
  229. end
  230.  
  231. def set_timer
  232. self.expires_at = (ignore_nil{root.expires_at} || (Time.now+MAX_TIMER_AMOUNT.sum))
  233. end
  234. end
  235.  
  236. ## Specs outlining the issue
  237. it "prove alter ego is sucking atm" do
  238. @h = Hold.new(:invite_code => 'owner')
  239. @h.is_owner?('owner').should be_true
  240. @h.can_cancel?('owner').should be_true
  241. end
Add Comment
Please, Sign In to add comment