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
@@ -123,8 +123,6 @@ h4
123
123
  img#logo
124
124
  float: left
125
125
  margin-right: 10px
126
-
127
- h1#logo
128
126
 
129
127
  ul#shows, ul#memberships
130
128
  clear: both
@@ -230,56 +228,6 @@ table.calendar
230
228
  #shopping-cart
231
229
  width: auto
232
230
  background-color: #e6e6e6 !important
233
- #steps
234
- display: none
235
- position: static
236
- background: #fff
237
- position: static
238
- width: 650px
239
- margin: 0px auto
240
- padding: 50px
241
- padding-top: 10px
242
- padding-bottom: 0
243
- height: 380px
244
- overflow: auto
245
- ul#nav
246
- width: 650px
247
- margin: 0 auto
248
- overflow: hidden
249
- margin-bottom: 20px
250
- li
251
- float: left
252
- list-style: none
253
- letter-spacing: 0
254
- font-family: "Helvetica", Arial, arial, sans-serif
255
- word-spacing: normal
256
- &.active a
257
- background-color: $compliment_highlight
258
- color: #fff
259
- font-weight: normal
260
- &.disabled a
261
- color: #BBB
262
- cursor: default
263
- a
264
- @include rounded-corners(15px, 15px, 15px, 15px)
265
- font-size: 12px
266
- padding-top: 8px
267
- padding-bottom: 8px
268
- margin-top: 4px
269
- padding-right: 12px
270
- padding-left: 12px
271
- margin-right: 2px
272
- line-height: 14px
273
- display: block
274
- color: #333
275
- &:hover
276
- text-decoration: none
277
- lable.error
278
- color: red
279
- .tab-pane
280
- display: none
281
- &.active
282
- display: block
283
231
 
284
232
  #cart
285
233
  width: 100%
@@ -412,15 +360,7 @@ table.calendar
412
360
  text-shadow: none
413
361
  color: #fff
414
362
  background-color: #a85300
