artfully_ose 1.3.0.pre3 → 1.3.0.pre4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/loading-white.gif +0 -0
  3. data/app/assets/images/seating_temp/1.jpg +0 -0
  4. data/app/assets/images/seating_temp/10.jpg +0 -0
  5. data/app/assets/images/seating_temp/11.jpg +0 -0
  6. data/app/assets/images/seating_temp/2.jpg +0 -0
  7. data/app/assets/images/seating_temp/3.jpg +0 -0
  8. data/app/assets/images/seating_temp/4.jpg +0 -0
  9. data/app/assets/images/seating_temp/5.jpg +0 -0
  10. data/app/assets/images/seating_temp/6.jpg +0 -0
  11. data/app/assets/images/seating_temp/7.jpg +0 -0
  12. data/app/assets/images/seating_temp/8.jpg +0 -0
  13. data/app/assets/images/seating_temp/9.jpg +0 -0
  14. data/app/assets/images/seating_temp/icon_43405.png +0 -0
  15. data/app/assets/images/seating_temp/icon_43405.svg +3 -0
  16. data/app/assets/images/seating_temp/icon_43405_plus.png +0 -0
  17. data/app/assets/images/seating_temp/license.txt +8 -0
  18. data/app/assets/javascripts/application.js +1 -0
  19. data/app/assets/javascripts/custom/cookies.js +27 -0
  20. data/app/assets/javascripts/custom/inline-people-search.js +4 -0
  21. data/app/assets/javascripts/custom/job-monitor.js +0 -1
  22. data/app/assets/javascripts/exchange-seat-chart.js +5 -0
  23. data/app/assets/javascripts/seat-chart.js +606 -0
  24. data/app/assets/javascripts/show-seat-chart.js +17 -0
  25. data/app/assets/javascripts/store/store-seat-chart.js +76 -0
  26. data/app/assets/javascripts/store/store.js +14 -39
  27. data/app/assets/stylesheets/application.sass +49 -1
  28. data/app/assets/stylesheets/bootstrap-overrides.css +11 -3
  29. data/app/assets/stylesheets/sass/seat-chart.sass +311 -0
  30. data/app/assets/stylesheets/sass/store.sass +73 -19
  31. data/app/assets/stylesheets/storefront.css +2 -0
  32. data/app/concerns/pdf_generation.rb +1 -15
  33. data/app/controllers/advanced_searches_controller.rb +1 -3
  34. data/app/controllers/charts_controller.rb +14 -12
  35. data/app/controllers/console_sales_controller.rb +55 -0
  36. data/app/controllers/event_calendars_controller.rb +15 -0
  37. data/app/controllers/events_controller.rb +16 -5
  38. data/app/controllers/exchanges_controller.rb +32 -9
  39. data/app/controllers/export_controller.rb +8 -0
  40. data/app/controllers/members/sessions_controller.rb +0 -2
  41. data/app/controllers/membership_comps_controller.rb +2 -1
  42. data/app/controllers/prices_controller.rb +20 -0
  43. data/app/controllers/shows_controller.rb +3 -1
  44. data/app/controllers/store/events_controller.rb +6 -5
  45. data/app/controllers/store/orders_controller.rb +11 -13
  46. data/app/controllers/store/shows_controller.rb +1 -0
  47. data/app/controllers/store/store_controller.rb +11 -0
  48. data/app/controllers/tickets_controller.rb +0 -28
  49. data/app/controllers/user_memberships_controller.rb +7 -2
  50. data/app/controllers/venues_controller.rb +9 -0
  51. data/app/helpers/artfully_ose_helper.rb +18 -4
  52. data/app/helpers/seating_helper.rb +157 -0
  53. data/app/models/assigned_chart.rb +220 -0
  54. data/app/models/cart.rb +6 -1
  55. data/app/models/chart.rb +28 -17
  56. data/app/models/database_views/item_view.rb +76 -5
  57. data/app/models/discount.rb +4 -0
  58. data/app/models/discounts/buy_one_get_one_free_discount_type.rb +1 -1
  59. data/app/models/discounts/dollars_off_tickets_discount_type.rb +5 -1
  60. data/app/models/discounts/percentage_off_tickets_discount_type.rb +8 -4
  61. data/app/models/event.rb +86 -12
  62. data/app/models/general_admission_chart.rb +51 -0
  63. data/app/models/imports/events_import.rb +1 -1
  64. data/app/models/job/show_creator.rb +3 -10
  65. data/app/models/kit.rb +11 -1
  66. data/app/models/kits/assigned_seating_kit.rb +23 -0
  67. data/app/models/member_walkup.rb +1 -1
  68. data/app/models/order_handler.rb +22 -6
  69. data/app/models/organization.rb +4 -5
  70. data/app/models/person.rb +3 -1
  71. data/app/models/sale.rb +1 -1
  72. data/app/models/seat.rb +96 -0
  73. data/app/models/section.rb +1 -3
  74. data/app/models/show.rb +10 -17
  75. data/app/models/ticket.rb +30 -6
  76. data/app/models/ticket/locker.rb +3 -2
  77. data/app/models/ticket_type.rb +12 -6
  78. data/app/models/ticket_types_seat.rb +4 -0
  79. data/app/models/venue.rb +23 -0
  80. data/app/views/advanced_searches/filters/_birthday.html.haml +1 -0
  81. data/app/views/assigned_charts/_show.html.haml +12 -0
  82. data/app/views/console_sales/_aloha.html.haml +5 -4
  83. data/app/views/console_sales/new.html.haml +9 -0
  84. data/app/views/event_calendars/index.html.haml +34 -0
  85. data/app/views/events/_menu.html.haml +2 -1
  86. data/app/views/events/_section_fields.html.haml +13 -8
  87. data/app/views/events/new.html.haml +34 -4
  88. data/app/views/events/prices.html.haml +3 -4
  89. data/app/views/events/seating.html.haml +131 -0
  90. data/app/views/exchanges/_assigned_chart.html.haml +108 -0
  91. data/app/views/exchanges/_general_admission_chart.html.haml +55 -0
  92. data/app/views/exchanges/new.html.haml +1 -55
  93. data/app/views/general_admission_charts/_show.html.haml +2 -0
  94. data/app/views/layouts/_menu.html.haml +44 -31
  95. data/app/views/layouts/storefront.html.haml +72 -30
  96. data/app/views/membership_comps/new.html.haml +1 -0
  97. data/app/views/order_mailer/confirmation_for.html.haml +5 -3
  98. data/app/views/order_mailer/confirmation_for.text.haml +1 -2
  99. data/app/views/pdfs/order.html.haml +20 -6
  100. data/app/views/seating/_actions_menu.html.haml +10 -0
  101. data/app/views/seating/_chart.html.haml +15 -0
  102. data/app/views/seating/_chart_container.html.haml +2 -0
  103. data/app/views/seating/_chart_note_display.html.haml +7 -0
  104. data/app/views/seating/_hold_seats_modal.html.haml +39 -0
  105. data/app/views/seating/_layer_menu.html.haml +23 -0
  106. data/app/views/seating/_legend.html.haml +52 -0
  107. data/app/views/seating/_modify_seats_modal.html.haml +29 -0
  108. data/app/views/seating/_ticket_type_modals.html.haml +41 -0
  109. data/app/views/shows/_seat_chart.html.haml +122 -0
  110. data/app/views/shows/_sections_table.html.haml +3 -24
  111. data/app/views/shows/_ticket_table.html.haml +4 -2
  112. data/app/views/shows/_work_with.html.haml +4 -0
  113. data/app/views/shows/new.html.haml +2 -2
  114. data/app/views/shows/show.html.haml +93 -14
  115. data/app/views/store/assigned_charts/_show.html.haml +54 -0
  116. data/app/views/store/checkouts/shopping_cart_display/_tickets.haml +13 -0
  117. data/app/views/store/donations/index.html.haml +1 -1
  118. data/app/views/store/events/calendar.html.haml +94 -11
  119. data/app/views/store/events/index.html.haml +1 -1
  120. data/app/views/store/events/show.html.haml +36 -2
  121. data/app/views/store/events/single_show.html.haml +5 -4
  122. data/app/views/store/general_admission_charts/_show.html.haml +41 -0
  123. data/app/views/store/orders/show.html.haml +17 -4
  124. data/app/views/store/shared/_donate_form.html.haml +2 -1
  125. data/app/views/store/shared/_small_donate_form.html.haml +1 -1
  126. data/app/views/store/shows/_show.html.haml +1 -39
  127. data/app/views/ticket_types/edit.html.haml +1 -1
  128. data/app/views/user_memberships/_list.html.haml +1 -1
  129. data/app/views/venues/edit.html.haml +1 -1
  130. data/app/views/venues/show.html.haml +11 -0
  131. data/config/routes.rb +27 -10
  132. data/db/migrate/20140828174357_add_type_to_chart.rb +7 -0
  133. data/db/migrate/20140828195617_create_seats.rb +16 -0
  134. data/db/migrate/20140829135426_add_venue_to_chart.rb +5 -0
  135. data/db/migrate/20140829143520_add_assigned_to_event.rb +5 -0
  136. data/db/migrate/20140904164927_add_fields_to_seat.rb +14 -0
  137. data/db/migrate/20140912170010_add_note_to_seat.rb +6 -0
  138. data/db/migrate/20140919152307_add_seats_to_ticket.rb +5 -0
  139. data/db/migrate/20140930224543_add_public_note_to_chart.rb +5 -0
  140. data/db/migrate/20141001140737_add_seat_id_index_to_tickets.rb +5 -0
  141. data/db/migrate/20141001193242_associate_hold_with_person.rb +6 -0
  142. data/db/migrate/20141021175311_create_ticket_types_seats.rb +11 -0
  143. data/db/migrate/20150106161744_migrate_charts_back_to_venues.rb +18 -0
  144. data/db/migrate/20151105085424_add_creator_to_items_view.rb +40 -0
  145. data/lib/artfully_ose/version.rb +1 -1
  146. data/spec/factories/assigned_chart_factories.rb +18 -0
  147. data/spec/factories/chart_factories.rb +4 -8
  148. data/spec/factories/kit_factories.rb +4 -0
  149. data/spec/factories/seat_factories.rb +4 -0
  150. data/spec/factories/show_factories.rb +1 -1
  151. metadata +66 -5
  152. data/app/models/ticket/foundry.rb +0 -48
  153. data/app/models/ticket/template.rb +0 -40
  154. data/app/views/store/events/_calendar.html.haml +0 -13
