artfully_ose 1.2.0.pre.27 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +4 -6
  3. data/app/assets/javascripts/application.js +39 -0
  4. data/app/assets/javascripts/boxoffice.js +558 -0
  5. data/app/assets/javascripts/custom/kits-config.js +33 -0
  6. data/app/assets/javascripts/sales-console.js +29 -24
  7. data/app/assets/javascripts/store/store.js +11 -0
  8. data/app/assets/stylesheets/application.sass +66 -52
  9. data/app/assets/stylesheets/bootstrap-overrides.css +1 -1
  10. data/app/assets/stylesheets/boxoffice.css.scss +258 -0
  11. data/app/assets/stylesheets/pages/bootstrap-responsive.css +1109 -0
  12. data/app/assets/stylesheets/sass/store.sass +52 -62
  13. data/app/assets/stylesheets/storefront.css +1 -1
  14. data/app/concerns/itemable.rb +1 -1
  15. data/app/concerns/pdf_generation.rb +1 -11
  16. data/app/concerns/search_by_dates.rb +20 -0
  17. data/app/controllers/events_controller.rb +1 -0
  18. data/app/controllers/export_controller.rb +11 -1
  19. data/app/controllers/imports_controller.rb +2 -3
  20. data/app/controllers/member_cards_controller.rb +2 -3
  21. data/app/controllers/orders_controller.rb +42 -0
  22. data/app/controllers/organizations_controller.rb +1 -0
  23. data/app/controllers/passes_reports_controller.rb +21 -1
  24. data/app/controllers/regular_donation_kits_controller.rb +32 -0
  25. data/app/controllers/store/donations_controller.rb +19 -1
  26. data/app/controllers/store/orders_controller.rb +15 -5
  27. data/app/helpers/artfully_ose_helper.rb +28 -18
  28. data/app/models/database_views/item_view.rb +41 -0
  29. data/app/models/event.rb +10 -2
  30. data/app/models/ext/integrations.rb +5 -0
  31. data/app/models/fee_strategy.rb +47 -1
  32. data/app/models/imports/events_import.rb +6 -7
  33. data/app/models/item.rb +4 -3
  34. data/app/models/job/order_processor.rb +4 -3
  35. data/app/models/kit.rb +18 -0
  36. data/app/models/kits/regular_donation_kit.rb +51 -9
  37. data/app/models/member.rb +4 -3
  38. data/app/models/membership.rb +1 -2
  39. data/app/models/membership_sale_search.rb +2 -20
  40. data/app/models/membership_type.rb +1 -2
  41. data/app/models/order.rb +29 -1
  42. data/app/models/order_handler.rb +4 -3
  43. data/app/models/organization.rb +17 -9
  44. data/app/models/pass.rb +18 -17
  45. data/app/models/pass_sale_search.rb +18 -0
  46. data/app/models/pass_type.rb +7 -2
  47. data/app/models/passes_report.rb +117 -0
  48. data/app/models/sale_search.rb +3 -21
  49. data/app/models/user.rb +1 -2
  50. data/app/serializers/show_serializer.rb +15 -0
  51. data/app/views/contributions/index.html.haml +2 -2
  52. data/app/views/events/_header.html.haml +1 -0
  53. data/app/views/events/_ticket_type_fields.html.haml +31 -15
  54. data/app/views/events/edit.html.haml +6 -1
  55. data/app/views/imports/_export_links.html.haml +3 -0
  56. data/app/views/imports/donations/_pending.html.haml +24 -6
  57. data/app/views/imports/events/_pending.html.haml +16 -5
  58. data/app/views/imports/index.html.haml +6 -4
  59. data/app/views/imports/people/_pending.html.haml +20 -25
  60. data/app/views/layouts/storefront.html.haml +9 -5
  61. data/app/views/order_mailer/confirmation_for.html.haml +11 -5
  62. data/app/views/order_mailer/confirmation_for_refund.html.haml +6 -2
  63. data/app/views/order_mailer/confirmation_for_refund.text.haml +4 -3
  64. data/app/views/orders/membership.html.haml +15 -19
  65. data/app/views/orders/passes.html.haml +97 -0
  66. data/app/views/orders/sales.html.haml +2 -2
  67. data/app/views/organizations/_form.html.haml +4 -37
  68. data/app/views/pass_types/index.html.haml +1 -1
  69. data/app/views/passes_reports/index.html.haml +79 -1
  70. data/app/views/people/show.html.haml +16 -15
  71. data/app/views/regular_donation_kits/edit.html.haml +140 -0
  72. data/app/views/store/checkouts/thanks.html.haml +14 -6
  73. data/app/views/store/donations/index.html.haml +19 -2
  74. data/app/views/store/events/calendar.html.haml +1 -0
  75. data/app/views/store/events/index.html.haml +1 -0
  76. data/app/views/store/events/show.html.haml +1 -0
  77. data/app/views/store/events/single_show.html.haml +2 -0
  78. data/app/views/store/orders/show.html.haml +10 -10
  79. data/app/views/store/passes/index.html.haml +2 -2
  80. data/app/views/store/shared/_donate_form.html.haml +31 -12
  81. data/app/views/store/shared/_small_donate_form.html.haml +22 -0
  82. data/app/views/users/invitations/edit.html.haml +3 -42
  83. data/config/locales/en.yml +3 -1
  84. data/config/routes.rb +4 -1
  85. data/db/migrate/20140603200735_add_subtitle_to_events.rb +5 -0
  86. data/lib/artfully_ose/version.rb +1 -1
  87. data/spec/factories/kit_factories.rb +5 -4
  88. metadata +25 -13
  89. data/app/assets/javascripts/box-office.js +0 -262
