artfully_ose 1.2.0.alpha.2 → 1.2.0.beta.1
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.
- checksums.yaml +8 -8
- data/app/assets/stylesheets/application.sass +7 -1
- data/app/concerns/itemable.rb +1 -1
- data/app/concerns/pdf_generation.rb +1 -11
- data/app/concerns/search_by_dates.rb +20 -0
- data/app/controllers/member_cards_controller.rb +2 -3
- data/app/controllers/orders_controller.rb +42 -0
- data/app/controllers/passes_reports_controller.rb +21 -1
- data/app/helpers/artfully_ose_helper.rb +10 -0
- data/app/models/database_views/item_view.rb +41 -0
- data/app/models/ext/integrations.rb +4 -0
- data/app/models/fee_strategy.rb +47 -1
- data/app/models/item.rb +4 -3
- data/app/models/job/order_processor.rb +4 -3
- data/app/models/member.rb +4 -3
- data/app/models/membership_sale_search.rb +2 -20
- data/app/models/membership_type.rb +1 -2
- data/app/models/order.rb +29 -0
- data/app/models/pass.rb +2 -1
- data/app/models/pass_sale_search.rb +18 -0
- data/app/models/pass_type.rb +6 -1
- data/app/models/passes_report.rb +117 -0
- data/app/models/sale_search.rb +3 -21
- data/app/views/contributions/index.html.haml +2 -2
- data/app/views/orders/membership.html.haml +15 -19
- data/app/views/orders/passes.html.haml +97 -0
- data/app/views/orders/sales.html.haml +2 -2
- data/app/views/pass_types/index.html.haml +1 -1
- data/app/views/passes_reports/index.html.haml +79 -1
- data/app/views/store/passes/index.html.haml +2 -2
- data/config/routes.rb +1 -0
- data/lib/artfully_ose/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NzdkN2Y3NDg3MDVhMDY5NjQ4OWM1MzlhYjlmNGFkMTI1YThlM2EzYQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzhhODQxYjMzYTFjMDI5M2RkNzZiMzg3YzYyYTVmYTc1NjcyMjgzOQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZThmZDFjY2RlMWQ2MGExYzlkODYyYWE2MmQ3OWY1NDYyNjk5MDIzOTQ1MDhl
|
10
|
+
NTkzN2Q0NGJhOGJiNDE4ODBhODJkODczNzZmMWE5OTVmMGUzYzVlZDhiMzI3
|
11
|
+
ZGQ3NGI4NmJiZWUzODFiM2IzYzUzNzU5NGQ3OGE2OGNmN2YyMTg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MzU1N2U3MzgzODQ2MzZmOTc2MjU4YjBjYzc2MzBjMzQ0YWU2NDExMjcxZTNk
|
14
|
+
ZmJjNzBjM2JiMzVkMDUxNzM5MzZlZjBjZGI2NTZjZmVhYjEyNDdiMDkzNWVm
|
15
|
+
NWUzNTE4MWUxZTk0NzgwMGFhYzRjNGE2OGFmODRkMjU1ZGNkNGI=
|
@@ -119,8 +119,14 @@ ul#memberships
|
|
119
119
|
#text
|
120
120
|
padding-top: 50px
|
121
121
|
|
122
|
-
#
|
122
|
+
#no-pass-sales
|
123
123
|
text-align: center
|
124
|
+
width: 100%
|
125
|
+
height: 100px
|
126
|
+
#text
|
127
|
+
padding-top: 25px
|
128
|
+
|
129
|
+
#add-a-pass-type
|
124
130
|
width: 75%
|
125
131
|
height: 150px
|
126
132
|
#text
|
data/app/concerns/itemable.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# Include this method on objects that can be used to create items using Item.for
|
3
|
-
# Ticket class doesn't
|
3
|
+
# Ticket class doesn't need it because it defines its own sold_price method
|
4
4
|
#
|
5
5
|
module Itemable
|
6
6
|
extend ActiveSupport::Concern
|
@@ -17,17 +17,7 @@ class PdfGeneration
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def generate
|
20
|
-
|
21
|
-
json = JSON.parse(response.body)
|
22
|
-
|
23
|
-
while !json["complete"]
|
24
|
-
response = http_party.get(status_url(json))
|
25
|
-
json = JSON.parse(response.body)
|
26
|
-
|
27
|
-
sleeper.sleep 1 unless json["complete"]
|
28
|
-
end
|
29
|
-
|
30
|
-
download_url(json)
|
20
|
+
Wisepdf::Writer.new.to_pdf(content)
|
31
21
|
end
|
32
22
|
|
33
23
|
def content
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SearchByDates
|
2
|
+
attr_reader :start, :stop
|
3
|
+
attr_reader :organization
|
4
|
+
|
5
|
+
def start_with(start)
|
6
|
+
start.present? ? DateTime.parse(start) : default_start
|
7
|
+
end
|
8
|
+
|
9
|
+
def stop_with(stop)
|
10
|
+
stop.present? ? Sundial.midnightish(@organization, stop) : default_stop
|
11
|
+
end
|
12
|
+
|
13
|
+
def default_start
|
14
|
+
DateTime.now.in_time_zone(@organization.time_zone).beginning_of_month
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_stop
|
18
|
+
DateTime.now.in_time_zone(@organization.time_zone).end_of_day
|
19
|
+
end
|
20
|
+
end
|
@@ -4,9 +4,8 @@ class MemberCardsController < ArtfullyOseController
|
|
4
4
|
before_filter :find_members
|
5
5
|
|
6
6
|
def new
|
7
|
-
|
8
|
-
|
9
|
-
redirect_to generator.download_url
|
7
|
+
pdf = MemberCardGenerator::BlanksUsaIdc6.new(@members).generate
|
8
|
+
send_data pdf, :filename => "member_cards.pdf", :type => "application/pdf", :disposition => "attachment"
|
10
9
|
end
|
11
10
|
|
12
11
|
private
|
@@ -89,6 +89,48 @@ class OrdersController < ArtfullyOseController
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
+
def passes
|
93
|
+
authorize! :view, Order
|
94
|
+
|
95
|
+
@organization = current_organization
|
96
|
+
@pass_type = PassType.find_by_id(params[:pass_type_id]) if params[:pass_type_id].present?
|
97
|
+
@pass_types = @organization.pass_types
|
98
|
+
|
99
|
+
request.format = :csv if params[:commit] == "Download"
|
100
|
+
|
101
|
+
search_terms = {
|
102
|
+
:start => params[:start],
|
103
|
+
:stop => params[:stop],
|
104
|
+
:organization => @organization,
|
105
|
+
:pass_type => @pass_type
|
106
|
+
}
|
107
|
+
|
108
|
+
@search = PassSaleSearch.new(search_terms) do |results|
|
109
|
+
results.paginate(:page => params[:page], :per_page => 25)
|
110
|
+
end
|
111
|
+
|
112
|
+
respond_to do |format|
|
113
|
+
format.html
|
114
|
+
format.csv do
|
115
|
+
filename = "Artfully-Pass-Sales-Export-#{DateTime.now.strftime("%m-%d-%y")}.csv"
|
116
|
+
items = ItemView.where(:product_type => "Pass")
|
117
|
+
.where('items_view.created_at > ? ', @search.start)
|
118
|
+
.where('items_view.created_at < ?', @search.stop)
|
119
|
+
.where('items_view.organization_id = ?', current_organization)
|
120
|
+
.order('items_view.created_at desc')
|
121
|
+
if @pass_type
|
122
|
+
items = items.joins(:item).
|
123
|
+
joins("INNER JOIN passes ON (items.product_type = #{::Item.sanitize('Pass')} AND items.product_id = passes.id)").
|
124
|
+
joins("INNER JOIN pass_types ON (pass_types.id = passes.pass_type_id)").
|
125
|
+
where(:pass_types => {:id => @pass_type}).
|
126
|
+
group('items_view.order_id')
|
127
|
+
end
|
128
|
+
csv_string = items.all.to_comma(:pass_sale)
|
129
|
+
send_data csv_string, :filename => filename, :type => "text/csv", :disposition => "attachment"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
92
134
|
def sales
|
93
135
|
authorize! :view, Order
|
94
136
|
|
@@ -1,5 +1,25 @@
|
|
1
1
|
class PassesReportsController < ArtfullyOseController
|
2
2
|
def index
|
3
|
-
@
|
3
|
+
@start_date = params[:start_date]
|
4
|
+
@end_date = params[:end_date]
|
5
|
+
@organization = current_user.current_organization
|
6
|
+
@pass_types = @organization.pass_types
|
7
|
+
@pass_type = PassType.find(params[:pass_type]) if params[:pass_type].present?
|
8
|
+
@report = nil
|
9
|
+
@report = PassesReport.new(@organization, @pass_type, @start_date, @end_date)
|
10
|
+
@rows = @report.rows.paginate(:page => params[:page], :per_page => 100) unless @report.nil?
|
11
|
+
|
12
|
+
@options_for_select = @pass_types.collect{ |p| [p.name, p.id] }
|
13
|
+
@options_for_select.unshift [PassType::ALL_PASSES_STRING, nil]
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
format.html
|
17
|
+
|
18
|
+
format.csv do
|
19
|
+
@filename = [ @report.header, ".csv" ].join
|
20
|
+
@csv_string = @report.rows.to_comma
|
21
|
+
send_data @csv_string, :filename => @filename, :type => "text/csv", :disposition => "attachment"
|
22
|
+
end
|
23
|
+
end
|
4
24
|
end
|
5
25
|
end
|
@@ -252,6 +252,16 @@ module ArtfullyOseHelper
|
|
252
252
|
select_tag membership_type_id, raw(options), :class => "span3"
|
253
253
|
end
|
254
254
|
|
255
|
+
def select_pass_type_for_sales_search(pass_types, pass_type_id, default)
|
256
|
+
options =
|
257
|
+
[
|
258
|
+
content_tag(:option, " --- All Pass Types --- ", :value => ""),
|
259
|
+
options_from_collection_for_select(pass_types, :id, :name, default)
|
260
|
+
].join
|
261
|
+
|
262
|
+
select_tag pass_type_id, raw(options), :class => "span3"
|
263
|
+
end
|
264
|
+
|
255
265
|
def nav_dropdown(text, link='#')
|
256
266
|
link_to ERB::Util.html_escape(text) + ' <b class="caret"></b>'.html_safe, link, :class => 'dropdown-toggle', 'data-toggle' => 'dropdown'
|
257
267
|
end
|
@@ -145,4 +145,45 @@ class ItemView < ActiveRecord::Base
|
|
145
145
|
person("Do Not Email") { |person| person.do_not_email }
|
146
146
|
person("Do Not Call") { |person| person.do_not_call }
|
147
147
|
end
|
148
|
+
|
149
|
+
comma :pass_sale do
|
150
|
+
created_at_local_to_organization("Date of Purchase")
|
151
|
+
|
152
|
+
item('Pass Type') { |item| item.product.pass_type.name }
|
153
|
+
payment_method("Payment Method")
|
154
|
+
price("Price") { |cents| number_to_currency(cents.to_f/100) }
|
155
|
+
special_instructions("Special Instructions")
|
156
|
+
notes("Notes")
|
157
|
+
|
158
|
+
person("Email") { |person| person.email }
|
159
|
+
person("Salutation") { |person| person.salutation }
|
160
|
+
person("First Name") { |person| person.first_name }
|
161
|
+
person("Middle Name") { |person| person.middle_name }
|
162
|
+
person("Last Name") { |person| person.last_name }
|
163
|
+
person("Suffix") { |person| person.suffix }
|
164
|
+
person("Title") { |person| person.title }
|
165
|
+
person("Type") { |person| person.type }
|
166
|
+
person("Subtype") { |person| person.subtype }
|
167
|
+
person("Company Name") { |person| person.company_name }
|
168
|
+
|
169
|
+
person("Address 1") { |person| person.address && person.address.address1 }
|
170
|
+
person("Address 2") { |person| person.address && person.address.address2 }
|
171
|
+
person("City") { |person| person.address && person.address.city }
|
172
|
+
person("State") { |person| person.address && person.address.state }
|
173
|
+
person("Zip") { |person| person.address && person.address.zip }
|
174
|
+
person("Country") { |person| person.address && person.address.country }
|
175
|
+
person("Phone1 type") { |person| person.phones[0] && person.phones[0].kind }
|
176
|
+
person("Phone1 number") { |person| person.phones[0] && person.phones[0].number }
|
177
|
+
person("Phone2 type") { |person| person.phones[1] && person.phones[1].kind }
|
178
|
+
person("Phone2 number") { |person| person.phones[1] && person.phones[1].number }
|
179
|
+
person("Phone3 type") { |person| person.phones[2] && person.phones[2].kind }
|
180
|
+
person("Phone3 number") { |person| person.phones[2] && person.phones[2].number }
|
181
|
+
person("Website") { |person| person.website }
|
182
|
+
person("Twitter Handle") { |person| person.twitter_handle }
|
183
|
+
person("Facebook URL") { |person| person.facebook_url }
|
184
|
+
person("Linked In Url") { |person| person.linked_in_url }
|
185
|
+
person("Tags") { |person| person.tags.join("|") }
|
186
|
+
person("Do Not Email") { |person| person.do_not_email }
|
187
|
+
person("Do Not Call") { |person| person.do_not_call }
|
188
|
+
end
|
148
189
|
end
|
data/app/models/fee_strategy.rb
CHANGED
@@ -1,5 +1,51 @@
|
|
1
1
|
class FeeStrategy
|
2
|
+
def ticket_fee
|
3
|
+
ARTFULLY_CONFIG[:ticket_fee] || 0
|
4
|
+
end
|
5
|
+
|
2
6
|
def apply_to_cart(cart)
|
3
|
-
|
7
|
+
return if cart.is_a? BoxOffice::Cart
|
8
|
+
|
9
|
+
handle_tickets(cart)
|
10
|
+
handle_memberships(cart)
|
11
|
+
handle_passes(cart)
|
12
|
+
end
|
13
|
+
|
14
|
+
def handle_tickets(cart)
|
15
|
+
cart.tickets.each do |ticket|
|
16
|
+
if ticket.price > 0
|
17
|
+
ticket.service_fee = ticket_fee
|
18
|
+
elsif ticket.price == 0
|
19
|
+
ticket.service_fee = 0
|
20
|
+
end
|
21
|
+
|
22
|
+
if ticket.cart_price == 0 && waive_fee_for?(ticket)
|
23
|
+
ticket.service_fee = 0
|
24
|
+
end
|
25
|
+
|
26
|
+
ticket.save
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def handle_memberships(cart)
|
31
|
+
cart.memberships.each do |membership|
|
32
|
+
membership.service_fee = membership.membership_type.hide_fee? ? 0 : (membership.cart_price || membership.price) * MembershipType::SERVICE_FEE
|
33
|
+
membership.save
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def handle_passes(cart)
|
38
|
+
cart.passes.each do |pass|
|
39
|
+
pass.service_fee = pass.pass_type.hide_fee? ? 0 : pass.price * PassType::SERVICE_FEE
|
40
|
+
pass.save
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def waive_fee_for?(ticket)
|
45
|
+
#
|
46
|
+
# This match is too tightly coupled to discount. Also, horrible.
|
47
|
+
# Check needs to be made because cart_price == 0 && BOGO means fee is applied
|
48
|
+
#
|
49
|
+
(ticket.discount.try(:promotion_type) == "DollarsOffTickets") || ticket.pass.present?
|
4
50
|
end
|
5
51
|
end
|
data/app/models/item.rb
CHANGED
@@ -22,9 +22,10 @@ class Item < ActiveRecord::Base
|
|
22
22
|
validates_presence_of :product_type, :price, :realized_price, :net
|
23
23
|
validates_inclusion_of :product_type, :in => %( Ticket Donation Membership Pass)
|
24
24
|
|
25
|
-
scope :donation,
|
26
|
-
scope :membership,
|
27
|
-
scope :ticket,
|
25
|
+
scope :donation, where(:product_type => 'Donation')
|
26
|
+
scope :membership, where(:product_type => 'Membership')
|
27
|
+
scope :ticket, where(:product_type => 'Ticket')
|
28
|
+
scope :sold_or_comped, where("state in ('purchased','comped','settled')")
|
28
29
|
|
29
30
|
scope :imported, joins(:order).merge(Order.imported)
|
30
31
|
scope :not_imported, joins(:order).merge(Order.not_imported)
|
@@ -85,9 +85,10 @@ class OrderProcessor < Struct.new(:order, :options)
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def generate_pdf
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
pdf = PdfGeneration.new(order).generate
|
89
|
+
file = Tempfile.new(["#{order.id}", '.pdf'])
|
90
|
+
file << pdf.force_encoding("UTF-8")
|
91
|
+
order.pdf = file
|
91
92
|
order.save
|
92
93
|
end
|
93
94
|
end
|
data/app/models/member.rb
CHANGED
@@ -169,9 +169,10 @@ class Member < ActiveRecord::Base
|
|
169
169
|
end
|
170
170
|
|
171
171
|
def generate_pdf
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class MembershipSaleSearch
|
2
|
+
include SearchByDates
|
2
3
|
|
3
|
-
attr_reader :
|
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
|
data/app/models/order.rb
CHANGED
@@ -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?
|
@@ -269,6 +273,23 @@ class Order < ActiveRecord::Base
|
|
269
273
|
standard = standard.where("membership_types.id = ?", search.membership_type.id) if search.membership_type if search.membership_type
|
270
274
|
standard.all
|
271
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
|
272
293
|
|
273
294
|
def has_single_donation?
|
274
295
|
(donations.size == 1) && tickets.empty?
|
@@ -307,6 +328,14 @@ class Order < ActiveRecord::Base
|
|
307
328
|
items.select(&:membership?).present?
|
308
329
|
end
|
309
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
|
+
|
310
339
|
def sum_donations
|
311
340
|
all_donations.collect{|item| item.total_price.to_i}.sum
|
312
341
|
end
|
data/app/models/pass.rb
CHANGED
@@ -18,6 +18,7 @@ class Pass < ActiveRecord::Base
|
|
18
18
|
|
19
19
|
scope :not_expired, lambda { |time = DateTime.now| where("#{Pass.table_name}.ends_at > ?", time) }
|
20
20
|
scope :expired, lambda { |time = DateTime.now| where("#{Pass.table_name}.ends_at < ?", time) }
|
21
|
+
scope :owned, where('person_id is not null')
|
21
22
|
|
22
23
|
def self.for(pass_type)
|
23
24
|
new.tap do |pass|
|
@@ -30,7 +31,7 @@ class Pass < ActiveRecord::Base
|
|
30
31
|
pass.starts_at = pass_type.starts_at
|
31
32
|
pass.ends_at = pass_type.ends_at
|
32
33
|
end
|
33
|
-
end
|
34
|
+
end
|
34
35
|
|
35
36
|
def adjust_ends_at
|
36
37
|
self.ends_at = self.ends_at.end_of_day unless self.ends_at.blank?
|
@@ -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
|
data/app/models/pass_type.rb
CHANGED
@@ -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
|
|
@@ -14,7 +15,7 @@ class PassType < ActiveRecord::Base
|
|
14
15
|
scope :on_sale, where(:on_sale => true)
|
15
16
|
scope :not_ended, where('ends_at > ?', DateTime.now)
|
16
17
|
|
17
|
-
|
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
|
data/app/models/sale_search.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class SaleSearch
|
2
|
-
|
3
|
-
|
4
|
-
attr_reader :
|
2
|
+
include SearchByDates
|
3
|
+
|
4
|
+
attr_reader :event, :show
|
5
5
|
|
6
6
|
def initialize(terms)
|
7
7
|
@organization = terms[:organization]
|
@@ -16,22 +16,4 @@ class SaleSearch
|
|
16
16
|
def results
|
17
17
|
@results ||= Order.sale_search(self).select(&:has_ticket?)
|
18
18
|
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def start_with(start)
|
23
|
-
start.present? ? DateTime.parse(start) : default_start
|
24
|
-
end
|
25
|
-
|
26
|
-
def stop_with(stop)
|
27
|
-
stop.present? ? Sundial.midnightish(@organization, stop) : default_stop
|
28
|
-
end
|
29
|
-
|
30
|
-
def default_start
|
31
|
-
DateTime.now.in_time_zone(@organization.time_zone).beginning_of_month
|
32
|
-
end
|
33
|
-
|
34
|
-
def default_stop
|
35
|
-
DateTime.now.in_time_zone(@organization.time_zone).end_of_day
|
36
|
-
end
|
37
19
|
end
|
@@ -6,9 +6,9 @@
|
|
6
6
|
= form_tag contributions_path, :method => :get, :class => 'well form-inline' do
|
7
7
|
.pull-left
|
8
8
|
= label_tag :start, "From", :class => "control-label"
|
9
|
-
= text_field_tag :start,"#{l @search.start, :format => :date_for_input}", :
|
9
|
+
= text_field_tag :start,"#{l @search.start, :format => :date_for_input}", :class => 'datepicker input-small'
|
10
10
|
= label_tag :stop, "To", :class => "control-label"
|
11
|
-
= text_field_tag :stop, "#{l @search.stop, :format => :date_for_input}", :
|
11
|
+
= text_field_tag :stop, "#{l @search.stop, :format => :date_for_input}", :class => 'datepicker input-small'
|
12
12
|
.pull-right
|
13
13
|
= submit_tag "Search", :class => "btn"
|
14
14
|
= submit_tag "Download", :class => "btn"
|
@@ -2,26 +2,16 @@
|
|
2
2
|
- content_for :header do
|
3
3
|
%h1 Membership Orders
|
4
4
|
|
5
|
-
#print-cards.modal.hide.fade
|
6
|
-
.modal-header
|
7
|
-
.close{'data-dismiss'=>'modal'} x
|
8
|
-
%h3 Generating Member Cards
|
9
|
-
.modal-body
|
10
|
-
%p
|
11
|
-
A PDF is being generated and will automatically begin downloading when ready...
|
12
|
-
.progress.progress-success.progress-striped.active
|
13
|
-
.bar{:style => 'width: 90%'}
|
14
|
-
|
15
5
|
#donations-search
|
16
6
|
|
17
7
|
.control-group.well
|
18
|
-
= form_tag membership_orders_path, :method => :get, :class => 'form-inline' do
|
8
|
+
= form_tag membership_orders_path, :method => :get, :id => 'memberships-date-search-form', :class => 'form-inline' do
|
19
9
|
.pull-left
|
20
10
|
= label_tag :start, "From", :class => "control-label"
|
21
|
-
= text_field_tag :start,"#{l @search.start, :format => :date_for_input}", :
|
11
|
+
= text_field_tag :start,"#{l @search.start, :format => :date_for_input}", :class => 'datepicker input-small'
|
22
12
|
|
23
13
|
= label_tag :stop, "To", :class => "control-label"
|
24
|
-
= text_field_tag :stop, "#{l @search.stop, :format => :date_for_input}", :
|
14
|
+
= text_field_tag :stop, "#{l @search.stop, :format => :date_for_input}", :class => 'datepicker input-small'
|
25
15
|
|
26
16
|
- if @membership_types.present?
|
27
17
|
= label_tag :membership_type_id, nil, :class => "control-label"
|
@@ -41,7 +31,7 @@
|
|
41
31
|
= link_to 'Export to CSV', params.merge(:format => 'csv').delete_if {|k,v| :commit == k.to_sym }
|
42
32
|
- with_kit(:membership) do
|
43
33
|
%li
|
44
|
-
=link_to 'Print Member Cards', new_member_card_path({:start => @search.start, :stop => @search.stop, :membership_type_id => @search.membership_type.try(:id)})
|
34
|
+
=link_to 'Print Member Cards', new_member_card_path({:start => @search.start, :stop => @search.stop, :membership_type_id => @search.membership_type.try(:id)})
|
45
35
|
|
46
36
|
|
47
37
|
- if @search.results.present?
|
@@ -59,16 +49,22 @@
|
|
59
49
|
%tbody
|
60
50
|
- @search.results.each do |order|
|
61
51
|
- order.items.select(&:membership?).each_with_index do |item, index|
|
62
|
-
|
63
|
-
|
52
|
+
- if index == 0
|
53
|
+
%tr{:id => "order_#{order.id}"}
|
64
54
|
- rowspan = order.items.select(&:membership?).size
|
65
55
|
%td{:rowspan => rowspan}= link_to order.id, order_path(order.id)
|
66
56
|
%td{:rowspan => rowspan}= l(order.created_at_local_to_organization, :format => :short)
|
67
57
|
%td{:rowspan => rowspan}= link_to_person(order.person)
|
68
58
|
%td{:rowspan => rowspan}= (order.payment_method || "")
|
69
|
-
|
70
|
-
|
71
|
-
|
59
|
+
%td
|
60
|
+
="#{item.product.membership_type.name}"
|
61
|
+
%td= number_as_cents item.price
|
62
|
+
- else
|
63
|
+
%tr
|
64
|
+
%td
|
65
|
+
="#{item.product.membership_type.name}"
|
66
|
+
%td= number_as_cents item.price
|
67
|
+
|
72
68
|
= will_paginate(@search.results)
|
73
69
|
|
74
70
|
- else
|
@@ -0,0 +1,97 @@
|
|
1
|
+
- in_section :transactions
|
2
|
+
- content_for :header do
|
3
|
+
%h1 Pass Orders
|
4
|
+
|
5
|
+
#donations-search
|
6
|
+
|
7
|
+
.control-group.well
|
8
|
+
= form_tag passes_orders_path, :method => :get, :id => 'passes-date-search-form', :class => 'form-inline' do
|
9
|
+
.pull-left
|
10
|
+
= label_tag :start, "From", :class => "control-label"
|
11
|
+
= text_field_tag :start,"#{l @search.start, :format => :date_for_input}", :class => 'datepicker input-small'
|
12
|
+
|
13
|
+
= label_tag :stop, "To", :class => "control-label"
|
14
|
+
= text_field_tag :stop, "#{l @search.stop, :format => :date_for_input}", :class => 'datepicker input-small'
|
15
|
+
|
16
|
+
- if @pass_types.present?
|
17
|
+
= label_tag :pass_type_id, nil, :class => "control-label"
|
18
|
+
= raw select_pass_type_for_sales_search @pass_types, :pass_type_id, params[:pass_type_id]
|
19
|
+
|
20
|
+
= submit_tag "Search", :class => "btn"
|
21
|
+
|
22
|
+
|
23
|
+
- if @search.results.present?
|
24
|
+
.pull-right
|
25
|
+
|
26
|
+
%ul.in-table
|
27
|
+
%li.dropdown#bulkactions
|
28
|
+
=icon_link_to('Work with...', "#menu#bulkactions", 'fa-asterisk', 'dropdown-toggle dropdown btn', '')
|
29
|
+
%ul.dropdown-menu
|
30
|
+
%li
|
31
|
+
= link_to 'Export to CSV', params.merge(:format => 'csv').delete_if {|k,v| :commit == k.to_sym }
|
32
|
+
|
33
|
+
|
34
|
+
- if @search.results.present?
|
35
|
+
|
36
|
+
#tickets
|
37
|
+
%table.standalone.zebra.table
|
38
|
+
%thead
|
39
|
+
%tr
|
40
|
+
%th Order
|
41
|
+
%th Time
|
42
|
+
%th Person
|
43
|
+
%th Method
|
44
|
+
%th Membership Type
|
45
|
+
%th Amount
|
46
|
+
%tbody
|
47
|
+
- @search.results.each do |order|
|
48
|
+
- order.items.select(&:pass?).each_with_index do |item, index|
|
49
|
+
- if index == 0
|
50
|
+
%tr{:id => "order_#{order.id}"}
|
51
|
+
- rowspan = order.items.select(&:pass?).size
|
52
|
+
%td{:rowspan => rowspan}= link_to order.id, order_path(order.id)
|
53
|
+
%td{:rowspan => rowspan}= l(order.created_at_local_to_organization, :format => :short)
|
54
|
+
%td{:rowspan => rowspan}= link_to_person(order.person)
|
55
|
+
%td{:rowspan => rowspan}= (order.payment_method || "")
|
56
|
+
%td
|
57
|
+
="#{item.product.pass_type.name}"
|
58
|
+
%td= number_as_cents item.price
|
59
|
+
- else
|
60
|
+
%tr
|
61
|
+
%td
|
62
|
+
="#{item.product.pass_type.name}"
|
63
|
+
%td= number_as_cents item.price
|
64
|
+
|
65
|
+
= will_paginate(@search.results)
|
66
|
+
|
67
|
+
- else
|
68
|
+
|
69
|
+
%h4= "No sales found."
|
70
|
+
|
71
|
+
- content_for :custom_js do
|
72
|
+
:javascript
|
73
|
+
var printCardInterval;
|
74
|
+
|
75
|
+
$('#print-cards').on('show', function (show) {
|
76
|
+
// Remove any existing intervals
|
77
|
+
clearInterval(printCardInterval);
|
78
|
+
|
79
|
+
// Initial hurry to 90%
|
80
|
+
var bar = $('#print-cards .bar');
|
81
|
+
$(bar).css('width', '1%').animate({width: '90%'}, 1500, function() {
|
82
|
+
|
83
|
+
// Progress to 100% from there
|
84
|
+
var times = 0;
|
85
|
+
printCardInterval = setInterval(function() {
|
86
|
+
// Count this run
|
87
|
+
times = times + 1;
|
88
|
+
|
89
|
+
// Update the progress bar
|
90
|
+
$(bar).css('width', (90 + times) + '%');
|
91
|
+
|
92
|
+
// Clear the interval on the last run
|
93
|
+
if (times > 9) { clearInterval(printCardInterval); }
|
94
|
+
}, 1000);
|
95
|
+
|
96
|
+
});
|
97
|
+
});
|
@@ -7,10 +7,10 @@
|
|
7
7
|
.control-group.well
|
8
8
|
.pull-left
|
9
9
|
= label_tag :start, "From", :class => "control-label"
|
10
|
-
= text_field_tag :start,"#{l @search.start, :format => :date_for_input}", :
|
10
|
+
= text_field_tag :start,"#{l @search.start, :format => :date_for_input}", :class => 'datepicker input-small'
|
11
11
|
|
12
12
|
= label_tag :stop, "To", :class => "control-label"
|
13
|
-
= text_field_tag :stop, "#{l @search.stop, :format => :date_for_input}", :
|
13
|
+
= text_field_tag :stop, "#{l @search.stop, :format => :date_for_input}", :class => 'datepicker input-small'
|
14
14
|
|
15
15
|
- if @events.present?
|
16
16
|
= label_tag :event_id, nil, :class => "control-label"
|
@@ -21,7 +21,7 @@
|
|
21
21
|
%td=link_to pass_type.name, edit_pass_type_path(pass_type)
|
22
22
|
%td=l pass_type.starts_at, :format => :slashed_date
|
23
23
|
%td=l pass_type.ends_at, :format => :slashed_date
|
24
|
-
%td.right=pass_type.
|
24
|
+
%td.right=pass_type.sold.count
|
25
25
|
%td.right=pass_type.tickets_allowed
|
26
26
|
%td.right=number_as_cents pass_type.price
|
27
27
|
%td.right
|
@@ -1,2 +1,80 @@
|
|
1
1
|
-content_for :header do
|
2
|
-
%h1
|
2
|
+
%h1 Pass Usage
|
3
|
+
|
4
|
+
= form_tag passes_reports_path, :method => :get, :class => 'well form-inline' do
|
5
|
+
= label_tag :pass_type, "Pass", :class => "control-label"
|
6
|
+
= select_tag :pass_type, options_for_select(@options_for_select, @report.pass_type.try(:id))
|
7
|
+
|
8
|
+
|
9
|
+
= label_tag :start_date, "From", :class => "control-label"
|
10
|
+
= text_field_tag :start_date, @start_date, :readonly => true, :class => 'datepicker input-small'
|
11
|
+
|
12
|
+
= label_tag :end_date, "To", :class => "control-label"
|
13
|
+
= text_field_tag :end_date, @end_date, :readonly => true, :class => 'datepicker input-small'
|
14
|
+
|
15
|
+
.pull-right
|
16
|
+
= submit_tag "Search", :class => "btn"
|
17
|
+
|
18
|
+
- unless @report.nil?
|
19
|
+
|
20
|
+
.row-fluid.botton-room
|
21
|
+
.span9
|
22
|
+
%h3=@report.header
|
23
|
+
.span3
|
24
|
+
.pull-right
|
25
|
+
=link_to "Download CSV", passes_reports_path(code: @report.pass_type, start_date: @report.start_date, end_date: @report.end_date, format: "csv"), :class => "btn"
|
26
|
+
|
27
|
+
#statement-summary.bottom-room.well
|
28
|
+
.row-fluid
|
29
|
+
.span4
|
30
|
+
.center.headline-stat#passes-sold-stat
|
31
|
+
=@report.passes_sold
|
32
|
+
.center.headline-caption
|
33
|
+
%h6 PASSES SOLD
|
34
|
+
.span4
|
35
|
+
.center.headline-stat#tickets-sold-stat
|
36
|
+
=@report.tickets_sold
|
37
|
+
.center.headline-caption
|
38
|
+
%h6 TICKETS SOLD
|
39
|
+
.span4
|
40
|
+
.center.headline-stat#tickets-remaining-stat
|
41
|
+
=@report.tickets_remaining
|
42
|
+
.center.headline-caption
|
43
|
+
%h6 TICKETS REMAINING
|
44
|
+
|
45
|
+
.row
|
46
|
+
.span12
|
47
|
+
%table.table.zebra#order-table
|
48
|
+
%thead
|
49
|
+
%tr
|
50
|
+
%th{:style=>'width:200px'} Pass
|
51
|
+
%th Order/Date
|
52
|
+
%th{:style=>'width:200px'} Person
|
53
|
+
%th Event
|
54
|
+
%th.right Tickets
|
55
|
+
%th.right Orig. Price
|
56
|
+
%th.right Gross
|
57
|
+
%tbody
|
58
|
+
-if @rows.empty?
|
59
|
+
%tr
|
60
|
+
%td{:colspan => 7}
|
61
|
+
.no-image#no-pass-sales
|
62
|
+
#text
|
63
|
+
=icon_tag '299-ticket'
|
64
|
+
%br
|
65
|
+
This pass hasn't been used to buy any tickets.
|
66
|
+
-@rows.each do |row|
|
67
|
+
%tr
|
68
|
+
%td=row.pass_type
|
69
|
+
%td
|
70
|
+
=link_to row.order.id, order_path(row.order)
|
71
|
+
%br
|
72
|
+
=l row.order.created_at, :format => :slashed_date
|
73
|
+
%td
|
74
|
+
=link_to row.order.person, person_path(row.order.person)
|
75
|
+
%td=link_to row.show.event.name, event_path(row.show.event)
|
76
|
+
%td.right=row.ticket_count
|
77
|
+
%td.right=number_as_cents row.original_price
|
78
|
+
%td.right=number_as_cents row.gross
|
79
|
+
|
80
|
+
= will_paginate(@rows)
|
@@ -17,7 +17,7 @@
|
|
17
17
|
.title.active
|
18
18
|
.price
|
19
19
|
=number_as_cents pass_type.price
|
20
|
-
.
|
20
|
+
.pass_type_name
|
21
21
|
=pass_type.name
|
22
22
|
=pass_type.description
|
23
23
|
%br
|
@@ -26,7 +26,7 @@
|
|
26
26
|
= form_for pass_type, :as => :pass_type, :url => store_order_path(@store_organization.cached_slug), :html => {:id => "edit_pass_type_#{pass_type.id}"}, :method => :post do |f|
|
27
27
|
= f.hidden_field :id
|
28
28
|
= select_tag :quantity, options_for_select((1..6).to_a.map {|i| [pluralize(i, "#{pass_type.passerize}"), i]})
|
29
|
-
= f.submit 'Add to cart', :class => 'btn btn-primary', :style => 'margin-top: -10px'
|
29
|
+
= f.submit 'Add to cart', :class => 'add-to-cart btn btn-primary', :style => 'margin-top: -10px'
|
30
30
|
|
31
31
|
.span4
|
32
32
|
.side-section
|
data/config/routes.rb
CHANGED
data/lib/artfully_ose/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: artfully_ose
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.0.
|
4
|
+
version: 1.2.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Artful.ly
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -1916,6 +1916,7 @@ files:
|
|
1916
1916
|
- app/concerns/itemable.rb
|
1917
1917
|
- app/concerns/oh_noes.rb
|
1918
1918
|
- app/concerns/pdf_generation.rb
|
1919
|
+
- app/concerns/search_by_dates.rb
|
1919
1920
|
- app/concerns/unrefundable.rb
|
1920
1921
|
- app/controllers/actions_controller.rb
|
1921
1922
|
- app/controllers/addresses_controller.rb
|
@@ -2122,8 +2123,10 @@ files:
|
|
2122
2123
|
- app/models/organization_ability.rb
|
2123
2124
|
- app/models/parsed_row.rb
|
2124
2125
|
- app/models/pass.rb
|
2126
|
+
- app/models/pass_sale_search.rb
|
2125
2127
|
- app/models/pass_summary.rb
|
2126
2128
|
- app/models/pass_type.rb
|
2129
|
+
- app/models/passes_report.rb
|
2127
2130
|
- app/models/payment.rb
|
2128
2131
|
- app/models/payments/cash_payment.rb
|
2129
2132
|
- app/models/payments/check_payment.rb
|
@@ -2354,6 +2357,7 @@ files:
|
|
2354
2357
|
- app/views/orders/_search_form.haml
|
2355
2358
|
- app/views/orders/index.html.haml
|
2356
2359
|
- app/views/orders/membership.html.haml
|
2360
|
+
- app/views/orders/passes.html.haml
|
2357
2361
|
- app/views/orders/sales.html.haml
|
2358
2362
|
- app/views/orders/show.html.haml
|
2359
2363
|
- app/views/organizations/_connection_form.html.haml
|