@@ -3,8 +3,6 @@ class Members::SessionsController < Devise::SessionsController
3
3
 
4
4
  def new
5
5
  @org = Organization.find_by_name(params[:org_name])
6
- # Store the referrer so we can send them back
7
- # where they started after successful sign in.
8
6
  session[:continue] = request.referrer
9
7
  super
10
8
  end
@@ -18,8 +18,9 @@ class MembershipCompsController < ArtfullyOseController
18
18
  @membership_comp.send_email ||= true
19
19
  @membership_comp.number_of_memberships ||= 1
20
20
  @membership_comp.person_id = params[:person_id]
21
- @membership_comp.segment_id = params[:segment_id]
21
+ @membership_comp.segment_id = params[:segment_id]
22
22
  @membership_comp.search_id = params[:search_id]
23
+ @membership_comp.advanced_search_id = params[:advanced_search_id]
23
24
  @membership_comp.organization = current_user.current_organization
24
25
  @membership_comp.find_people
25
26
  end
@@ -0,0 +1,20 @@
1
+ class PricesController < ApplicationController
2
+ def update
3
+ @chart = Chart.find(params[:id])
4
+ authorize! :edit, @chart
5
+
6
+ if @chart.update_attributes_from_params(Chart.polish_params(params[:chart]))
7
+ flash[:notice] = "Prices saved."
8
+ else
9
+ flash[:error] = "Please name all of your ticket types."
10
+ redirect_to prices_event_url(@chart.event) and return
11
+ end
12
+
13
+ if user_requesting_next_step?
14
+ redirect_to seating_event_path(@chart.event)
15
+ #redirect_to image_event_path(@chart.event)
16
+ else
17
+ redirect_to prices_event_url(@chart.event)
18
+ end
19
+ end
20
+ end
@@ -33,7 +33,7 @@ class ShowsController < ArtfullyOseController
33
33
  end