@@ -169,9 +169,10 @@ class Member < ActiveRecord::Base
169
169
  end
170
170
 
171
171
  def generate_pdf
172
- pdf_generator = PdfGeneration.new(self)
173
- download_url = pdf_generator.generate
174
- self.pdf = URI.parse(download_url)
172
+ pdf = PdfGeneration.new(self).generate
173
+ file = Tempfile.new(["#{self.id}", '.pdf'])
174
+ file << pdf.force_encoding("UTF-8")
175
+ self.pdf = file
175
176
  self.save
176
177
  end
177
178
 
@@ -4,7 +4,6 @@
4
4
  #
5
5
  class Membership < ActiveRecord::Base
6
6
  include Extendable
7
- extend ActionView::Helpers::TextHelper
8
7
 
9
8
  belongs_to :organization
10
9
  belongs_to :member
@@ -72,7 +71,7 @@ class Membership < ActiveRecord::Base
72
71
  if membership_types.length > 1
73
72
  "multiple memberships"
74
73
  else
75
- pluralize(memberships.length, "#{memberships.first.membership_type.membershipize}")
74
+ ActionController::Base.helpers.pluralize(memberships.length, "#{memberships.first.membership_type.membershipize}")
76
75
  end
77
76
  else
78
77
  "No memberships"
@@ -1,7 +1,7 @@
1
1
  class MembershipSaleSearch
2
+ include SearchByDates
2
3
 
3
- attr_reader :start, :stop
4
- attr_reader :organization, :membership_type
4
+ attr_reader :membership_type
5
5
 
6
6
  def initialize(terms)
7
7
  @organization = terms[:organization]
@@ -15,22 +15,4 @@ class MembershipSaleSearch
15
15
  def results
16
16
  @results ||= Order.membership_sale_search(self).select(&:has_membership?)
17
17
  end
18
-
19
- private
20
-
21
- def start_with(start)
22
- start.present? ? DateTime.parse(start) : default_start
23
- end
24
-
25
- def stop_with(stop)
26
- stop.present? ? Sundial.midnightish(@organization, stop) : default_stop
27
- end
28
-
29
- def default_start
30
- DateTime.now.in_time_zone(@organization.time_zone).beginning_of_month
31
- end
32
-
33
- def default_stop
34
- DateTime.now.in_time_zone(@organization.time_zone).end_of_day
35
- end
36
18
  end
@@ -1,4 +1,5 @@
1
1
  class MembershipType < ActiveRecord::Base
2
+ include Ext::Integrations::ServiceFee
2
3
  extend ::ArtfullyOseHelper
3
4
  attr_accessible :name, :price, :fee, :number_of_shows,
4
5
  :plan, :on_sale, :description, :ends_at,
