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.
- checksums.yaml +8 -8
- data/README.md +4 -6
- data/app/assets/javascripts/application.js +39 -0
- data/app/assets/javascripts/boxoffice.js +558 -0
- data/app/assets/javascripts/custom/kits-config.js +33 -0
- data/app/assets/javascripts/sales-console.js +29 -24
- data/app/assets/javascripts/store/store.js +11 -0
- data/app/assets/stylesheets/application.sass +66 -52
- data/app/assets/stylesheets/bootstrap-overrides.css +1 -1
- data/app/assets/stylesheets/boxoffice.css.scss +258 -0
- data/app/assets/stylesheets/pages/bootstrap-responsive.css +1109 -0
- data/app/assets/stylesheets/sass/store.sass +52 -62
- data/app/assets/stylesheets/storefront.css +1 -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/events_controller.rb +1 -0
- data/app/controllers/export_controller.rb +11 -1
- data/app/controllers/imports_controller.rb +2 -3
- data/app/controllers/member_cards_controller.rb +2 -3
- data/app/controllers/orders_controller.rb +42 -0
- data/app/controllers/organizations_controller.rb +1 -0
- data/app/controllers/passes_reports_controller.rb +21 -1
- data/app/controllers/regular_donation_kits_controller.rb +32 -0
- data/app/controllers/store/donations_controller.rb +19 -1
- data/app/controllers/store/orders_controller.rb +15 -5
- data/app/helpers/artfully_ose_helper.rb +28 -18
- data/app/models/database_views/item_view.rb +41 -0
- data/app/models/event.rb +10 -2
- data/app/models/ext/integrations.rb +5 -0
- data/app/models/fee_strategy.rb +47 -1
- data/app/models/imports/events_import.rb +6 -7
- data/app/models/item.rb +4 -3
- data/app/models/job/order_processor.rb +4 -3
- data/app/models/kit.rb +18 -0
- data/app/models/kits/regular_donation_kit.rb +51 -9
- data/app/models/member.rb +4 -3
- data/app/models/membership.rb +1 -2
- data/app/models/membership_sale_search.rb +2 -20
- data/app/models/membership_type.rb +1 -2
- data/app/models/order.rb +29 -1
- data/app/models/order_handler.rb +4 -3
- data/app/models/organization.rb +17 -9
- data/app/models/pass.rb +18 -17
- data/app/models/pass_sale_search.rb +18 -0
- data/app/models/pass_type.rb +7 -2
- data/app/models/passes_report.rb +117 -0
- data/app/models/sale_search.rb +3 -21
- data/app/models/user.rb +1 -2
- data/app/serializers/show_serializer.rb +15 -0
- data/app/views/contributions/index.html.haml +2 -2
- data/app/views/events/_header.html.haml +1 -0
- data/app/views/events/_ticket_type_fields.html.haml +31 -15
- data/app/views/events/edit.html.haml +6 -1
- data/app/views/imports/_export_links.html.haml +3 -0
- data/app/views/imports/donations/_pending.html.haml +24 -6
- data/app/views/imports/events/_pending.html.haml +16 -5
- data/app/views/imports/index.html.haml +6 -4
- data/app/views/imports/people/_pending.html.haml +20 -25
- data/app/views/layouts/storefront.html.haml +9 -5
- data/app/views/order_mailer/confirmation_for.html.haml +11 -5
- data/app/views/order_mailer/confirmation_for_refund.html.haml +6 -2
- data/app/views/order_mailer/confirmation_for_refund.text.haml +4 -3
- 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/organizations/_form.html.haml +4 -37
- data/app/views/pass_types/index.html.haml +1 -1
- data/app/views/passes_reports/index.html.haml +79 -1
- data/app/views/people/show.html.haml +16 -15
- data/app/views/regular_donation_kits/edit.html.haml +140 -0
- data/app/views/store/checkouts/thanks.html.haml +14 -6
- data/app/views/store/donations/index.html.haml +19 -2
- data/app/views/store/events/calendar.html.haml +1 -0
- data/app/views/store/events/index.html.haml +1 -0
- data/app/views/store/events/show.html.haml +1 -0
- data/app/views/store/events/single_show.html.haml +2 -0
- data/app/views/store/orders/show.html.haml +10 -10
- data/app/views/store/passes/index.html.haml +2 -2
- data/app/views/store/shared/_donate_form.html.haml +31 -12
- data/app/views/store/shared/_small_donate_form.html.haml +22 -0
- data/app/views/users/invitations/edit.html.haml +3 -42
- data/config/locales/en.yml +3 -1
- data/config/routes.rb +4 -1
- data/db/migrate/20140603200735_add_subtitle_to_events.rb +5 -0
- data/lib/artfully_ose/version.rb +1 -1
- data/spec/factories/kit_factories.rb +5 -4
- metadata +25 -13
- data/app/assets/javascripts/box-office.js +0 -262
@@ -13,8 +13,8 @@ module ArtfullyOseHelper
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def with_kit(kit)
|
17
|
-
organization = current_user.try(:current_organization) || @store_organization
|
16
|
+
def with_kit(kit, organization = nil)
|
17
|
+
organization = organization || current_user.try(:current_organization) || @store_organization
|
18
18
|
if organization.has_kit? kit
|
19
19
|
yield
|
20
20
|
end
|
@@ -29,11 +29,11 @@ module ArtfullyOseHelper
|
|
29
29
|
def build_order_location(order)
|
30
30
|
order.location
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
def channel_checkbox(channel)
|
34
34
|
channel.to_s.eql?("storefront") ? "Storefront & Widgets" : channel.to_s.humanize
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def channel_text(channel)
|
38
38
|
case channel.to_s
|
39
39
|
when "members"
|
@@ -44,7 +44,7 @@ module ArtfullyOseHelper
|
|
44
44
|
channel.to_s.humanize
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def build_action_path(target, action)
|
49
49
|
action_path_name = action.new_record? ? "actions" : "actions"
|
50
50
|
"#{target.class.name.downcase}_#{action_path_name}_path"
|
@@ -71,17 +71,17 @@ module ArtfullyOseHelper
|
|
71
71
|
def get_selected_class(selected_object, menu_object)
|
72
72
|
selected_object.try(:id) == menu_object.id ? "active" : "unselected"
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
#For use with Font Awesome icon %i classes
|
76
76
|
def icon_link_to(text, href, icon, class_names, id, html_attributes={})
|
77
77
|
s = "<a href='#{href}' class='#{class_names}' id='#{id}' "
|
78
78
|
html_attributes.each do |k,v|
|
79
|
-
s = s + " #{k}=#{v} "
|
79
|
+
s = s + " #{k}=#{v} "
|
80
80
|
end
|
81
81
|
s = s + "><i class='fa #{icon}'></i> #{text}</a>"
|
82
82
|
s.html_safe
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
#
|
86
86
|
# just name the image, this method will prepend the path and append the .png
|
87
87
|
# icon_tag('111-logo')
|
@@ -93,12 +93,12 @@ module ArtfullyOseHelper
|
|
93
93
|
def time_zone_description(tz)
|
94
94
|
ActiveSupport::TimeZone.create(tz)
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
#This is for the widget generator, DO NOT use anywhere else
|
98
98
|
def fully_qualified_asset_path(asset)
|
99
99
|
"#{asset_path(asset, :digest => false)}"
|
100
100
|
end
|
101
|
-
|
101
|
+
|
102
102
|
def events_to_options(selected_event_id = nil)
|
103
103
|
@events = current_user.current_organization.events
|
104
104
|
@events_array = @events.map { |event| [event.name, event.id] }
|
@@ -132,7 +132,7 @@ module ArtfullyOseHelper
|
|
132
132
|
str += " (#{number_as_cents item.nongift_amount} Non-deductible)" unless item.nongift_amount.nil? || item.nongift_amount == 0
|
133
133
|
str
|
134
134
|
end
|
135
|
-
|
135
|
+
|
136
136
|
#This method will not prepend the $
|
137
137
|
def number_to_dollars(cents)
|
138
138
|
cents.to_i / 100.00
|
@@ -241,7 +241,7 @@ module ArtfullyOseHelper
|
|
241
241
|
|
242
242
|
select_tag show_id, raw(options), :class => "span3"
|
243
243
|
end
|
244
|
-
|
244
|
+
|
245
245
|
def select_membership_type_for_sales_search(membership_types, membership_type_id, default)
|
246
246
|
options =
|
247
247
|
[
|
@@ -252,10 +252,20 @@ 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
|
258
|
-
|
268
|
+
|
259
269
|
def bootstrapped_type(type)
|
260
270
|
case type
|
261
271
|
when :notice then "alert alert-info"
|
@@ -268,7 +278,7 @@ module ArtfullyOseHelper
|
|
268
278
|
def link_to_remove_fields(name, f)
|
269
279
|
f.hidden_field(:_destroy) + link_to(name, "#", :onclick => "remove_fields(this); return false;")
|
270
280
|
end
|
271
|
-
|
281
|
+
|
272
282
|
def link_to_add_fields(name, f, association, view_path = '', additional_javascript=nil)
|
273
283
|
new_object = f.object.class.reflect_on_association(association).klass.new
|
274
284
|
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
|
@@ -278,17 +288,17 @@ module ArtfullyOseHelper
|
|
278
288
|
end
|
279
289
|
link_to name, "#", :onclick => "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\"); #{additional_javascript} return false;"
|
280
290
|
end
|
281
|
-
|
291
|
+
|
282
292
|
def ticket_seller_name(ticket)
|
283
293
|
end
|
284
|
-
|
294
|
+
|
285
295
|
def credit_card_message
|
286
296
|
end
|
287
|
-
|
297
|
+
|
288
298
|
def date_field_tag(name, value = nil, options = {})
|
289
299
|
text_field_tag(name, value, options.stringify_keys.update("type" => "date"))
|
290
300
|
end
|
291
|
-
|
301
|
+
|
292
302
|
def datetime_field_tag(name, value = nil, options = {})
|
293
303
|
text_field_tag(name, value, options.stringify_keys.update("type" => "datetime"))
|
294
304
|
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/event.rb
CHANGED
@@ -10,8 +10,9 @@ class Event < ActiveRecord::Base
|
|
10
10
|
|
11
11
|
attr_accessible :name, :producer, :description, :contact_email, :contact_phone, :image, :venue_attributes,
|
12
12
|
:show_special_instructions, :special_instructions_caption, :public, :primary_category,
|
13
|
-
:secondary_categories, :primary_category_other, :secondary_category_other, :members_only
|
14
|
-
|
13
|
+
:secondary_categories, :primary_category_other, :secondary_category_other, :members_only,
|
14
|
+
:subtitle
|
15
|
+
|
15
16
|
store :cached_stats, :accessors => [ :on_sale, :off_sale, :sold, :sales_total ]
|
16
17
|
|
17
18
|
belongs_to :organization
|
@@ -28,6 +29,7 @@ class Event < ActiveRecord::Base
|
|
28
29
|
validates :contact_email, :presence => true, :email => true
|
29
30
|
validates :name, :presence => true
|
30
31
|
validates :organization_id, :presence => true
|
32
|
+
validate :subtitle, length: { maximum: 255 }
|
31
33
|
|
32
34
|
has_attached_file :image,
|
33
35
|
:storage => :s3,
|
@@ -59,9 +61,15 @@ class Event < ActiveRecord::Base
|
|
59
61
|
ANY_EVENT_TEXT = "(Any Event)"
|
60
62
|
ANY_EVENT_ID = "-1"
|
61
63
|
|
64
|
+
searchable do
|
65
|
+
text :name
|
66
|
+
end
|
67
|
+
include Ext::DelayedIndexing
|
68
|
+
|
62
69
|
#
|
63
70
|
# Run synchronously only with great care.
|
64
71
|
#
|
72
|
+
|
65
73
|
def refresh_stats
|
66
74
|
self.on_sale = self.glance.available.on_sale
|
67
75
|
self.off_sale = self.glance.available.off_sale
|
@@ -3,6 +3,10 @@ module Ext
|
|
3
3
|
module Member
|
4
4
|
end
|
5
5
|
|
6
|
+
module ServiceFee
|
7
|
+
SERVICE_FEE = 0
|
8
|
+
end
|
9
|
+
|
6
10
|
module User
|
7
11
|
def need_more_info?
|
8
12
|
false
|
@@ -46,6 +50,7 @@ module Ext
|
|
46
50
|
kit.save
|
47
51
|
end
|
48
52
|
end
|
53
|
+
validates_presence_of :name, :email, :time_zone
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
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
|
@@ -193,14 +193,13 @@ class EventsImport < Import
|
|
193
193
|
order
|
194
194
|
end
|
195
195
|
|
196
|
-
def
|
197
|
-
|
198
|
-
|
199
|
-
parsed_rows.each do |row|
|
196
|
+
def parse_and_hash(rows)
|
197
|
+
rows.reduce({}) do | all,imported_row|
|
198
|
+
row = ParsedRow.new(headers, imported_row.content)
|
200
199
|
key = (row.event_name || "") + (row.venue_name || "") + (row.show_date.to_s || "")
|
201
|
-
|
202
|
-
|
200
|
+
all[key] ||= []
|
201
|
+
all[key] << row
|
202
|
+
all
|
203
203
|
end
|
204
|
-
@events
|
205
204
|
end
|
206
205
|
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/kit.rb
CHANGED
@@ -23,6 +23,7 @@ class Kit < ActiveRecord::Base
|
|
23
23
|
|
24
24
|
event(:activate, :success => :record_activation) { transitions :from => [:fresh, :pending], :to => :activated, :guard => :activatable? }
|
25
25
|
event(:approve, :success => :record_approval) { transitions :from => :pending, :to => :activated, :guard => :approvable? }
|
26
|
+
event(:admin_approve, :success => :record_approval) { transitions :from => :pending, :to => :activated, :guard => :admin_approvable? }
|
26
27
|
event(:cancel) { transitions :from => [:activated, :pending, :rejected ], :to => :cancelled }
|
27
28
|
event(:reactivate) { transitions :from => :cancelled, :to => :activated, :guard => :activatable? }
|
28
29
|
event(:activate_without_pending) { transitions :from => [:fresh, :pending, :cancelled], :to => :activated }
|
@@ -48,6 +49,11 @@ class Kit < ActiveRecord::Base
|
|
48
49
|
approval_requirements[:if] << options.delete(:if) if options.has_key?(:if)
|
49
50
|
end
|
50
51
|
|
52
|
+
def self.admin_approve(options)
|
53
|
+
admin_approval_requirements[:unless] << options.delete(:unless) if options.has_key?(:unless)
|
54
|
+
admin_approval_requirements[:if] << options.delete(:if) if options.has_key?(:if)
|
55
|
+
end
|
56
|
+
|
51
57
|
def self.activation_requirements
|
52
58
|
@requirements ||= Hash.new { |h,k| h[k] = [] }
|
53
59
|
end
|
@@ -56,6 +62,10 @@ class Kit < ActiveRecord::Base
|
|
56
62
|
@approval_requirements ||= Hash.new { |h,k| h[k] = [] }
|
57
63
|
end
|
58
64
|
|
65
|
+
def self.admin_approval_requirements
|
66
|
+
@admin_approval_requirements ||= Hash.new { |h,k| h[k] = [] }
|
67
|
+
end
|
68
|
+
|
59
69
|
def self.when_active(&block)
|
60
70
|
self.ability_proc = Proc.new(&block)
|
61
71
|
end
|
@@ -108,6 +118,10 @@ class Kit < ActiveRecord::Base
|
|
108
118
|
check_approval
|
109
119
|
end
|
110
120
|
|
121
|
+
def admin_approvable?
|
122
|
+
check_admin_approval
|
123
|
+
end
|
124
|
+
|
111
125
|
class DuplicateError < StandardError
|
112
126
|
end
|
113
127
|
|
@@ -124,6 +138,10 @@ class Kit < ActiveRecord::Base
|
|
124
138
|
check_unlesses(self.class.approval_requirements[:unless]) and check_ifs(self.class.approval_requirements[:if])
|
125
139
|
end
|
126
140
|
|
141
|
+
def check_admin_approval
|
142
|
+
check_unlesses(self.class.admin_approval_requirements[:unless]) and check_ifs(self.class.admin_approval_requirements[:if])
|
143
|
+
end
|
144
|
+
|
127
145
|
def check_unlesses(unlesses)
|
128
146
|
return true if unlesses.empty?
|
129
147
|
unlesses.all? { |req| !self.send(req) }
|
@@ -1,35 +1,58 @@
|
|
1
1
|
class RegularDonationKit < Kit
|
2
2
|
acts_as_kit :with_approval => true do
|
3
|
+
self.configurable = true
|
4
|
+
|
3
5
|
activate :if => :has_tax_info?
|
4
6
|
activate :if => :exclusive?
|
5
|
-
|
7
|
+
|
8
|
+
#
|
9
|
+
# So, this is horrible. Sorry.
|
10
|
+
# Leaving "approve" out of this list sets the kit to auto-approve which is the
|
11
|
+
# opposite of what we want. So, this kludge is here to force the kit to
|
12
|
+
# never approve until you call kit.admin_approve
|
13
|
+
#
|
14
|
+
approve :if => :dont_approve
|
15
|
+
admin_approve :unless => :no_bank_account?
|
6
16
|
|
7
17
|
when_active do |organization|
|
8
18
|
organization.can :receive, Donation
|
9
19
|
end
|
10
20
|
end
|
11
21
|
|
22
|
+
ACCESSORS = [
|
23
|
+
:about_organization_text, :donation_ask_text, :donate_now_text, :donation_nudge_text,
|
24
|
+
:suggested_gifts, :open_gift_field, :thanks_msg_text, :email_msg_text, :donation_only_storefront,
|
25
|
+
]
|
26
|
+
|
27
|
+
attr_accessible *ACCESSORS
|
28
|
+
|
29
|
+
store :settings, :accessors => ACCESSORS
|
30
|
+
|
31
|
+
def dont_approve
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
12
35
|
def has_tax_info?
|
13
|
-
errors.add(:requirements,
|
36
|
+
errors.add(:requirements, 'Your organization\'s tax information is missing or incomplete. Please complete it in order to active this kit.') unless organization.has_tax_info?
|
14
37
|
organization.has_tax_info?
|
15
38
|
end
|
16
|
-
|
39
|
+
|
17
40
|
def friendly_name
|
18
|
-
|
41
|
+
'501(c)(3) Donations'
|
19
42
|
end
|
20
|
-
|
43
|
+
|
21
44
|
def pitch
|
22
|
-
|
45
|
+
'Receive donations for a 501(c)(3)'
|
23
46
|
end
|
24
47
|
|
25
48
|
def exclusive?
|
26
49
|
exclusive = !organization.kits.where(:type => alternatives.collect(&:to_s)).any?
|
27
|
-
errors.add(:requirements,
|
50
|
+
errors.add(:requirements, 'You have already activated a mutually exclusive kit.') unless exclusive
|
28
51
|
exclusive
|
29
52
|
end
|
30
53
|
|
31
54
|
def no_bank_account?
|
32
|
-
errors.add(:requirements,
|
55
|
+
errors.add(:requirements, 'Your organization needs bank account information first.') if organization.bank_account.nil?
|
33
56
|
organization.bank_account.nil?
|
34
57
|
end
|
35
58
|
|
@@ -41,4 +64,23 @@ class RegularDonationKit < Kit
|
|
41
64
|
AdminMailer.donation_kit_notification(self).deliver
|
42
65
|
ProducerMailer.donation_kit_notification(self, organization.owner).deliver
|
43
66
|
end
|
44
|
-
|
67
|
+
|
68
|
+
def suggested_gifts=(value)
|
69
|
+
value = value.values if value.is_a?(Hash)
|
70
|
+
|
71
|
+
value = value.map do |suggested_gift|
|
72
|
+
suggested_gift = { :amount => suggested_gift } if [String, Fixnum, Bignum, Float, BigDecimal].any? { |klass| suggested_gift.is_a?(klass) }
|
73
|
+
suggested_gift[:amount] = suggested_gift[:amount].to_i
|
74
|
+
suggested_gift.delete :level_name if suggested_gift[:level_name].blank?
|
75
|
+
suggested_gift.with_indifferent_access
|
76
|
+
end.reject do |suggested_gift|
|
77
|
+
suggested_gift[:amount].to_i <= 0
|
78
|
+
end.sort do |l, r|
|
79
|
+
l[:amount] <=> r[:amount]
|
80
|
+
end
|
81
|
+
|
82
|
+
self.settings = {} unless self.settings.is_a?(Hash)
|
83
|
+
self.settings[:suggested_gifts] = value
|
84
|
+
self.settings_will_change!
|
85
|
+
end
|
86
|
+
end
|