34
34
 
35
35
  def new
36
- @show = @event.next_show
36
+ @show = @event.build_next_show
37
37
  end
38
38
 
39
39
  def calendar
@@ -85,7 +85,9 @@ class ShowsController < ArtfullyOseController
85
85
  def show
86
86
  @show = Show.includes(:event => :venue, :tickets => :section).find(params[:id])
87
87
  authorize! :view, @show
88
+ @chart = Chart.includes(@show.chart.class.included_models).find(@show.chart_id)
88
89
  @tickets = @show.tickets
90
+ @show.chart = @chart
89
91
  end
90
92
 
91
93
  def edit
@@ -6,14 +6,15 @@ class Store::EventsController < Store::StoreController
6
6
  @shows = @event.upcoming_shows_rel.published
7
7
 
8
8
  if @shows.count < 5
9
- @shows = @shows.includes(:event, :chart => [:sections => :ticket_types])
10
- elsif
11
- dates = @shows.collect(&:datetime_local_to_event).map {|d| d.to_date}
12
- @dates_by_month = dates.group_by {|d| d.strftime("%B %Y")}
9
+ @shows = @shows.includes(:event => :events_pass_types, :chart => @event.default_chart.class.included_models)
10
+ elsif session[:last_show_uuid]
11
+ @previous_show = @event.shows.find_by_uuid(session[:last_show_uuid])
13
12
  end
14
13
 