@@ -20,8 +21,6 @@ class MembershipType < ActiveRecord::Base
20
21
  scope :sales_valid, where("sales_start_at < ? or sales_start_at is null", DateTime.now).where("sales_end_at > ? or sales_end_at is null", DateTime.now)
21
22
  scope :not_ended, where('ends_at > ?', DateTime.now)
22
23
 
23
- SERVICE_FEE = 0.05
24
-
25
24
  comma do
26
25
  name
27
26
  description
@@ -121,6 +121,10 @@ class Order < ActiveRecord::Base
121
121
  def discount_codes
122
122
  tickets.collect(&:discount).uniq.compact
123
123
  end
124
+
125
+ def pass_codes
126
+ tickets.collect(&:pass).uniq.compact
127
+ end
124
128
 
125
129
  def imported?
126
130
  !self.import_id.nil?
@@ -256,7 +260,6 @@ class Order < ActiveRecord::Base
256
260
 
257
261
  def self.membership_sale_search(search)
258
262
  standard = ::Order.
259
- where("orders.type != ?", ::Reseller::Order.name).
260
263
  joins(:items).
261
264
  joins("INNER JOIN memberships ON (items.product_type = #{::Item.sanitize('Membership')} AND items.product_id = memberships.id)").
262
265
  joins("INNER JOIN membership_types ON (membership_types.id = memberships.membership_type_id)").
@@ -270,6 +273,23 @@ class Order < ActiveRecord::Base
270
273
  standard = standard.where("membership_types.id = ?", search.membership_type.id) if search.membership_type if search.membership_type
271
274
  standard.all
272
275
  end
276
+
277
+ def self.pass_sale_search(search)
278
+ standard = ::Order.
279
+ where("orders.type != ?", ::Reseller::Order.name).
280
+ joins(:items).
281
+ joins("INNER JOIN passes ON (items.product_type = #{::Item.sanitize('Pass')} AND items.product_id = passes.id)").
282
+ joins("INNER JOIN pass_types ON (pass_types.id = passes.pass_type_id)").
283
+ includes([:organization, :person]).
284
+ group('orders.id')
285
+
286
+
287
+ standard = standard.after(search.start) if search.start
288
+ standard = standard.before(search.stop) if search.stop
289
+ standard = standard.where('orders.organization_id = ?', search.organization.id) if search.organization
290
+ standard = standard.where("pass_types.id = ?", search.pass_type.id) if search.pass_type if search.pass_type
291
+ standard.all
292
+ end
273
293
 
274
294
  def has_single_donation?
275
295
  (donations.size == 1) && tickets.empty?
@@ -308,6 +328,14 @@ class Order < ActiveRecord::Base
308
328
  items.select(&:membership?).present?
309
329
  end
310
330
 
331
+ def has_pass?
332
+ items.select(&:pass?).present?
333
+ end
334
+
335
+ def items_that_used_pass
336
+ items.select{ |i| i.pass_id.present? }
337
+ end
338
+
311
339
  def sum_donations
312
340
  all_donations.collect{|item| item.total_price.to_i}.sum
313
341
  end
@@ -41,15 +41,16 @@ class OrderHandler
41
41
  end
42
42
 
43
43
  def handle_donation(params, organization)
44
- if params[:donation_amount]
44
+ donation_amount = params[:donation_amount].present? ? params[:donation_amount] : params[:donation_amount_fixed]
45
+ if donation_amount
45
46
  self.cart.clear_donations
46
- if params[:donation_amount].to_i == 0
47
+ if donation_amount.to_i == 0
47
48
  self.error = "Please enter a donation amount."
48
49
  return
49
50
  end
50
51
 
51
52
  donation = Donation.new
52
- donation.amount = params[:donation_amount].to_i * 100
53
+ donation.amount = donation_amount.to_i * 100
53
54
  donation.organization = organization
54
55
  self.cart.donations << donation
55
56
  end
@@ -34,14 +34,10 @@ class Organization < ActiveRecord::Base
34
34
 
35
35
  has_many :imports
36
36
 
37
- validates_presence_of :name, :email, :time_zone, :country, :state, :zip, :phone_number, :discipline
38
- validates :ein, :presence => true, :if => :updating_tax_info
39
- validates :legal_organization_name, :presence => true, :if => :updating_tax_info
40
-
41
37
  scope :receiving_sales_email, where(:receive_daily_sales_report => true)