415
- background-image: -khtml-gradient(linear, left top, left bottom, from(#f8930a), to(#a85300))
416
- background-image: -moz-linear-gradient(top, #f8930a, #a85300)
417
- background-image: -ms-linear-gradient(top, #f8930a, #a85300)
418
- background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f8930a), color-stop(100%, #a85300))
419
- background-image: -webkit-linear-gradient(top, #f8930a, #a85300)
420
- background-image: -o-linear-gradient(top, #f8930a, #a85300)
421
- background-image: linear-gradient(top, #f8930a, #a85300)
422
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8930a', endColorstr='#a85300', GradientType=0)
423
- border-color: #a85300 #a85300 #003f81
363
+ background-image: none
424
364
 
425
365
  .navbar .btn.primary
426
366
  margin-top: 3px
@@ -502,7 +442,7 @@ tr.no-border
502
442
  padding: 3px
503
443
  border: 1px solid #eee
504
444
 
505
- #event-header
445
+ #event-header, #donate-now-header
506
446
  h1
507
447
  font-family: 'Roboto', sans-serif
508
448
  font-weight: 300
@@ -511,6 +451,19 @@ tr.no-border
511
451
  font-weight: 100
512
452
  margin: 0px 0px 2px 0px
513
453
 
454
+ #donate-now-header
455
+ text-align: center
456
+ margin-bottom: 30px
457
+
458
+ #donate-now-container
459
+ margin-top: -30px
460
+ padding: 50px 20px 60px 20px
461
+ box-shadow: 6px 5px 5px -5px #999, -6px 5px 5px -5px #999
462
+
463
+ #donate-now
464
+ text-align: center
465
+ margin-top: 20px
466
+
514
467
  .available-ticket-type-table
515
468
  form
516
469
  margin: 0px
@@ -538,3 +491,40 @@ tr.no-border
538
491
  #poster-modal
539
492
  .modal-body
540
493
  text-align: center
494
+
495
+ .add-donation-to-cart
496
+ .preset-amount
497
+ float: left
498
+ width: 227px
499
+ // height: 28px
500
+ margin-bottom: 10px
501
+ text-align: left
502
+
503
+ .add-donation-to-cart
504
+ .preset-amount.last
505
+ width: 455px
506
+
507
+ .add-donation-to-cart
508
+ .preset-amount
509
+ label
510
+ margin: 0
511
+ padding: 0
512
+ // height: 28px
513
+ line-height: 28px
514
+
515
+ .add-donation-to-cart
516
+ .preset-amount
517
+ label
518
+ input[type='radio']
519
+ float: none
520
+ vertical-align: baseline
521
+ margin-top: 0
522
+
523
+ #event-header.side-section
524
+ h4
525
+ padding-bottom: 8px
526
+ #subtitle
527
+ padding-bottom: 8px
528
+ font-weight: bold
529
+ line-height: 1.4em
530
+ font-size: 1em
@@ -1,4 +1,4 @@
1
- /*
1
+ /*
2
2
  *= require bootstrap
3
3
  *= require sass/cart
4
4
  *= require sass/store
@@ -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 meed it because it defines its own sold_price method
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
- response = http_party.post(PDF_POST_URL, pdf_attributes)
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
@@ -95,6 +95,7 @@ class EventsController < ArtfullyOseController
95
95
  end
96
96
 
97
97
  def widget
98
+ @donation_kit = current_user.current_organization.kit(:regular_donation)
98
99
  end
99
100
 
100
101
  def storefront_link
@@ -7,6 +7,9 @@ class ExportController < ArtfullyOseController
7
7
  send_data @csv_string, :filename => @filename, :type => "text/csv", :disposition => "attachment"
8
8
  end
9
9
 
10
+ #
11
+ # Artful.ly generates these nightly and provides links directly to s3
12
+ #
10
13
  def donations
11
14
  @organization = current_user.current_organization
12
15
  @filename = "Artfully-Donations-Export-#{DateTime.now.strftime("%m-%d-%y")}.csv"
@@ -15,8 +18,15 @@ class ExportController < ArtfullyOseController
15
18
  send_data @csv_string, :filename => @filename, :type => "text/csv", :disposition => "attachment"
16
19
  end
17
20
 
21
+ #
22
+ # Artful.ly generates these nightly and provides links directly to s3
23
+ #
18
24
  def ticket_sales
19
- # Moved to s3. Generated nightly with rake csv:sales
25
+ @organization = current_user.current_organization
26
+ @filename = "Artfully-Ticket-Sales-Export-#{DateTime.now.strftime("%m-%d-%y")}.csv"
27
+ @items = ItemView.where(:organization_id => current_organization).where(:product_type => "Ticket").all
28
+ @csv_string = @items.to_comma(:ticket_sale)
29
+ send_data @csv_string, :filename => @filename, :type => "text/csv", :disposition => "attachment"
20
30
  end
21
31
 
22
32
  end
@@ -23,9 +23,8 @@ class ImportsController < ArtfullyOseController
23
23
  # Building an import preview was just murdering us. The problem is way down in Array.index in parsed_row.load_value.
24
24
  # Temporarily shutting it off for > 1000
25
25
  #
26
- @under_limit = @import.import_rows.count < 1000
27
- if @import.status == "pending" && @under_limit
28
- @parsed_rows = @import.parsed_rows.paginate(:page => params[:page], :per_page => 50)
26
+ if @import.status == "pending"
27
+ @imported_rows = @import.import_rows.paginate(:page => params[:page], :per_page => 50)
29
28
  end
30
29
 
31
30
  @people = Person.where(:import_id => @import.id).paginate(:page => params[:page], :per_page => 50) unless @import.id.nil?
@@ -4,9 +4,8 @@ class MemberCardsController < ArtfullyOseController
4
4
  before_filter :find_members
5
5
 
6
6
  def new
7
- generator = MemberCardGenerator::BlanksUsaIdc6.new(@members)
8
- generator.generate
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
 
@@ -40,6 +40,7 @@ class OrganizationsController < ArtfullyOseController
40
40
 
41
41
  if @organization.save
42
42
  @organization.users << current_user
43
+ @organization.make_owner(current_user)
43
44
  redirect_to organizations_url, :notice => "#{@organization.name} has been created"
44
45
  else
45
46
  render :new
@@ -1,5 +1,25 @@
1
1
  class PassesReportsController < ArtfullyOseController
2
2
  def index
3
- @pass_types = current_organization.pass_types.all
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
@@ -0,0 +1,32 @@
1
+ class RegularDonationKitsController < ApplicationController
2
+ rescue_from CanCan::AccessDenied do |exception|
3
+ flash[:alert] = exception.message
4
+ redirect_to root_path, :alert => exception.message
5
+ end
6
+
7
+ before_filter do
8
+ authorize! :edit, current_user.current_organization
9
+ end
10
+
11
+ def edit
12
+ @kit = Kit.find(params[:id])
13
+ end
14
+
15
+ def update
16
+ @kit = Kit.find(params[:id])
17
+
18
+ if @kit.update_attributes(kit_params)
19
+ flash[:notice] = 'Your changes have been saved.'
20
+ redirect_to organization_path(@kit.organization)
21
+ else
22
+ flash[:error] = 'We had a problem configuring your kit. Please try again.'
23
+ render :edit
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def kit_params
30
+ params[:regular_donation_kit]
31
+ end
32
+ end
@@ -1,4 +1,22 @@
1
1
  class Store::DonationsController < Store::StoreController
2
+ rescue_from ActiveRecord::RecordNotFound do
3
+ render :text => File.read("#{Rails.root}/public/404.html"),
4
+ :content_type => Mime::HTML,
5
+ :status => :not_found
6
+ end
7
+
2
8
  def index
9
+ # If there is no kit at all, NotFound
10
+ raise ActionController::RoutingError.new('Not Found') unless @store_organization.has_kit?(:regular_donation)
11
+
12
+ # If there's a kit, and they're logged in, show them a preview if the kit is off
13
+ if current_user && current_user.current_organization == @store_organization
14
+ if !@store_organization.has_active_donation_only_storefront?
15
+ flash[:notice] = "You are seeing a preview of your donation-only storefront. To make this page visible to the general public, go to your 501(c)(3) kit configuration and check \"Display Donation-Only Storefront\""
16
+ end
17
+ else
18
+ # show everyone else NotFound
19
+ raise ActionController::RoutingError.new('Not Found') unless @store_organization.has_active_donation_only_storefront?
20
+ end
3
21
  end
4
- end
22
+ end
@@ -1,18 +1,29 @@
1
1
  class Store::OrdersController < Store::StoreController
2
2
  include ActionView::Helpers::TextHelper
3
3
  include ArtfullyOseHelper
4
-
4
+
5
5
  def update
6
6
  handler = OrderHandler.new(current_cart, current_member)
7
- handler.handle_tickets(params)
7
+ handler.handle_tickets(params)
8
8
  handler.handle_donation(params, @store_organization)
9
9
  handler.handle_memberships(params, current_member)
10
10
  handler.handle_passes(params)
11
11
  handler.handle_discount_or_pass_code(params)
12
12
 
13
- flash[:alert] = handler.error unless handler.error.blank?
13
+ if handler.error.present?
14
+ flash[:alert] = handler.error unless handler.error.blank?
15
+
16
+ redirect_url = case params[:_source]
17
+ when 'storefront'
18
+ store_donate_path
19
+ else
20
+ store_order_path
21
+ end
14
22
 
15
- redirect_to store_order_path
23
+ redirect_to redirect_url
24
+ else
25
+ redirect_to store_order_path
26
+ end
16
27
  end
17
28
 
18
29
  def show
@@ -50,7 +61,6 @@ class Store::OrdersController < Store::StoreController
50
61
  end
51
62
 
52
63
  private
53
-
54
64
  def event
55
65
  current_cart.tickets.first.event
56
66
  end