14
+ @current_membership_types = current_member.try(:current_membership_types)
15
+
15
16
  render :single_show and return if @event.single_show?
16
- render :calendar and return if @event.upcoming_public_shows.length > 4
17
+ render :calendar and return if @event.upcoming_public_shows.length > 4 || @event.assigned?
17
18
  render :show
18
19
  end
19
20
 
@@ -10,20 +10,10 @@ class Store::OrdersController < Store::StoreController
10
10
  handler.handle_passes(params)
11
11
  handler.handle_discount_or_pass_code(params)
12
12
 
13
- if handler.error.present?
14
- flash[:alert] = handler.error unless handler.error.blank?
13
+ errored = handler.error.present?
14
+ flash[:alert] = handler.error if errored
15
15
 
16
- redirect_url = case params[:_source]
17
- when 'storefront'
18
- store_donate_path
19
- else
20
- store_order_path
21
- end
22
-
23
- redirect_to redirect_url
24
- else
25
- redirect_to store_order_path
26
- end
16
+ redirect_to redirect_path(errored)
27
17
  end
28
18
 
29
19
  def show
@@ -80,4 +70,12 @@ class Store::OrdersController < Store::StoreController
80
70
  def event
81
71
  current_cart.tickets.first.event
82
72
  end
73
+
74
+ def redirect_path(errored)
75
+ if errored
76
+ params[:on_error] || store_order_path(@store_organization)
77
+ else
78
+ params[:on_success] || store_order_path(@store_organization)
79
+ end
80
+ end
83
81
  end
@@ -1,5 +1,6 @@
1
1
  class Store::ShowsController < Store::StoreController
2
2
  def show
3
+ session[:last_show_uuid] = params[:id]
3
4
  @show = Show.includes(:event, :chart).where(:uuid => params[:id]).first
4
5
  render :layout => false
5
6
  end
@@ -2,6 +2,8 @@ class Store::StoreController < ActionController::Base
2
2
  layout "storefront"
3
3
  include CartFinder
4
4
  before_filter :store_organization
5
+ before_filter :save_page_location
6
+
5
7
 
6
8
  def store_organization
7
9
  @store_organization ||= load_store_organization
@@ -25,4 +27,13 @@ class Store::StoreController < ActionController::Base
25
27
  nil
26
28
  end
27
29
  end
30
+
31
+ #
32
+ # We're saving all pages for the user
33
+ # so that if they use the modal to member login,
34
+ # devise will redirect back to what they were doing
35
+ #
36
+ def save_page_location
37
+ session[:continue] = request.original_url
38
+ end
28
39
  end
@@ -59,34 +59,6 @@ class TicketsController < ArtfullyOseController
59
59
  end
60
60
  end
61
61
 
62
- def on_sale
63
- authorize! :bulk_edit, Ticket
64
- with_confirmation do
65
- @show = Show.find(params[:show_id])
66
- @selected_tickets = params[:selected_tickets]
67
- if @show.bulk_on_sale(@selected_tickets)
68
- flash[:notice] = "Put #{to_plural(@selected_tickets.size, 'ticket')} on sale. "
69
- else
70
- flash[:error] = "Tickets that have been sold or comped can't be put on or taken off sale. A ticket that is already on sale or off sale can't be put on or off sale again."
71
- end
72
- redirect_to event_show_url(@show.event, @show)
73
- end
74
- end
75
-
76
- def off_sale
77
- authorize! :bulk_edit, Ticket
78
- with_confirmation do
79
- @show = Show.find(params[:show_id])
80
- @selected_tickets = params[:selected_tickets]
81
- if @show.bulk_off_sale(@selected_tickets)
82
- flash[:notice] = "Put #{to_plural(@selected_tickets.size, 'ticket')} off sale. "
83
- else
84
- flash[:error] = "Tickets that have been sold or comped can't be put on or taken off sale. A ticket that is already on sale or off sale can't be put on or off sale again."
85
- end
86
- redirect_to event_show_url(@show.event, @show)
87
- end
88
- end
89
-
90
62
  def delete
91
63
  @show = Show.find(params[:show_id])
92
64
  @selected_tickets = params[:selected_tickets]
@@ -11,11 +11,16 @@ class UserMembershipsController < ActionController::Base
11
11
  build_membership(user, clean_permission, @organization) or build_errors(user, @organization)
12
12
  end
13
13
 
14
-
15
-
16
14
  redirect_to organization_url(@organization, :active_tab=>"users") and return
17
15
  end
18
16
 