42
38
 
43
39
  is_sluggable :name, :editable => true
44
- validates :cached_slug,
40
+ validates :cached_slug,
45
41
  :exclusion => { :in => %w(orders tickets admin artfully statements settlements search searches store event events show shows reseller members mobile member resellers merges people phones refunds exchanges),
46
42
  :message => "we can't set your Storefront URL to \"%{value}\"" },
47
43
  :uniqueness => { :message => "\"%{value}\" has already been taken"}
@@ -142,9 +138,11 @@ class Organization < ActiveRecord::Base
142
138
  end
143
139
 
144
140
  def authorization_hash
145
- { :authorized => can?(:receive, Donation),
141
+ {
142
+ :authorized => can?(:receive, Donation),
146
143
  :type => donation_type,
147
- :fsp_name => name_for_donations }
144
+ :fsp_name => name_for_donations
145
+ }
148
146
  end
149
147
 
150
148
  def donations
@@ -155,14 +153,24 @@ class Organization < ActiveRecord::Base
155
153
  Item.includes(:show => [:event => :venue], :order => [:person => :address]).where(:product_type => "Ticket", :orders => { :organization_id => id })
156
154
  end
157
155
 
156
+ def kit(name)
157
+ name = "#{name.to_s.camelize.gsub(/Kit$/, '')}Kit"
158
+ kits.select { |k| k.class.name == name }.first
159
+ end
160
+
158
161
  def has_kit?(name)
159
- kits.where(:state => "activated").map(&:class).map(&:name).include?(name.to_s.camelize + "Kit")
162
+ name = "#{name.to_s.camelize.gsub(/Kit$/, '')}Kit"
163
+ kits.select { |k| k.class.name == name && k.activated? }.any?
160
164
  end
161
165
 
162
166
  def individuals
163
167
  people.where(:type => 'Individual')
164
168
  end
165
169
 
170
+ def has_active_donation_only_storefront?
171
+ self.has_kit?(:regular_donation) && self.kit(:regular_donation).donation_only_storefront == '1'
172
+ end
173
+
166
174
  private
167
175
 
168
176
  def check_for_duplicates(kit)
@@ -170,7 +178,7 @@ class Organization < ActiveRecord::Base
170
178
  end
171
179
 
172
180
  def donation_type
173
- return :sponsored if kits.where(:type => "SponsoredDonationKit").any? && kits.where(:type => "SponsoredDonationKit").first.activated?
174
181
  return :regular if kits.where(:type => "RegularDonationKit").any? && kits.where(:type => "RegularDonationKit").first.activated?
182
+ return :sponsored if kits.where(:type => "SponsoredDonationKit").any? && kits.where(:type => "SponsoredDonationKit").first.activated?
175
183
  end
176
184
  end
@@ -1,6 +1,5 @@
1
1
  class Pass < ActiveRecord::Base
2
2
  include Extendable
3
- include ActionView::Helpers::TextHelper
4
3
 
5
4
  belongs_to :pass_type
6
5
  belongs_to :person
@@ -19,6 +18,7 @@ class Pass < ActiveRecord::Base
19
18
 
20
19
  scope :not_expired, lambda { |time = DateTime.now| where("#{Pass.table_name}.ends_at > ?", time) }
21
20
  scope :expired, lambda { |time = DateTime.now| where("#{Pass.table_name}.ends_at < ?", time) }
21
+ scope :owned, where('person_id is not null')
22
22
 
23
23
  def self.for(pass_type)
24
24
  new.tap do |pass|
@@ -31,7 +31,7 @@ class Pass < ActiveRecord::Base
31
31
  pass.starts_at = pass_type.starts_at
32
32
  pass.ends_at = pass_type.ends_at
33
33
  end
34
- end
34
+ end
35
35
 
36
36
  def adjust_ends_at
37
37
  self.ends_at = self.ends_at.end_of_day unless self.ends_at.blank?
@@ -96,7 +96,7 @@ class Pass < ActiveRecord::Base
96
96
  if pass_types.length > 1
97
97
  "multiple passes"
98
98
  else
99
- pluralize(passes.length, "#{passes.first.pass_type.passerize}")
99
+ ActionController::Base.helpers.pluralize(passes.length, "#{passes.first.pass_type.passerize}")
100
100
  end
