Class: Order
Overview
The base order class. An order represents a collection of items purchased at the same time.
Subclasses (and their type) should speak to the location or nature of the order, not the contents of the items WebOrder, BoxOfficeOrder for example. NOT DonationOrder, since orders may contain multiple different item types
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
included
#amount_and_nongift, #bootstrapped_type, #build_action_path, #build_order_location, #channel_checkbox, #channel_text, #check_mark, #clean_full_error_messages, #contextual_menu, #credit_card_message, #date_field_tag, #datetime_field_tag, #events_to_options, #fully_qualified_asset_path, #get_selected_class, #icon_link_to, #icon_tag, #link_to_add_fields, #link_to_remove_fields, #nav_dropdown, #number_as_cents, #number_to_dollars, #pluralize_word, #refund_header, #select_event_for_sales_search, #select_membership_type_for_sales_search, #select_pass_type_for_sales_search, #select_show_for_sales_search, #sorted_us_state_abbreviations, #sorted_us_state_names, #thanks_message, #ticket_seller_name, #time_ago_sentence, #time_zone_description, #us_states, #verb_for_save, #widget_script, #with_kit
Methods included from LinkHelper
#active?, #active_link_to, #active_section, #calendar_active_link_to, #in_section, #in_section?, #in_sub_section
#destroy
#fa_id, included
Instance Attribute Details
#per_item_processing_charge ⇒ Object
This is a lambda used to by the items to calculate their net
15
16
17
|
# File 'app/models/order.rb', line 15
def per_item_processing_charge
@per_item_processing_charge
end
|
#skip_actions ⇒ Object
Returns the value of attribute skip_actions.
28
29
30
|
# File 'app/models/order.rb', line 28
def skip_actions
@skip_actions
end
|
#skip_email ⇒ Object
Returns the value of attribute skip_email.
28
29
30
|
# File 'app/models/order.rb', line 28
def skip_email
@skip_email
end
|
Class Method Details
.in_range(start, stop, organization_id = nil) ⇒ Object
99
100
101
102
103
104
105
106
|
# File 'app/models/order.rb', line 99
def self.in_range(start, stop, organization_id = nil)
query = after(start).before(stop).includes(:items, :person, :organization).order("created_at DESC")
if organization_id.present?
query.where('organization_id = ?', organization_id)
else
query
end
end
|
.location ⇒ Object
167
168
169
|
# File 'app/models/order.rb', line 167
def self.location
""
end
|
.membership_sale_search(search) ⇒ Object
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
# File 'app/models/order.rb', line 261
def self.membership_sale_search(search)
standard = ::Order.
joins(:items).
joins("INNER JOIN memberships ON (items.product_type = #{::Item.sanitize('Membership')} AND items.product_id = memberships.id)").
joins("INNER JOIN membership_types ON (membership_types.id = memberships.membership_type_id)").
includes([:organization, :person]).
group('orders.id')
standard = standard.after(search.start) if search.start
standard = standard.before(search.stop) if search.stop
standard = standard.where('orders.organization_id = ?', search.organization.id) if search.organization
standard = standard.where("membership_types.id = ?", search.membership_type.id) if search.membership_type if search.membership_type
standard.all
end
|
.pass_sale_search(search) ⇒ Object
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
|
# File 'app/models/order.rb', line 277
def self.pass_sale_search(search)
standard = ::Order.
where("orders.type != ?", ::Reseller::Order.name).
joins(:items).
joins("INNER JOIN passes ON (items.product_type = #{::Item.sanitize('Pass')} AND items.product_id = passes.id)").
joins("INNER JOIN pass_types ON (pass_types.id = passes.pass_type_id)").
includes([:organization, :person]).
group('orders.id')
standard = standard.after(search.start) if search.start
standard = standard.before(search.stop) if search.stop
standard = standard.where('orders.organization_id = ?', search.organization.id) if search.organization
standard = standard.where("pass_types.id = ?", search.pass_type.id) if search.pass_type if search.pass_type
standard.all
end
|
Instance Method Details
#<<(products) ⇒ Object
212
213
214
|
# File 'app/models/order.rb', line 212
def <<(products)
self.items << Array.wrap(products).collect { |product| Item.for(product, @per_item_processing_charge) }
end
|
#action_class ⇒ Object
443
444
445
|
# File 'app/models/order.rb', line 443
def action_class
GetAction
end
|
#action_details(collection) ⇒ Object
518
519
520
521
|
# File 'app/models/order.rb', line 518
def action_details(collection)
klass = Kernel.const_get(collection.first.class.name)
klass.to_sentence(collection)
end
|
#all_donations ⇒ Object
239
240
241
|
# File 'app/models/order.rb', line 239
def all_donations
all_items.select(&:donation?)
end
|
#all_items ⇒ Object
226
227
228
|
# File 'app/models/order.rb', line 226
def all_items
merge_and_sort_items
end
|
#all_tickets ⇒ Object
230
231
232
|
# File 'app/models/order.rb', line 230
def all_tickets
all_items.select(&:ticket?)
end
|
#anonymous_purchase? ⇒ Boolean
451
452
453
|
# File 'app/models/order.rb', line 451
def anonymous_purchase?
person.try(:dummy?) || false
end
|
#artfully? ⇒ Boolean
159
160
161
|
# File 'app/models/order.rb', line 159
def artfully?
!transaction_id.nil?
end
|
#assign_buyer_to_tickets(person) ⇒ Object
455
456
457
|
# File 'app/models/order.rb', line 455
def assign_buyer_to_tickets(person)
tickets.each {|item| item.assign_person(person) }
end
|
#assign_person(person, create_actions = true) ⇒ Object
523
524
525
526
527
528
529
530
531
532
533
534
535
|
# File 'app/models/order.rb', line 523
def assign_person(person, create_actions = true)
if anonymous_purchase? && !person.new_record?
transaction do
self.person = person
save!
assign_person_to_actions(person)
assign_buyer_to_tickets(person)
children.each do |child_order|
child_order.assign_person(person, false)
end
end
end
end
|
#assign_person_to_actions(person) ⇒ Object
459
460
461
462
463
464
|
# File 'app/models/order.rb', line 459
def assign_person_to_actions(person)
actions.all.each do |action|
action.person = person
action.save!
end
end
|
#assignable? ⇒ Boolean
200
201
202
|
# File 'app/models/order.rb', line 200
def assignable?
anonymous_purchase? && parent.nil?
end
|
#calculate_lifetime_value ⇒ Object
This method is called after_destroy, so *we cannot async this method*
435
436
437
438
439
440
441
|
# File 'app/models/order.rb', line 435
def calculate_lifetime_value
self.person.calculate_lifetime_value
self.person.calculate_lifetime_ticket_value
self.person.calculate_lifetime_donations
self.person.calculate_lifetime_memberships
end
|
#calculate_when_revenue_applies ⇒ Object
150
151
152
153
|
# File 'app/models/order.rb', line 150
def calculate_when_revenue_applies
self.revenue_applies_at = self.created_at || DateTime.now
end
|
428
429
430
|
# File 'app/models/order.rb', line 428
def contact_email
items.try(:first).try(:show).try(:event).try(:contact_email)
end
|
#create_donation_actions ⇒ Object
466
467
468
469
470
471
472
473
474
475
476
477
478
|
# File 'app/models/order.rb', line 466
def create_donation_actions
self.items.select(&:donation?).collect do |item|
action = GiveAction.new
action.person = self.person
action.subject = self
action.organization_id = self.organization.id
action.details = self.donation_details
action.occurred_at = self.created_at
action.subtype = "Monetary"
action.save!
action
end
end
|
#create_generic_action(collection_name) ⇒ Object
Creates actions for collection_name
For example, if we’re creating actions for the passses on this order, call order.create_generic_action(‘passes’) order.rb must respond to .send(collection_name) and the underlying class must implement to_sentence
For example, order.create_generic_action(‘passes’), Pass.to_sentence must be implemented
505
506
507
508
509
510
511
512
513
514
515
516
|
# File 'app/models/order.rb', line 505
def create_generic_action(collection_name)
action = self.action_class.new
action.person = self.person
action.subject = self
action.organization = self.organization
action.details = action_details(self.send(collection_name).collect(&:product)) + ". " + (self.notes || "")
action.occurred_at = self.created_at
action.subtype = action.subtype
action.save!
action
end
|
#create_purchase_action ⇒ Object
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
|
# File 'app/models/order.rb', line 480
def create_purchase_action
unless self.all_tickets.empty?
action = self.purchase_action_class.new
action.person = self.person
action.subject = self
action.organization = self.organization
action.details = self.ticket_details
action.occurred_at = self.created_at
action.subtype = action.subtype
action.import = self.import if self.import
action.save!
action
end
end
|
#destroyable? ⇒ Boolean
183
184
185
|
# File 'app/models/order.rb', line 183
def destroyable?
( (type.eql? "ApplicationOrder") || (type.eql? "ImportedOrder") ) && !is_fafs? && !artfully? && has_single_donation?
end
|
#discount_codes ⇒ Object
121
122
123
|
# File 'app/models/order.rb', line 121
def discount_codes
tickets.collect(&:discount).uniq.compact
end
|
#discounts_used ⇒ Object
Will return an array of all discount codes on all items on this order
346
347
348
|
# File 'app/models/order.rb', line 346
def discounts_used
items.map{|i| i.discount.try(:code)}.reject(&:blank?).uniq
end
|
#donation_details ⇒ Object
374
375
376
377
378
379
380
|
# File 'app/models/order.rb', line 374
def donation_details
if is_fafs?
"#{number_as_cents sum_donations} donation made through Fractured Atlas"
else
"#{number_as_cents sum_donations} donation"
end
end
|
#donations ⇒ Object
243
244
245
|
# File 'app/models/order.rb', line 243
def donations
items.select(&:donation?)
end
|
#editable? ⇒ Boolean
204
205
206
|
# File 'app/models/order.rb', line 204
def editable?
( (type.eql? "ApplicationOrder") || (type.eql? "ImportedOrder") ) && !is_fafs? && !artfully? && has_single_donation?
end
|
#events ⇒ Object
Pass through methods to help out with the checkout thanks page
117
118
119
|
# File 'app/models/order.rb', line 117
def events
tickets.collect(&:product).collect(&:event).uniq
end
|
#exchangeable_items ⇒ Object
307
308
309
|
# File 'app/models/order.rb', line 307
def exchangeable_items
items.select(&:exchangeable?)
end
|
#exchanges ⇒ Object
155
156
157
|
# File 'app/models/order.rb', line 155
def exchanges
tickets.find_all(&:exchanged?)
end
|
#for_organization(org) ⇒ Object
208
209
210
|
# File 'app/models/order.rb', line 208
def for_organization(org)
self.organization = org
end
|
#has_donation? ⇒ Boolean
323
324
325
|
# File 'app/models/order.rb', line 323
def has_donation?
items.select(&:donation?).present?
end
|
#has_membership? ⇒ Boolean
327
328
329
|
# File 'app/models/order.rb', line 327
def has_membership?
items.select(&:membership?).present?
end
|
#has_pass? ⇒ Boolean
331
332
333
|
# File 'app/models/order.rb', line 331
def has_pass?
items.select(&:pass?).present?
end
|
#has_single_donation? ⇒ Boolean
294
295
296
|
# File 'app/models/order.rb', line 294
def has_single_donation?
(donations.size == 1) && tickets.empty?
end
|
#has_ticket? ⇒ Boolean
319
320
321
|
# File 'app/models/order.rb', line 319
def has_ticket?
items.select(&:ticket?).present?
end
|
#imported? ⇒ Boolean
129
130
131
|
# File 'app/models/order.rb', line 129
def imported?
!self.import_id.nil?
end
|
#is_fafs? ⇒ Boolean
370
371
372
|
# File 'app/models/order.rb', line 370
def is_fafs?
!fa_id.nil?
end
|
#items_that_used_pass ⇒ Object
335
336
337
|
# File 'app/models/order.rb', line 335
def items_that_used_pass
items.select{ |i| i.pass_id.present? }
end
|
#location ⇒ Object
163
164
165
|
# File 'app/models/order.rb', line 163
def location
self.class.location
end
|
#membership_types ⇒ Object
257
258
259
|
# File 'app/models/order.rb', line 257
def membership_types
memberships.collect{|item| item.product.membership_type}.uniq
end
|
#memberships(reload = false) ⇒ Object
TODO: Undupe these methods
249
250
251
|
# File 'app/models/order.rb', line 249
def memberships(reload=false)
items(reload).select(&:membership?)
end
|
#non_exchanged_total ⇒ Object
175
176
177
|
# File 'app/models/order.rb', line 175
def non_exchanged_total
all_items.reject(&:exchanged?).inject(0) {|sum, item| sum + item.total_price.to_i }
end
|
#nongift_amount ⇒ Object
179
180
181
|
# File 'app/models/order.rb', line 179
def nongift_amount
all_items.inject(0) {|sum, item| sum + item.nongift_amount.to_i }
end
|
#num_tickets ⇒ Object
315
316
317
|
# File 'app/models/order.rb', line 315
def num_tickets
all_tickets.size
end
|
#original_order ⇒ Object
402
403
404
405
406
407
408
|
# File 'app/models/order.rb', line 402
def original_order
if self.parent.nil?
return self
else
return self.parent.original_order
end
end
|
#originally_sold_at ⇒ Object
142
143
144
|
# File 'app/models/order.rb', line 142
def originally_sold_at
original_order.created_at
end
|
#pass_codes ⇒ Object
125
126
127
|
# File 'app/models/order.rb', line 125
def pass_codes
tickets.collect(&:pass).uniq.compact
end
|
#passes(reload = false) ⇒ Object
253
254
255
|
# File 'app/models/order.rb', line 253
def passes(reload=false)
items(reload).select(&:pass?)
end
|
#payment ⇒ Object
216
217
218
|
# File 'app/models/order.rb', line 216
def payment
CreditCardPayment.new(:transaction_id => transaction_id)
end
|
#process ⇒ Object
191
192
193
194
|
# File 'app/models/order.rb', line 191
def process
@skip_actions ||= false
OrderProcessor.process(self, {:skip_actions => @skip_actions, :skip_email => self.skip_confirmation_email?})
end
|
#processor_class ⇒ Object
196
197
198
|
# File 'app/models/order.rb', line 196
def processor_class
OrderProcessor
end
|
#purchase_action_class ⇒ Object
447
448
449
|
# File 'app/models/order.rb', line 447
def purchase_action_class
GetAction
end
|
#record_exchange!(exchanged_items) ⇒ Object
220
221
222
223
224
|
# File 'app/models/order.rb', line 220
def record_exchange!(exchanged_items)
items.each_with_index do |item, index|
item.to_exchange! exchanged_items[index]
end
end
|
#refundable_items ⇒ Object
302
303
304
305
|
# File 'app/models/order.rb', line 302
def refundable_items
return [] unless Payment.create(payment_method).refundable?
items.select(&:refundable?)
end
|
#returnable_items ⇒ Object
311
312
313
|
# File 'app/models/order.rb', line 311
def returnable_items
items.select { |i| i.returnable? and i.comped? and not i.refundable? }
end
|
#revenue_applies_to_range(start_date, end_date) ⇒ Object
146
147
148
|
# File 'app/models/order.rb', line 146
def revenue_applies_to_range(start_date, end_date)
start_date < self.created_at && self.created_at < end_date
end
|
#sell_tickets ⇒ Object
418
419
420
421
422
|
# File 'app/models/order.rb', line 418
def sell_tickets
all_tickets.each do |item|
item.product.sell_to(self.person, self.created_at)
end
end
|
#service_fee ⇒ Object
112
113
114
|
# File 'app/models/order.rb', line 112
def service_fee
items.collect(&:service_fee).sum
end
|
#settleable_donations ⇒ Object
298
299
300
|
# File 'app/models/order.rb', line 298
def settleable_donations
all_donations.reject(&:modified?)
end
|
#show ⇒ Object
108
109
110
|
# File 'app/models/order.rb', line 108
def show
items.first.try(:show)
end
|
#skip_confirmation_email? ⇒ Boolean
187
188
189
|
# File 'app/models/order.rb', line 187
def skip_confirmation_email?
skip_email || anonymous_purchase? || imported? || self.person.email.blank?
end
|
#sum_donations ⇒ Object
339
340
341
|
# File 'app/models/order.rb', line 339
def sum_donations
all_donations.collect{|item| item.total_price.to_i}.sum
end
|
#ticket_details ⇒ Object
350
351
352
353
354
355
356
357
358
359
360
361
362
|
# File 'app/models/order.rb', line 350
def ticket_details
String.new.tap do |details|
if self.tickets.any?
details << Ticket.to_sentence(self.tickets.map(&:product))
else
details << "No tickets"
end
if discounts_used.any?
details << ", used #{'discount'.pluralize(discounts_used.length)} " + discounts_used.join(",")
end
end
end
|
#ticket_summary ⇒ Object
382
383
384
385
386
387
388
|
# File 'app/models/order.rb', line 382
def ticket_summary
summary = TicketSummary.new
items.select(&:ticket?).each do |item|
summary << item.product
end
summary
end
|
#tickets(reload = false) ⇒ Object
TODO: Undupe these methods
235
236
237
|
# File 'app/models/order.rb', line 235
def tickets(reload=false)
items(reload).select(&:ticket?)
end
|
#time_zone ⇒ Object
424
425
426
|
# File 'app/models/order.rb', line 424
def time_zone
"Eastern Time (US & Canada)"
end
|
#to_comp! ⇒ Object
364
365
366
367
368
|
# File 'app/models/order.rb', line 364
def to_comp!
items.each do |item|
item.to_comp!
end
end
|
#total ⇒ Object
171
172
173
|
# File 'app/models/order.rb', line 171
def total
all_items.inject(0) {|sum, item| sum + item.total_price.to_i }
end
|
#total_discount ⇒ Object
133
134
135
|
# File 'app/models/order.rb', line 133
def total_discount
tickets.collect(&:total_discount).sum
end
|
#total_with_service_fee ⇒ Object
137
138
139
|
# File 'app/models/order.rb', line 137
def total_with_service_fee
total + service_fee
end
|
#transaction_id ⇒ Object
If this order has no transaction_id, run up the parent chain until we hit one This is needed for exchanges that ultimately need to be refunded
414
415
416
|
# File 'app/models/order.rb', line 414
def transaction_id
read_attribute(:transaction_id) || self.parent.try(:transaction_id)
end
|