17
+ def reinvite
18
+ @organization = current_user.current_organization
19
+ @user = @organization.user_memberships.find(params[:id]).user
20
+ User.invite!({:email => @user.email}, current_user)
21
+ redirect_to organization_url(@organization, :active_tab=>"users"), :notice => "We've resent the invite to #{@user.email}." and return
22
+ end
23
+
19
24
  def destroy
20
25
  @organization = Organization.find(params[:organization_id])
21
26
  @mship = UserMembership.find(params[:id])
@@ -4,6 +4,15 @@ class VenuesController < ArtfullyOseController
4
4
  authorize! :edit, @event
5
5
  @venue = @event.venue
6
6
  end
7
+
8
+ #
9
+ # Used asynchronously from events/new
10
+ # For now, pass venue name as the id since we can't get it from Bootstrap's typeahead
11
+ #
12
+ def show
13
+ @venue = Venue.most_recently_named(current_organization, params[:id])
14
+ render :show, :layout => false
15
+ end
7
16
 
8
17
  def update
9
18
  @event = Event.find(params[:event_id])
@@ -27,6 +27,17 @@ module ArtfullyOseHelper
27
27
  end
28
28
  end
29
29
 
30
+ def enter_code_string
31
+ @store_organization.can?(:access, :passes) ? "Have a Discount or Pass Code?" : "Have a Discount Code?"
32
+ end
33
+
34
+ def write_membership_modal
35
+ (@store_organization.has_kit? :membership) &&
36
+ (controller_path != "store/memberships") &&
37
+ (controller_path != "store/donations") &&
38
+ !member_signed_in?
39
+ end
40
+
30
41
  def current_role
31
42
  current_user.permission_in(current_user.current_organization)
32
43
  end
@@ -70,9 +81,12 @@ module ArtfullyOseHelper
70
81
  "#{target.class.name.downcase}_#{action_path_name}_path"
71
82
  end
72
83
 
73
- def last_login(t)
74
- return "Never logged in" if t.nil?
75
- "Last login #{time_ago_in_words(t)} ago"
84
+ def last_login(user_membership)
85
+ if user_membership.user.current_sign_in_at.nil?
86
+ link_to("Resend invite", reinvite_organization_user_membership_path(@organization, user_membership), :method => :put)
87
+ else
88
+ "Last login #{time_ago_in_words(user_membership.user.current_sign_in_at)} ago"
89
+ end
76
90
  end
77
91
 
78
92
  def time_ago_sentence(t)
@@ -292,7 +306,7 @@ module ArtfullyOseHelper
292
306
  end
293
307
 
294
308
  def nav_dropdown(text, link='#')
295
- link_to ERB::Util.html_escape(text) + ' <b class="caret"></b>'.html_safe, link, :class => 'dropdown-toggle', 'data-toggle' => 'dropdown'
309
+ link_to ERB::Util.html_escape(text) + ''.html_safe, link, :class => 'dropdown-toggle', 'data-toggle' => 'dropdown'
296
310
  end
297
311
 
298
312
  def bootstrapped_type(type)