101
101
  else
102
102
  "No passes"
@@ -109,25 +109,22 @@ class Pass < ActiveRecord::Base
109
109
  .where(:event_id => event.id)
110
110
  .where(:pass_type_id => self.pass_type_id).first
111
111
 
112
- Rails.logger.debug ("PASSES the ept is [#{@ept.inspect}]")
113
-
114
112
  return 0 if @ept.nil?
115
113
  return self.tickets_allowed if @ept.limit_per_pass.nil?
116
-
117
- Rails.logger.debug ("PASSES tickets remaining to this event [#{@ept.limit_per_pass - event.tickets.where(:pass_id => self.id).count}]")
118
-
119
114
  return @ept.limit_per_pass - event.tickets.where(:pass_id => self.id).count
120
115
  end
121
116
 
122
117
  def apply_pass_to_cart(cart)
118
+ Rails.logger.debug ("PASSES Applying pass [#{self.id}] to cart [#{cart.id}]")
123
119
  cart.prepare_for_pass!
124
120
 
125
121
  #the number of tickets remining for this pass. We go straight to the DB here
126
122
  #to avoid a race condition on pass.tickets_remaining
127
- tickets_remaining = self.tickets_allowed - tickets_purchased
123
+ tickets_remaining_on_pass = self.tickets_allowed - tickets_purchased
124
+ Rails.logger.debug ("PASSES [#{tickets_remaining_on_pass}] tickets remaining on this pass")
128
125
 
129
126
  self.errors.add(:base, EXPIRED_ERROR) and return if self.expired?
130
- self.errors.add(:base, OUT_OF_TICKETS) and return if tickets_remaining < 1
127
+ self.errors.add(:base, OUT_OF_TICKETS) and return if tickets_remaining_on_pass < 1
131
128
 
132
129
  #The list of tickets w'eve applied this pass too
133
130
  tickets_applied = []
@@ -148,20 +145,24 @@ class Pass < ActiveRecord::Base
148
145
  (pass_errors << TICKET_TYPE_NOT_ELIGIBLE and next) unless self.applies_to? (ticket.ticket_type)
149
146
  (pass_errors << ORG_ERROR and next) unless (self.organization == ticket.organization)
150
147
 
151
- Rails.logger.debug ("PASSES tickets remaining to this event [#{tickets_remaining_for(ticket.show.event)}]")
152
-
153
- tickets_remaining_for_this_event = tickets_remaining_for(ticket.show.event)
148
+ event = ticket.show.event
149
+ tickets_remaining_for_this_event = tickets_remaining_for(event)
150
+ Rails.logger.debug ("PASSES [#{tickets_remaining_for_this_event}] tickets remaining to event [#{event.id}]")
154
151
  over_event_limit = true if tickets_remaining_for_this_event == 0
155
152
 
156
- tickets_remaining = [tickets_remaining, tickets_remaining_for(ticket.show.event)].min
153
+ tickets_remaining = [tickets_remaining_on_pass, tickets_remaining_for_this_event].min
154
+ Rails.logger.debug ("PASSES [#{tickets_remaining}] tickets remaining after considering pass and event")
157
155
 
158
156
  if tickets_remaining > 0
157
+ Rails.logger.debug ("PASSES adding pass [#{self.id}] to ticket [#{ticket.id}]")
159
158
  ticket.pass = self
160
159
  ticket.cart_price = 0
161
160
  ticket.save
162
161
  tickets_applied << ticket
163
- tickets_remaining = tickets_remaining - 1
162
+ tickets_remaining_on_pass = tickets_remaining_on_pass - 1
163
+ Rails.logger.debug ("PASSES Now only [#{tickets_remaining_on_pass}] tickets remaining on this pass")
164
164
  else
165
+ Rails.logger.debug ("PASSES rejecting ticket [#{ticket.id}]")
165
166
  tickets_rejected << tickets
166
167
  end
167
168
  end
@@ -171,7 +172,7 @@ class Pass < ActiveRecord::Base
171
172
  if tickets_applied.length == 0
172
173
  str += "There are no tickets"
173
174
  else
