artfully_ose 1.2.0.pre.27 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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