@@ -0,0 +1,157 @@
1
+ module SeatingHelper
2
+
3
+ def html_class_for(seat)
4
+ classes = ""
5
+
6
+ seat.ticket_types.each do |ticket_type|
7
+ classes = classes + "ticket-type-#{ticket_type.id} "
8
+ end
9
+
10
+ if seat.ticket && seat.ticket.sold?
11
+ classes = classes + "seat-unselectable "
12
+ else
13
+ classes = classes + "seat-selectable "
14
+ end
15
+
16
+
17
+ classes = classes + "available empty " if seat.available
18
+ #classes = classes + "sold " if seat.ticket && seat.ticket.sold?
19
+ classes = classes + "killed " if seat.killed
20
+ classes = classes + "aisle " if seat.aisle
21
+ classes = classes + "wheelchair " if seat.wheelchair
22
+ classes = classes + "wheelchair-companion " if seat.wheelchair_companion
23
+
24
+ if seat.on_hold? && (!seat.ticket || !seat.ticket.sold?)
25
+ classes = classes + "hold house-hold "
26
+ return "development-hold" if seat.development_hold
27
+ return "tech-hold" if seat.tech_hold
28
+ return "contractual-hold" if seat.contractual_hold
29
+ return "person-hold" if seat.person_hold
30
+ return "press-hold" if seat.press_hold
31
+ end
32
+
33
+ classes
34
+ end
35
+
36
+ def hold_popover_text_for(seat)
37
+ str = ""
38
+
39
+ if seat.held_for_id.present?
40
+ str += "Hold for: #{seat.held_for.to_s}"
41
+ str += "<br>"
42
+ end
43
+
44
+ str += (h seat.hold_note)
45
+
46
+ if seat.ticket.present?
47
+ str += "<br>"
48
+ str += "<br>"
49
+ str += (link_to "Sell", "javascript:showSellSeat('#{seat.id}','#{seat.label}')", :class => "btn btn-primary sell-btn", :target => "_blank")
50
+ end
51
+
52
+ str
53
+ end
54
+
55
+ def storefront_html_class_for(seat)
56
+ classes = ""
57
+ classes = classes + "seat-in-cart " if seat.ticket.cart_id == current_cart.id #current_cart.tickets.include?(seat.ticket)
58
+ classes = classes + "available empty " if seat.available_for_purchase
59
+ classes = classes + "filled " if !seat.available_for_purchase
60
+ classes = classes + "aisle " if seat.aisle
61
+ classes = classes + "wheelchair " if seat.wheelchair
62
+ classes = classes + "wheelchair-companion " if seat.wheelchair_companion
63
+
64
+ if current_cart.discount.present?
65
+ if (current_cart.discount.ticket_types & seat.ticket_types.collect(&:name)).present?
66
+ classes = classes + "member-on "
67
+ else
68
+ classes = classes + "member-off "
69
+ end
70
+ end
71
+
72
+ if current_cart.applied_pass.present?
73
+ if current_cart.applied_pass.applies_to? (seat)
74
+ classes = classes + "member-on "
75
+ else
76
+ classes = classes + "member-off "
77
+ end
78
+ end
79
+
80
+ if current_member
81
+ if seat.member_ticket_for? @current_membership_types
82
+ classes = classes + "member-on "
83
+ else
84
+ classes = classes + "member-off "
85
+ end
86
+ end
87
+
88
+ classes
89
+ end
90
+
91
+ def exchange_html_class_for(seat, ticket_type)
92
+
93
+ classes = ""
94
+
95
+ if !seat.available_for_purchase || !seat.ticket_types.include?(ticket_type)
96
+ classes = classes + "filled "
97
+ classes = classes + "seat-unselectable "
98
+ elsif seat.available_for_purchase && seat.ticket_types.include?(ticket_type)
99
+ classes = classes + "available empty "
100
+ classes = classes + "seat-selectable "
101
+ end
102
+
103
+ classes = classes + "aisle " if seat.aisle
104
+ classes = classes + "wheelchair " if seat.wheelchair
105
+ classes = classes + "wheelchair-companion " if seat.wheelchair_companion
106
+
107
+ classes
108
+ end
109
+
110
+ def storefront_html_class_for(seat)
111
+ classes = ""
112
+ classes = classes + "seat-in-cart " if seat.ticket.cart_id == current_cart.id #current_cart.tickets.include?(seat.ticket)
113
+ classes = classes + "available empty " if seat.available_for_purchase
114
+ classes = classes + "filled " if !seat.available_for_purchase
115
+ classes = classes + "aisle " if seat.aisle
116
+ classes = classes + "wheelchair " if seat.wheelchair
117
+ classes = classes + "wheelchair-companion " if seat.wheelchair_companion
118
+
119
+ if current_cart.discount.present?
120
+ if (current_cart.discount.ticket_types & seat.ticket_types.collect(&:name)).present?
121
+ classes = classes + "member-on "
122
+ else
123
+ classes = classes + "member-off "
124
+ end
125
+ end
126
+
127
+ if current_cart.applied_pass.present?
128
+ if current_cart.applied_pass.applies_to? (seat)
129
+ classes = classes + "member-on "
130
+ else
131
+ classes = classes + "member-off "
132
+ end
133
+ end
134
+
135
+ if current_member
136
+ if seat.member_ticket_for? @current_membership_types
137
+ classes = classes + "member-on "
138
+ else
139
+ classes = classes + "member-off "
140
+ end
141
+ end
142
+
143
+ classes
144
+ end
145
+
146
+ def hold_header_for(seat)
147
+ "House Hold"
148
+ end
149
+
150
+ def ticket_type_pseudo_array_for(seat)
151
+ seat.ticket_types.collect(&:id).join(",")
152
+ end
153
+
154
+ def css_class(ticket_type)
155
+ ((ticket_type.name || "") + " " + (ticket_type.id || "").to_s).parameterize
156
+ end
157
+ end
@@ -0,0 +1,220 @@
1
+ class AssignedChart < Chart
2
+ has_many :seats, :foreign_key => "chart_id"
3
+ belongs_to :venue
4
+
5
+ def by_rows(row_key = :row_index)
6
+ rows = {}
7
+ self.seats.each do |seat|
8
+ seats_in_row = rows.fetch(seat.send(row_key), [])
9
+ seats_in_row << seat
10
+ rows[seat.send(row_key)] = seats_in_row
11
+ end
12
+ rows
13
+ end
14
+
15
+ #
16
+ # Suitable for chaining includes
17
+ # :chart => chart.class.included_models
18
+ #
19
+ def self.included_models
20
+ [:seats => [:held_for, :ticket, :ticket_types]]
21
+ end
22
+
23
+ def num_columns
24
+ #col_index starts with zero
25
+ self.seats.empty? ? 0 : self.seats.collect(&:col_index).max + 1
26
+ end
27
+
28
+ def create_tickets
29
+ raise "Only charts that have been assigned to shows can create tickets" if self.show.nil?
30
+ self.seats.each do |seat|
31
+ seat.create_ticket
32
+ end
33
+ end
34
+
35
+ def sync(seat_hash)
36
+
37
+ transaction do
38
+ updated_ids = []
39
+ Rails.logger.debug("CHARTSYNC received: #{seat_hash}")
40
+ seats = self.seats.includes(:ticket_types, :ticket).all
41
+ ticket_type_hash = {}
42
+ self.ticket_types.each {|ticket_type| ticket_type_hash[ticket_type.id] = ticket_type}
43
+ seat_hash["seatRows"].each do |seat_row|
44
+ Rails.logger.debug("CHARTSYNC handling row: #{seat_row["rowIndex"]}")
45
+ row_label = seat_row["rowLabel"]
46
+ row_index = seat_row["rowIndex"]
47
+ seat_row["seats"].each do |json_seat|
48
+
49
+ Rails.logger.debug("CHARTSYNC -")
50
+
51
+ Rails.logger.debug("CHARTSYNC handling seat: #{json_seat["colIndex"]}")
52
+ Rails.logger.debug("CHARTSYNC updating seat with id: [#{json_seat["id"]}]")
53
+ seat = seats.find{|s| s.id == json_seat["id"].to_i}
54
+ if seat.present?
55
+ Rails.logger.debug("CHARTSYNC found seat: #{seat.inspect}")
56
+ else
57
+ Rails.logger.debug("CHARTSYNC no seat found. Creating a new seat.")
58
+ seat = Seat.new if seat.nil?
59
+ end
60
+ #seat = Seat.where(:id => json_seat["id"]).first_or_initialize
61
+ updated_ids <<json_seat["id"]
62
+ seat.chart = self
63
+ seat.row_index = row_index
64
+ seat.row_label = row_label
65
+
66
+ seat.col_index = json_seat["colIndex"]
67
+ seat.col_label = (json_seat["colIndex"].to_i + 1).to_s
68
+
69
+ seat.label = json_seat["label"]
70
+ seat.available = json_seat["available"]
71
+ seat.killed = json_seat["killed"]
72
+ seat.aisle = json_seat["aisle"]
73
+ seat.wheelchair = json_seat["wheelchair"]
74
+ seat.wheelchair_companion = json_seat["wheelchairCompanion"]
75
+
76
+ seat.house_hold = json_seat["houseHold"]
77
+ seat.development_hold = json_seat["developmentHold"]
78
+ seat.tech_hold = json_seat["techHold"]
79
+ seat.contractual_hold = json_seat["contractualHold"]
80
+ seat.person_hold = json_seat["personHold"]
81
+ seat.press_hold = json_seat["pressHold"]
82
+
83
+ seat.hold_note = json_seat["holdNote"]
84
+ seat.held_for_id = json_seat["holdPersonId"]
85
+ seat.seat_note = json_seat["seatNote"]
86
+
87
+ Rails.logger.debug("CHARTSYNC ticket_types are: #{json_seat["ticketTypeIds"]}")
88
+
89
+ if (seat.ticket_types.collect(&:id) != json_seat["ticketTypeIds"].collect{|tt| tt.to_i})
90
+ seat.ticket_types_seats.destroy_all
91
+ json_seat["ticketTypeIds"].each do |ticket_type_id|
92
+ Rails.logger.debug("CHARTSYNC adding ticket_type: #{ticket_type_id}")
93
+ #seat.ticket_types << TicketType.find(ticket_type_id)
94
+ seat.ticket_types << ticket_type_hash[ticket_type_id.to_i]
95
+ end
96
+ else
97
+ Rails.logger.debug("CHARTSYNC no changes to ticket types")
98
+ end
99
+
100
+ Rails.logger.debug("CHARTSYNC saving seat: #{seat.inspect}")
101
+ seat.update_ticket
102
+ Rails.logger.debug("CHARTSYNC Changed: #{seat.changes}")
103
+ seat.save
104
+ seat.create_ticket
105
+ end
106
+ end
107
+ # deleted_ids = self.seats.collect(&:id).select{|id| updated_ids.exclude?(id)}
108
+ Rails.logger.debug("CHARTSYNC updated seats: #{updated_ids}")
109
+ self.seats.where('id not in (?)', updated_ids).destroy_all unless updated_ids.blank?
110
+ self.show.delay.refresh_stats if self.show
111
+ self.event.venue.delay.update_default_chart_from(self) if self.event
112
+ end
113
+
114
+ end
115
+
116
+ #
117
+ # Pass a venue or event
118
+ #
119
+ def self.default_chart_for(chartable)
120
+ chart = AssignedChart.where(chartable.class.name.foreign_key.to_sym => chartable.id)
121
+ .where(:is_template => true)
122
+ .first
123
+ return chart unless chart.nil?
124
+
125
+ chart = AssignedChart.new
126
+ ["A","B","C","D","E","F","G","H","I","J"].each_with_index do |row_label, index|
127
+ (0..9).each do |col_index|
128
+ seat = chart.seats.build({:row_index => index,
129
+ :col_index => col_index,
130
+ :row_label => row_label,
131
+ :col_label => col_index + 1,
132
+ :label => "#{row_label}#{col_index+1}",
133
+ :available => true})
134
+ chart.seats << seat
135
+ end
136
+ end
137
+ chart.is_template = true
138
+ chart.send("#{chartable.class.name.downcase}=", chartable)
139
+ chart.name = chartable.name
140
+ chart.organization = chartable.organization
141
+ chart
142
+ end
143
+ def update_attributes_from_params(params_hash = {}, parent_chart = nil)
144
+ super(params_hash)
145
+ attach_ticket_types_to_seats(parent_chart)
146
+ end
147
+
148
+ #
149
+ # Rebuild-the ticket types from the parent_chart
150
+ #
151
+ def attach_ticket_types_to_seats(parent_chart)
152
+ return if parent_chart.nil?
153
+ seats.each do |seat|
154
+ parent_seat = parent_chart.seats
155
+ .where(:row_index => seat.row_index)
156
+ .where(:col_index => seat.col_index)
157
+ .first
158
+
159
+ Rails.logger.debug("SEATS parent_seat #{parent_seat.inspect}")
160
+ parent_seat.ticket_types.each do |parent_ticket_type|
161
+ Rails.logger.debug("SEATS parent ticket type #{parent_ticket_type.inspect}")
162
+ Rails.logger.debug("SEATS my ticket types #{self.ticket_types.inspect}")
163
+ ticket_type = self.ticket_types.find{|tt| tt.name == parent_ticket_type.name}
164
+ Rails.logger.debug("SEATS found ticket_type #{ticket_type.inspect}")
165
+ if ticket_type
166
+ seat.ticket_types << ticket_type
167
+ Rails.logger.debug seat.ticket_types.inspect
168
+ end
169
+ end
170
+
171
+ seat.save if self.persisted?
172
+ end
173
+ end
174
+
175
+ #
176
+ # Returns an array of available tickets as well as an error
177
+ # [[ ticket array ], "error message suitable for end-user display"]
178
+ #
179
+ # this method ignores ticket_limit
180
+ #
181
+ def get_available_tickets(ticket_type, ticket_limit = 4, member = nil, seat = nil, cart = nil)
182
+ #
183
+ # TODO: check member, ticket holds, etc...
184
+ #
185
+
186
+ available_to = 1
187
+ if member && ticket_type.member_ticket?
188
+ Rails.logger.debug("ASSIGNED SEATING Checking for tickets available to this member")
189
+ available_to = ticket_type.available_to(member)
190
+ Rails.logger.debug("ASSIGNED SEATING available_to #{available_to}")
191
+ already_in_cart = cart.tickets.select{|t| t.ticket_type == ticket_type}.length
192
+ Rails.logger.debug("ASSIGNED SEATING already in cart #{already_in_cart}")
193
+ available_to = available_to - already_in_cart
194
+ Rails.logger.debug("ASSIGNED SEATING available to this member #{available_to}")
195
+ end
196
+
197
+ if available_to > 0
198
+ [ Array.wrap(Ticket.available.where(:seat_id => seat.id).first), nil ]
199
+ else
200
+ [ [], "Sorry, we couldn't add any more tickets at this price level." ]
201
+ end
202
+ end
203
+
204
+ protected
205
+
206
+ def duplicate(options = {})
207
+ new_chart = super(options)
208
+
209
+ self.seats.each do |seat|
210
+ new_chart.seats << seat.dup!
211
+ end
212
+
213
+ if (!!options[:save])
214
+ new_chart.save
215
+ new_chart.attach_ticket_types_to_seats(self)
216
+ end
217
+
218
+ new_chart
219
+ end
220
+ end