174
- str += "Only #{pluralize(tickets_applied.length, 'ticket')}"
175
+ str += "Only #{ActionController::Base.helpers.pluralize(tickets_applied.length, 'ticket')}"
175
176
  str += tickets_applied.length > 1 ? " were" : " was"
176
177
  end
177
178
 
@@ -179,7 +180,7 @@ class Pass < ActiveRecord::Base
179
180
  str += " for this event" if over_event_limit
180
181
 
181
182
  if tickets_applied.length > 0
182
- str += ". We've applied your pass to #{pluralize(tickets_applied.length, 'ticket')} and left the others in your cart."
183
+ str += ". We've applied your pass to #{ActionController::Base.helpers.pluralize(tickets_applied.length, 'ticket')} and left the others in your cart."
183
184
  end
184
185
 
185
186
  pass_errors << str
@@ -0,0 +1,18 @@
1
+ class PassSaleSearch
2
+ include SearchByDates
3
+
4
+ attr_reader :pass_type
5
+
6
+ def initialize(terms)
7
+ @organization = terms[:organization]
8
+ @pass_type = terms[:pass_type]
9
+ @start = start_with(terms[:start])
10
+ @stop = stop_with(terms[:stop])
11
+
12
+ @results = yield(results) if block_given?
13
+ end
14
+
15
+ def results
16
+ @results ||= Order.pass_sale_search(self).select(&:has_pass?)
17
+ end
18
+ end
@@ -1,4 +1,5 @@
1
1
  class PassType < ActiveRecord::Base
2
+ include Ext::Integrations::ServiceFee
2
3
  include OhNoes::Destroy
3
4
  extend ::ArtfullyOseHelper
4
5
 
@@ -8,13 +9,13 @@ class PassType < ActiveRecord::Base
8
9
  attr_accessible :name, :description, :hide_fee, :thanks_copy, :email_copy, :sales_start_at, :sales_end_at,
9
10
  :on_sale, :price, :tickets_allowed, :starts_at, :ends_at
10
11
 
11
- validates :name, :description, :price, :tickets_allowed, :presence => true
12
+ validates :name, :description, :price, :tickets_allowed, :starts_at, :ends_at, :presence => true
12
13
 
13
14
  scope :storefront, where(:on_sale => true).where("sales_start_at < ? or sales_start_at is null", DateTime.now).where("sales_end_at > ? or sales_end_at is null", DateTime.now)
14
15
  scope :on_sale, where(:on_sale => true)
15
16
  scope :not_ended, where('ends_at > ?', DateTime.now)
16
17
 
17
- SERVICE_FEE = 0.05
18
+ ALL_PASSES_STRING = "ALL PASSES"
18
19
 
19
20
  comma do
20
21
  name
@@ -30,6 +31,10 @@ class PassType < ActiveRecord::Base
30
31
  sales_start_at
31
32
  sales_end_at
32
33
  end
34
+
35
+ def sold
36
+ self.passes.select{ |p| p.person_id.present? }
37
+ end
33
38
 
34
39
  def passerize
35
40
  self.name.end_with?("Pass") ? self.name : self.name + " Pass"
@@ -0,0 +1,117 @@
1
+ class PassesReport
2
+ attr_accessor :pass_type, :header, :start_date, :end_date, :rows, :counts
3
+ attr_accessor :tickets_sold, :passes_sold, :total_tickets, :tickets_remaining, :original_price, :discounted
4
+ extend ::ArtfullyOseHelper
5
+
6
+ def pass_type_name
7
+ pass_type.try(:name) || PassType::ALL_PASSES_STRING
8
+ end
9
+
10
+ def initialize(organization, pass_type, start_date, end_date)
11
+ self.pass_type = pass_type
12
+ self.start_date = start_date
13
+ self.end_date = end_date
14
+
15
+ @orders = find_orders
16
+
17
+ self.rows = []
18
+ @orders.each do |order|
19
+ self.rows << Row.new(order)
20
+ end
21
+
22
+ build_header
23
+
24
+ self.passes_sold = count_passes_sold
25
+ self.total_tickets = calculate_total_tickets
26
+ self.tickets_sold = self.rows.inject(0) { |total, row| total + row.ticket_count}
27
+ self.tickets_remaining= self.total_tickets - self.tickets_sold
28
+ self.original_price = self.rows.inject(0) { |total, row| total + row.original_price }
29
+ self.discounted = self.rows.inject(0) { |total, row| total + row.discounted }
30
+ end
31
+
32
+ def calculate_total_tickets
33
+ @passes = Pass.owned
34
+ if self.pass_type.present?
35
+ @passes = @passes.where(:pass_type_id => self.pass_type.id)
36
+ end
37
+
38
+ @passes.sum(:tickets_allowed)
39
+ end
40
+
41
+ def count_passes_sold
42
+ @items = Item.sold_or_comped.where(:product_type => "Pass")
43
+ @items = @items.joins("INNER join passes ON items.product_id = passes.id")
44
+ @items = @items.joins("INNER join pass_types ON passes.pass_type_id = pass_types.id")
45
+
46
+ if self.pass_type.present?
47
+ @items = @items.where("pass_types.id" => self.pass_type)
48
+ end
49
+
50
+ @items = @items.joins(:order)
51
+ @items = @items.where('orders.created_at > ?',self.start_date) unless start_date.blank?
52
+ @items = @items.where('orders.created_at < ?',self.end_date) unless end_date.blank?
53
+ @items.count
54
+ end
55
+
56
+ def find_orders
57
+ @orders = Order.includes(:person, :items => [:show => :event])
58
+ .joins(:items)
59
+ .joins("INNER join passes ON items.pass_id = passes.id")
60
+ .joins("INNER join pass_types ON passes.pass_type_id = pass_types.id")
61
+ .group('orders.id')
62
+ .order('orders.created_at desc')
63
+
64
+ if pass_type.nil?
65
+ @orders = @orders.where("pass_types.id is not null")
66
+ else
67
+ @orders = @orders.where("pass_types.id" => self.pass_type.id)
68
+ end
69
+
70
+ @orders = @orders.where('orders.created_at > ?',self.start_date) unless start_date.blank?
71
+ @orders = @orders.where('orders.created_at < ?',self.end_date) unless end_date.blank?
72
+ @orders
73
+ end
74
+
75
+ def build_header
76
+ self.header = pass_type_name
77
+ if self.start_date.blank? && self.end_date.blank?
78
+ return
79
+ elsif self.start_date.blank?
80
+ self.header = self.header + " through #{I18n.localize(DateTime.parse(self.end_date), :format => :slashed_date)}"
81
+ elsif self.end_date.blank?
82
+ self.header = self.header + " since #{I18n.localize(DateTime.parse(self.start_date), :format => :slashed_date)}"
83
+ else
84
+ self.header = self.header + " from #{I18n.localize(DateTime.parse(self.start_date), :format => :slashed_date)} through #{I18n.localize(DateTime.parse(self.end_date), :format => :slashed_date)}"
85
+ end
86
+ end
87
+
88
+ class Row
89
+ attr_accessor :order, :show, :pass_type, :ticket_count, :original_price, :gross, :discounted
90
+
91
+ def initialize(order)
92
+ self.order = order
93
+ self.pass_type = order.pass_codes.first.pass_type.name
94
+ self.show = order.items_that_used_pass.first.show
95
+ self.original_price = order.items_that_used_pass.inject(0) { |total, item| total + item.original_price }
96
+ self.gross = order.items_that_used_pass.inject(0) { |total, item| total + item.price }
97
+ self.discounted = self.original_price - self.gross
98
+ self.ticket_count = order.items_that_used_pass.length
99
+ self.ticket_count = self.ticket_count * -1 if !order.items_that_used_pass.select(&:refund?).empty?
100
+ end
101
+
102
+ comma do
103
+ pass_type("Pass")
104
+ order("Order") { |order| order.id }
105
+ order("Order Date") { |order| order.created_at }
106
+ order("First Name") { |order| order.person.first_name }
107
+ order("Last Name") { |order| order.person.last_name }
108
+ order("Email") { |order| order.person.email }
109
+ show("Event") { |show| show.event.name }
110
+ ticket_count
111
+ original_price { |original_price| DiscountsReport.number_as_cents original_price }
112
+ discounted { |discounted| DiscountsReport.number_as_cents discounted }
113
+ gross { |gross| DiscountsReport.number_as_cents gross }
114
+ end
115
+
116
+ end
117
+ end