effective_events 0.1.3 → 0.1.7
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 +4 -4
- data/README.md +26 -2
- data/app/controllers/admin/event_products_controller.rb +8 -0
- data/app/controllers/admin/event_purchases_controller.rb +11 -0
- data/app/controllers/effective/event_registrations_controller.rb +2 -8
- data/app/datatables/admin/effective_event_products_datatable.rb +50 -0
- data/app/datatables/admin/effective_event_purchases_datatable.rb +41 -0
- data/app/datatables/admin/effective_event_registrations_datatable.rb +2 -1
- data/app/datatables/admin/effective_event_tickets_datatable.rb +10 -1
- data/app/datatables/admin/effective_events_datatable.rb +7 -6
- data/app/datatables/effective_event_purchases_datatable.rb +38 -0
- data/app/datatables/effective_event_registrations_datatable.rb +3 -4
- data/app/helpers/effective_events_helper.rb +22 -3
- data/app/models/concerns/effective_events_event_registration.rb +37 -104
- data/app/models/effective/event.rb +8 -2
- data/app/models/effective/event_product.rb +67 -0
- data/app/models/effective/event_purchase.rb +71 -0
- data/app/models/effective/event_registrant.rb +1 -0
- data/app/models/effective/event_ticket.rb +18 -4
- data/app/views/admin/event_products/_form.html.haml +12 -0
- data/app/views/admin/event_purchases/_form.html.haml +14 -0
- data/app/views/admin/event_tickets/_form.html.haml +9 -2
- data/app/views/admin/events/_form.html.haml +21 -5
- data/app/views/effective/event_purchases/_fields.html.haml +10 -0
- data/app/views/effective/event_registrations/_purchases.html.haml +9 -0
- data/app/views/effective/event_registrations/_registrants.html.haml +8 -9
- data/app/views/effective/event_registrations/_summary.html.haml +22 -25
- data/app/views/effective/event_registrations/billing.html.haml +8 -7
- data/app/views/effective/event_registrations/purchases.html.haml +14 -0
- data/config/effective_events.rb +2 -0
- data/config/routes.rb +2 -0
- data/db/migrate/01_create_effective_events.rb.erb +46 -9
- data/lib/effective_events/version.rb +1 -1
- data/lib/effective_events.rb +2 -1
- data/lib/generators/effective_events/install_generator.rb +6 -1
- metadata +14 -3
- data/app/views/effective/event_tickets/_fields.html.haml +0 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 19f4a303dbab49f23b15a28c71bce29f9d55036371c533a27f36ad3ac70ca1b4
         | 
| 4 | 
            +
              data.tar.gz: ad51623c2087ccf9a1c2a2a97d1623f89224be38cd7aae06b246aedb2108e2e3
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 7d51690029093356830ee881f54881054b4eafa9b0aaf99d2389c9d8966a2d76b2d8456f11e9ef45ef7df92cddce73c89961094802c21a198a766b04373b0eb8
         | 
| 7 | 
            +
              data.tar.gz: 68e1785f75da39ad9916a065c89dc79a3995602c250315276e165b58f4abf43bc4ab116c45698e1ee36cccfa7b7fe2c364efefab73d382deb58bd623e8064325
         | 
    
        data/README.md
    CHANGED
    
    | @@ -68,10 +68,34 @@ All authorization checks are handled via the effective_resources gem found in th | |
| 68 68 | 
             
            The permissions you actually want to define are as follows (using CanCan):
         | 
| 69 69 |  | 
| 70 70 | 
             
            ```ruby
         | 
| 71 | 
            -
            can | 
| 71 | 
            +
            can([:index, :show], Effective::Event) { |event| !event.draft? }
         | 
| 72 | 
            +
            can([:new, :create], EffectiveEvents.EventRegistration)
         | 
| 73 | 
            +
            can([:show, :index], Effective::EventRegistrant) { |registrant| registrant.owner == user || registrant.owner.blank? }
         | 
| 74 | 
            +
            can([:show, :index], Effective::EventPurchase) { |purchase| purchase.owner == user || purchase.owner.blank? }
         | 
| 75 | 
            +
            can([:show, :index], EffectiveEvents.EventRegistration) { |registration| registration.owner == user }
         | 
| 76 | 
            +
            can([:update, :destroy], EffectiveEvents.EventRegistration) { |registration| registration.owner == user && !registration.was_submitted? }
         | 
| 72 77 |  | 
| 73 78 | 
             
            if user.admin?
         | 
| 74 | 
            -
              can : | 
| 79 | 
            +
              can :admin, :effective_events
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              can(crud - [:destroy], Effective::Event)
         | 
| 82 | 
            +
              can(:destroy, Effective::Event) { |et| et.event_registrants_count == 0 }
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              can(crud - [:destroy], Effective::EventRegistrant)
         | 
| 85 | 
            +
              can(:mark_paid, Effective::EventRegistrant) { |er| !er.event_registration_id.present? }
         | 
| 86 | 
            +
              can(:destroy, Effective::EventRegistrant) { |er| !er.purchased? }
         | 
| 87 | 
            +
             | 
| 88 | 
            +
              can(crud - [:destroy], Effective::EventPurchase)
         | 
| 89 | 
            +
              can(:mark_paid, Effective::EventPurchase) { |er| !er.event_registration_id.present? }
         | 
| 90 | 
            +
              can(:destroy, Effective::EventPurchase) { |er| !er.purchased? }
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              can(crud - [:destroy], Effective::EventTicket)
         | 
| 93 | 
            +
              can(:destroy, Effective::EventTicket) { |et| et.purchased_event_registrants_count == 0 }
         | 
| 94 | 
            +
             | 
| 95 | 
            +
              can(crud - [:destroy], Effective::EventProduct)
         | 
| 96 | 
            +
              can(:destroy, Effective::EventProduct) { |et| et.purchased_event_purchases_count == 0 }
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              can([:index, :show], EffectiveEvents.EventRegistration)
         | 
| 75 99 | 
             
            end
         | 
| 76 100 | 
             
            ```
         | 
| 77 101 |  | 
| @@ -0,0 +1,11 @@ | |
| 1 | 
            +
            module Admin
         | 
| 2 | 
            +
              class EventPurchasesController < ApplicationController
         | 
| 3 | 
            +
                before_action(:authenticate_user!) if defined?(Devise)
         | 
| 4 | 
            +
                before_action { EffectiveResources.authorize!(self, :admin, :effective_events) }
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                include Effective::CrudController
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                submit :mark_paid, 'Save and Mark Paid'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
            end
         | 
| @@ -6,7 +6,7 @@ module Effective | |
| 6 6 |  | 
| 7 7 | 
             
                resource_scope -> {
         | 
| 8 8 | 
             
                  event = Effective::Event.find(params[:event_id])
         | 
| 9 | 
            -
                  EffectiveEvents.EventRegistration.deep.where(owner:  | 
| 9 | 
            +
                  EffectiveEvents.EventRegistration.deep.where(owner: current_user, event: event)
         | 
| 10 10 | 
             
                }
         | 
| 11 11 |  | 
| 12 12 | 
             
                # Allow only 1 in-progress event registration at a time
         | 
| @@ -37,16 +37,10 @@ module Effective | |
| 37 37 |  | 
| 38 38 | 
             
                private
         | 
| 39 39 |  | 
| 40 | 
            -
                def current_owner
         | 
| 41 | 
            -
                  (current_user.class.respond_to?(:effective_memberships_owner?) ? current_user.effective_memberships_owners : current_user)
         | 
| 42 | 
            -
                end
         | 
| 43 | 
            -
             | 
| 44 40 | 
             
                def permitted_params
         | 
| 45 41 | 
             
                  model = (params.key?(:effective_event_registration) ? :effective_event_registration : :event_registration)
         | 
| 46 42 |  | 
| 47 | 
            -
                  params.require(model).permit!.except(
         | 
| 48 | 
            -
                    :status, :status_steps, :wizard_steps, :submitted_at
         | 
| 49 | 
            -
                  )
         | 
| 43 | 
            +
                  params.require(model).permit!.except(:status, :status_steps, :wizard_steps, :submitted_at)
         | 
| 50 44 | 
             
                end
         | 
| 51 45 |  | 
| 52 46 | 
             
              end
         | 
| @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            module Admin
         | 
| 2 | 
            +
              class EffectiveEventProductsDatatable < Effective::Datatable
         | 
| 3 | 
            +
                datatable do
         | 
| 4 | 
            +
                  reorder :position
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                  col :updated_at, visible: false
         | 
| 7 | 
            +
                  col :created_at, visible: false
         | 
| 8 | 
            +
                  col :id, visible: false
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  col :event
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  col :title
         | 
| 13 | 
            +
                  col :price, as: :price
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  col :archived
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  col :capacity_to_s, label: 'Capacity' do |ticket|
         | 
| 18 | 
            +
                    if ticket.capacity.present?
         | 
| 19 | 
            +
                      "#{ticket.capacity_available} remaining / #{ticket.capacity} total"
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  col :purchased_event_purchases_count, label: 'Purchased'
         | 
| 24 | 
            +
                  col :capacity, visible: false
         | 
| 25 | 
            +
                  col :capacity_available, visible: false
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  col :purchased_event_purchases, label: 'Purchased by' do |product|
         | 
| 28 | 
            +
                    product.purchased_event_purchases.sort_by(&:to_s).map do |purchase|
         | 
| 29 | 
            +
                      content_tag(:div, purchase.owner.to_s, class: 'col-resource_item')
         | 
| 30 | 
            +
                    end.join.html_safe
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  actions_col
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                collection do
         | 
| 37 | 
            +
                  scope = Effective::EventProduct.deep.all
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  if attributes[:event_id]
         | 
| 40 | 
            +
                    scope = scope.where(event: event)
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  scope
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def event
         | 
| 47 | 
            +
                  Effective::Event.find(attributes[:event_id])
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
            end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            module Admin
         | 
| 2 | 
            +
              class EffectiveEventPurchasesDatatable < Effective::Datatable
         | 
| 3 | 
            +
                datatable do
         | 
| 4 | 
            +
                  col :updated_at, visible: false
         | 
| 5 | 
            +
                  col :created_at, visible: false
         | 
| 6 | 
            +
                  col :id, visible: false
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  col :event
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  col :event_registration, visible: false
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  if attributes[:event_id]
         | 
| 13 | 
            +
                    col :event_product, search: Effective::EventProduct.where(event: event).all
         | 
| 14 | 
            +
                  else
         | 
| 15 | 
            +
                    col :event_product, search: :string
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  col :purchased_order
         | 
| 19 | 
            +
                  col :owner
         | 
| 20 | 
            +
                  col :notes, label: 'Notes'
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  actions_col
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                collection do
         | 
| 26 | 
            +
                  scope = Effective::EventPurchase.deep.purchased
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  if attributes[:event_id].present?
         | 
| 29 | 
            +
                    scope = scope.where(event: event)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  scope
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def event
         | 
| 36 | 
            +
                  @event ||= if attributes[:event_id]
         | 
| 37 | 
            +
                    Effective::Event.find(attributes[:event_id])
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -9,10 +9,11 @@ class Admin::EffectiveEventRegistrationsDatatable < Effective::Datatable | |
| 9 9 |  | 
| 10 10 | 
             
                col :submitted_at, label: 'Submitted', visible: false, as: :date
         | 
| 11 11 |  | 
| 12 | 
            -
                col :event
         | 
| 12 | 
            +
                col :event, search: :string
         | 
| 13 13 | 
             
                col :owner
         | 
| 14 14 |  | 
| 15 15 | 
             
                col :event_registrants, search: :string
         | 
| 16 | 
            +
                col :event_purchases, search: :string
         | 
| 16 17 | 
             
                col :orders, label: 'Order'
         | 
| 17 18 |  | 
| 18 19 | 
             
                actions_col
         | 
| @@ -13,8 +13,17 @@ module Admin | |
| 13 13 | 
             
                  col :regular_price, as: :price
         | 
| 14 14 | 
             
                  col :early_bird_price, as: :price
         | 
| 15 15 |  | 
| 16 | 
            -
                  col : | 
| 16 | 
            +
                  col :archived
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  col :capacity_to_s, label: 'Capacity' do |ticket|
         | 
| 19 | 
            +
                    if ticket.capacity.present?
         | 
| 20 | 
            +
                      "#{ticket.capacity_available} remaining / #{ticket.capacity} total"
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 17 24 | 
             
                  col :purchased_event_registrants_count, label: 'Registered'
         | 
| 25 | 
            +
                  col :capacity, visible: false
         | 
| 26 | 
            +
                  col :capacity_available, visible: false
         | 
| 18 27 |  | 
| 19 28 | 
             
                  col :purchased_event_registrants, label: 'Registrants' do |ticket|
         | 
| 20 29 | 
             
                    ticket.purchased_event_registrants.sort_by(&:last_name).map do |registrant|
         | 
| @@ -15,14 +15,13 @@ module Admin | |
| 15 15 |  | 
| 16 16 | 
             
                  col :title
         | 
| 17 17 | 
             
                  col :draft
         | 
| 18 | 
            -
                  col :start_at, label: 'Event Date'
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  col :end_at, visible: false
         | 
| 18 | 
            +
                  col :start_at, label: 'Event Start Date'
         | 
| 19 | 
            +
                  col :end_at, label: 'Event End Date', visible: false
         | 
| 21 20 | 
             
                  col :excerpt, visible: false
         | 
| 22 21 |  | 
| 23 | 
            -
                  col :registration_start_at, label: 'Registration opens'
         | 
| 24 | 
            -
                  col :registration_end_at, label: 'Registration closes'
         | 
| 25 | 
            -
                  col :early_bird_end_at, label: 'Early bird ends'
         | 
| 22 | 
            +
                  col :registration_start_at, label: 'Registration opens', visible: false
         | 
| 23 | 
            +
                  col :registration_end_at, label: 'Registration closes', visible: false
         | 
| 24 | 
            +
                  col :early_bird_end_at, label: 'Early bird ends', visible: false
         | 
| 26 25 |  | 
| 27 26 | 
             
                  col :early_bird do |event|
         | 
| 28 27 | 
             
                    if event.early_bird?
         | 
| @@ -33,7 +32,9 @@ module Admin | |
| 33 32 | 
             
                  end
         | 
| 34 33 |  | 
| 35 34 | 
             
                  col :event_tickets, search: :string
         | 
| 35 | 
            +
                  col :event_products, search: :string
         | 
| 36 36 | 
             
                  col :event_registrants, search: :string
         | 
| 37 | 
            +
                  col :event_purchases, search: :string
         | 
| 37 38 |  | 
| 38 39 | 
             
                  col :roles, visible: false
         | 
| 39 40 | 
             
                  col :authenticate_user, visible: false
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # Used on the Event Registrations purchases step
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class EffectiveEventPurchasesDatatable < Effective::Datatable
         | 
| 4 | 
            +
              datatable do
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                col :event_product, search: :string
         | 
| 7 | 
            +
                col :price, as: :price
         | 
| 8 | 
            +
                col :notes
         | 
| 9 | 
            +
                # no actions_col
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              collection do
         | 
| 13 | 
            +
                scope = Effective::EventPurchase.deep.all
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                if event.present?
         | 
| 16 | 
            +
                  scope = scope.where(event: event)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                if event_registration.present?
         | 
| 20 | 
            +
                  scope = scope.where(event_registration_id: event_registration)
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                scope
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def event
         | 
| 27 | 
            +
                @event ||= if attributes[:event_id]
         | 
| 28 | 
            +
                  Effective::Event.find(attributes[:event_id])
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def event_registration
         | 
| 33 | 
            +
                @event_registration ||= if attributes[:event_registration_id]
         | 
| 34 | 
            +
                  EffectiveEvents.EventRegistration.find_by_id(attributes[:event_registration_id])
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            end
         | 
| @@ -16,7 +16,8 @@ class EffectiveEventRegistrationsDatatable < Effective::Datatable | |
| 16 16 |  | 
| 17 17 | 
             
                col :owner, visible: false, search: :string
         | 
| 18 18 | 
             
                col :status, visible: false
         | 
| 19 | 
            -
                col :event_registrants, search: :string
         | 
| 19 | 
            +
                col :event_registrants, label: 'Registrants', search: :string
         | 
| 20 | 
            +
                col :event_purchases, label: 'Purchases', search: :string
         | 
| 20 21 | 
             
                col :orders, action: :show, visible: false, search: :string
         | 
| 21 22 |  | 
| 22 23 | 
             
                actions_col(actions: []) do |er|
         | 
| @@ -30,9 +31,7 @@ class EffectiveEventRegistrationsDatatable < Effective::Datatable | |
| 30 31 | 
             
              end
         | 
| 31 32 |  | 
| 32 33 | 
             
              collection do
         | 
| 33 | 
            -
                 | 
| 34 | 
            -
             | 
| 35 | 
            -
                EffectiveEvents.EventRegistration.deep.where(owner: owner)
         | 
| 34 | 
            +
                EffectiveEvents.EventRegistration.deep.where(owner: current_user)
         | 
| 36 35 | 
             
              end
         | 
| 37 36 |  | 
| 38 37 | 
             
            end
         | 
| @@ -3,11 +3,30 @@ module EffectiveEventsHelper | |
| 3 3 | 
             
              def effective_events_event_tickets_collection(event)
         | 
| 4 4 | 
             
                raise('expected an Effective::Event') unless event.kind_of?(Effective::Event)
         | 
| 5 5 |  | 
| 6 | 
            -
                event.event_tickets.map do |ticket|
         | 
| 7 | 
            -
                   | 
| 6 | 
            +
                event.event_tickets.reject(&:archived?).map do |ticket|
         | 
| 7 | 
            +
                  title = ticket.to_s
         | 
| 8 8 | 
             
                  price = (ticket.price == 0 ? '$0' : price_to_currency(ticket.price))
         | 
| 9 | 
            +
                  remaining = (ticket.capacity.present? ? "#{ticket.capacity_available} remaining" : nil)
         | 
| 9 10 |  | 
| 10 | 
            -
                   | 
| 11 | 
            +
                  label = [title, price, remaining].compact.join(' - ')
         | 
| 12 | 
            +
                  disabled = { disabled: :disabled } unless ticket.available?
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  [label, ticket.to_param, disabled].compact
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def effective_events_event_products_collection(event)
         | 
| 19 | 
            +
                raise('expected an Effective::Event') unless event.kind_of?(Effective::Event)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                event.event_products.reject(&:archived?).map do |product|
         | 
| 22 | 
            +
                  title = product.to_s
         | 
| 23 | 
            +
                  price = (product.price == 0 ? '$0' : price_to_currency(product.price))
         | 
| 24 | 
            +
                  remaining = (product.capacity.present? ? "#{product.capacity_available} remaining" : nil)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  label = [title, price, remaining].compact.join(' - ')
         | 
| 27 | 
            +
                  disabled = { disabled: :disabled } unless product.available?
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  [label, product.to_param, disabled].compact
         | 
| 11 30 | 
             
                end
         | 
| 12 31 | 
             
              end
         | 
| 13 32 |  | 
| @@ -37,12 +37,15 @@ module EffectiveEventsEventRegistration | |
| 37 37 | 
             
                acts_as_wizard(
         | 
| 38 38 | 
             
                  start: 'Start',
         | 
| 39 39 | 
             
                  registrants: 'Registrants',
         | 
| 40 | 
            +
                  purchases: 'Purchases',
         | 
| 40 41 | 
             
                  summary: 'Review',
         | 
| 41 42 | 
             
                  billing: 'Billing Address',
         | 
| 42 43 | 
             
                  checkout: 'Checkout',
         | 
| 43 44 | 
             
                  submitted: 'Submitted'
         | 
| 44 45 | 
             
                )
         | 
| 45 46 |  | 
| 47 | 
            +
                acts_as_purchasable_wizard
         | 
| 48 | 
            +
             | 
| 46 49 | 
             
                log_changes(except: :wizard_steps) if respond_to?(:log_changes)
         | 
| 47 50 |  | 
| 48 51 | 
             
                # Application Namespace
         | 
| @@ -50,11 +53,14 @@ module EffectiveEventsEventRegistration | |
| 50 53 | 
             
                accepts_nested_attributes_for :owner
         | 
| 51 54 |  | 
| 52 55 | 
             
                # Effective Namespace
         | 
| 53 | 
            -
                belongs_to :event
         | 
| 56 | 
            +
                belongs_to :event, class_name: 'Effective::Event'
         | 
| 54 57 |  | 
| 55 | 
            -
                has_many :event_registrants, -> { order(:id) }, inverse_of: :event_registration, dependent: :destroy
         | 
| 58 | 
            +
                has_many :event_registrants, -> { order(:id) }, class_name: 'Effective::EventRegistrant', inverse_of: :event_registration, dependent: :destroy
         | 
| 56 59 | 
             
                accepts_nested_attributes_for :event_registrants, reject_if: :all_blank, allow_destroy: true
         | 
| 57 60 |  | 
| 61 | 
            +
                has_many :event_purchases, -> { order(:id) }, class_name: 'Effective::EventPurchase', inverse_of: :event_registration, dependent: :destroy
         | 
| 62 | 
            +
                accepts_nested_attributes_for :event_purchases, reject_if: :all_blank, allow_destroy: true
         | 
| 63 | 
            +
             | 
| 58 64 | 
             
                has_many :orders, -> { order(:id) }, as: :parent, class_name: 'Effective::Order', dependent: :nullify
         | 
| 59 65 | 
             
                accepts_nested_attributes_for :orders
         | 
| 60 66 |  | 
| @@ -78,10 +84,7 @@ module EffectiveEventsEventRegistration | |
| 78 84 | 
             
                scope :in_progress, -> { where.not(status: [:submitted]) }
         | 
| 79 85 | 
             
                scope :done, -> { where(status: [:submitted]) }
         | 
| 80 86 |  | 
| 81 | 
            -
                scope :for, -> (user) {
         | 
| 82 | 
            -
                  owner = (user.respond_to?(:effective_memberships_owners) ? user.effective_memberships_owners : user)
         | 
| 83 | 
            -
                  where(owner: owner)
         | 
| 84 | 
            -
                }
         | 
| 87 | 
            +
                scope :for, -> (user) { where(owner: user) }
         | 
| 85 88 |  | 
| 86 89 | 
             
                # All Steps validations
         | 
| 87 90 | 
             
                validates :owner, presence: true
         | 
| @@ -92,17 +95,29 @@ module EffectiveEventsEventRegistration | |
| 92 95 | 
             
                  self.errors.add(:event_registrants, "can't be blank") unless present_event_registrants.present?
         | 
| 93 96 | 
             
                end
         | 
| 94 97 |  | 
| 95 | 
            -
                #  | 
| 96 | 
            -
                validate( | 
| 97 | 
            -
                   | 
| 98 | 
            -
             | 
| 98 | 
            +
                # Validate all items are available
         | 
| 99 | 
            +
                validate(unless: -> { current_step == :checkout || done? }) do
         | 
| 100 | 
            +
                  event_registrants.reject { |er| er.purchased? || er.event_ticket&.available? }.each do |item|
         | 
| 101 | 
            +
                    errors.add(:base, "The #{item.event_ticket} ticket is sold out and no longer available for purchase")
         | 
| 102 | 
            +
                    item.errors.add(:event_ticket_id, "#{item.event_ticket} is unavailable for purchase")
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  event_purchases.reject { |ep| ep.purchased? || ep.event_product&.available? }.each do |item|
         | 
| 106 | 
            +
                    errors.add(:base, "The #{item.event_product} product is sold out and no longer available for purchase")
         | 
| 107 | 
            +
                    item.errors.add(:event_product_id, "#{item.event_product} is unavailable for purchase")
         | 
| 108 | 
            +
                  end
         | 
| 99 109 | 
             
                end
         | 
| 100 110 |  | 
| 101 | 
            -
                 | 
| 102 | 
            -
                   | 
| 103 | 
            -
                   | 
| 104 | 
            -
                  after_submit_purchased!
         | 
| 111 | 
            +
                def required_steps
         | 
| 112 | 
            +
                  return self.class.test_required_steps if Rails.env.test? && self.class.test_required_steps.present?
         | 
| 113 | 
            +
                  event&.event_products.present? ? wizard_step_keys : (wizard_step_keys - [:purchases])
         | 
| 105 114 | 
             
                end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                # All Fees and Orders
         | 
| 117 | 
            +
                def submit_fees
         | 
| 118 | 
            +
                  (event_registrants + event_purchases)
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
             | 
| 106 121 | 
             
              end
         | 
| 107 122 |  | 
| 108 123 | 
             
              # Instance Methods
         | 
| @@ -118,14 +133,16 @@ module EffectiveEventsEventRegistration | |
| 118 133 | 
             
                submitted?
         | 
| 119 134 | 
             
              end
         | 
| 120 135 |  | 
| 121 | 
            -
               | 
| 122 | 
            -
             | 
| 136 | 
            +
              # Find or build
         | 
| 137 | 
            +
              def event_registrant(event_ticket:, first_name:, last_name:, email:)
         | 
| 138 | 
            +
                registrant = event_registrants.find { |er| er.event_ticket == event_ticket && er.first_name == first_name && er.last_name == last_name && er.email == email }
         | 
| 139 | 
            +
                registrant || event_registrants.build(event: event, event_ticket: event_ticket, owner: owner, first_name: first_name, last_name: last_name, email: email)
         | 
| 123 140 | 
             
              end
         | 
| 124 141 |  | 
| 125 | 
            -
              # Find or build
         | 
| 126 | 
            -
              def  | 
| 127 | 
            -
                 | 
| 128 | 
            -
                 | 
| 142 | 
            +
              # Find or build. But it's not gonna work with more than 1. This is for testing only really.
         | 
| 143 | 
            +
              def event_purchase(event_product:)
         | 
| 144 | 
            +
                purchase = event_purchases.find { |ep| ep.event_product == event_product }
         | 
| 145 | 
            +
                purchase || event_purchases.build(event_product: event_product, owner: owner)
         | 
| 129 146 | 
             
              end
         | 
| 130 147 |  | 
| 131 148 | 
             
              # This builds the default event registrants used by the wizard form
         | 
| @@ -142,90 +159,6 @@ module EffectiveEventsEventRegistration | |
| 142 159 | 
             
                event_registrants
         | 
| 143 160 | 
             
              end
         | 
| 144 161 |  | 
| 145 | 
            -
              # All Fees and Orders
         | 
| 146 | 
            -
              def submit_fees
         | 
| 147 | 
            -
                event_registrants
         | 
| 148 | 
            -
              end
         | 
| 149 | 
            -
             | 
| 150 | 
            -
              def submit_order
         | 
| 151 | 
            -
                orders.first
         | 
| 152 | 
            -
              end
         | 
| 153 | 
            -
             | 
| 154 | 
            -
              def find_or_build_submit_order
         | 
| 155 | 
            -
                order = submit_order || orders.build(user: owner)
         | 
| 156 | 
            -
                fees = submit_fees()
         | 
| 157 | 
            -
             | 
| 158 | 
            -
                # Adds fees, but does not overwrite any existing price.
         | 
| 159 | 
            -
                fees.each do |fee|
         | 
| 160 | 
            -
                  order.add(fee) unless order.purchasables.include?(fee)
         | 
| 161 | 
            -
                end
         | 
| 162 | 
            -
             | 
| 163 | 
            -
                order.purchasables.each do |purchasable|
         | 
| 164 | 
            -
                  order.remove(purchasable) unless fees.include?(purchasable)
         | 
| 165 | 
            -
                end
         | 
| 166 | 
            -
             | 
| 167 | 
            -
                # From Billing Step
         | 
| 168 | 
            -
                order.billing_address = owner.billing_address if owner.billing_address.present?
         | 
| 169 | 
            -
             | 
| 170 | 
            -
                # Important to add/remove anything
         | 
| 171 | 
            -
                order.save
         | 
| 172 | 
            -
             | 
| 173 | 
            -
                order
         | 
| 174 | 
            -
              end
         | 
| 175 | 
            -
             | 
| 176 | 
            -
              # Should be indempotent.
         | 
| 177 | 
            -
              def build_submit_fees_and_order
         | 
| 178 | 
            -
                return false if was_submitted?
         | 
| 179 | 
            -
             | 
| 180 | 
            -
                fees = submit_fees()
         | 
| 181 | 
            -
                raise('already has purchased submit fees') if fees.any?(&:purchased?)
         | 
| 182 | 
            -
             | 
| 183 | 
            -
                order = find_or_build_submit_order()
         | 
| 184 | 
            -
                raise('already has purchased submit order') if order.purchased?
         | 
| 185 | 
            -
             | 
| 186 | 
            -
                true
         | 
| 187 | 
            -
              end
         | 
| 188 | 
            -
             | 
| 189 | 
            -
              # If they go back and change registrants. Update the order right away.
         | 
| 190 | 
            -
              def registrants!
         | 
| 191 | 
            -
                save!
         | 
| 192 | 
            -
                build_submit_fees_and_order if submit_order.present?
         | 
| 193 | 
            -
                true
         | 
| 194 | 
            -
              end
         | 
| 195 | 
            -
             | 
| 196 | 
            -
              # Owner clicks on the Billing step. Next step is Checkout
         | 
| 197 | 
            -
              def billing!
         | 
| 198 | 
            -
                ready!
         | 
| 199 | 
            -
              end
         | 
| 200 | 
            -
             | 
| 201 | 
            -
              # Ready to check out
         | 
| 202 | 
            -
              def ready!
         | 
| 203 | 
            -
                build_submit_fees_and_order
         | 
| 204 | 
            -
                save!
         | 
| 205 | 
            -
              end
         | 
| 206 | 
            -
             | 
| 207 | 
            -
              # Called automatically via after_purchase hook above
         | 
| 208 | 
            -
              def submit_purchased!
         | 
| 209 | 
            -
                return false if was_submitted?
         | 
| 210 | 
            -
             | 
| 211 | 
            -
                wizard_steps[:checkout] = Time.zone.now
         | 
| 212 | 
            -
                submit!
         | 
| 213 | 
            -
              end
         | 
| 214 | 
            -
             | 
| 215 | 
            -
              # A hook to extend
         | 
| 216 | 
            -
              def after_submit_purchased!
         | 
| 217 | 
            -
              end
         | 
| 218 | 
            -
             | 
| 219 | 
            -
              # Draft -> Submitted requirements
         | 
| 220 | 
            -
              def submit!
         | 
| 221 | 
            -
                raise('already submitted') if was_submitted?
         | 
| 222 | 
            -
                raise('expected a purchased order') unless submit_order&.purchased?
         | 
| 223 | 
            -
             | 
| 224 | 
            -
                wizard_steps[:checkout] ||= Time.zone.now
         | 
| 225 | 
            -
                wizard_steps[:submitted] = Time.zone.now
         | 
| 226 | 
            -
                submitted!
         | 
| 227 | 
            -
              end
         | 
| 228 | 
            -
             | 
| 229 162 | 
             
              private
         | 
| 230 163 |  | 
| 231 164 | 
             
              def present_event_registrants
         | 
| @@ -2,11 +2,17 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module Effective
         | 
| 4 4 | 
             
              class Event < ActiveRecord::Base
         | 
| 5 | 
            +
                has_many :event_tickets, -> { EventTicket.sorted }, inverse_of: :event
         | 
| 6 | 
            +
                accepts_nested_attributes_for :event_tickets, allow_destroy: true
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                has_many :event_products, -> { EventProduct.sorted }, inverse_of: :event
         | 
| 9 | 
            +
                accepts_nested_attributes_for :event_products, allow_destroy: true
         | 
| 10 | 
            +
             | 
| 5 11 | 
             
                has_many :event_registrants, -> { order(:event_ticket_id, :created_at) }, inverse_of: :event
         | 
| 6 12 | 
             
                accepts_nested_attributes_for :event_registrants, allow_destroy: true
         | 
| 7 13 |  | 
| 8 | 
            -
                has_many : | 
| 9 | 
            -
                accepts_nested_attributes_for : | 
| 14 | 
            +
                has_many :event_purchases, -> { order(:event_product_id, :created_at) }, inverse_of: :event
         | 
| 15 | 
            +
                accepts_nested_attributes_for :event_purchases, allow_destroy: true
         | 
| 10 16 |  | 
| 11 17 | 
             
                # rich_text_body - Used by the select step
         | 
| 12 18 | 
             
                has_many_rich_texts
         | 
| @@ -0,0 +1,67 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Effective
         | 
| 4 | 
            +
              class EventProduct < ActiveRecord::Base
         | 
| 5 | 
            +
                belongs_to :event
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                has_many :event_purchases
         | 
| 8 | 
            +
                has_many :purchased_event_purchases, -> { EventPurchase.purchased }, class_name: 'Effective::EventPurchase'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                log_changes(to: :event) if respond_to?(:log_changes)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                has_rich_text :body
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                effective_resource do
         | 
| 15 | 
            +
                  title                 :string
         | 
| 16 | 
            +
                  capacity              :integer
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  # Pricing
         | 
| 19 | 
            +
                  price                 :integer
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  qb_item_name          :string
         | 
| 22 | 
            +
                  tax_exempt            :boolean
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  position              :integer
         | 
| 25 | 
            +
                  archived              :boolean
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  timestamps
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                scope :sorted, -> { order(:position) }
         | 
| 31 | 
            +
                scope :deep, -> { with_rich_text_body.includes(:purchased_event_purchases) }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                scope :archived, -> { where(archived: true) }
         | 
| 34 | 
            +
                scope :unarchived, -> { where(archived: false) }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                before_validation(if: -> { event.present? }) do
         | 
| 37 | 
            +
                  self.position ||= (event.event_products.map(&:position).compact.max || -1) + 1
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                validates :title, presence: true, uniqueness: { scope: [:event_id] }
         | 
| 41 | 
            +
                validates :price, presence: true
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def to_s
         | 
| 44 | 
            +
                  title.presence || 'New Event Product'
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                # Available for purchase
         | 
| 48 | 
            +
                def available?
         | 
| 49 | 
            +
                  return false if archived?
         | 
| 50 | 
            +
                  capacity_available?
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def capacity_available?
         | 
| 54 | 
            +
                  capacity.blank? || (capacity_available > 0)
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def capacity_available
         | 
| 58 | 
            +
                  return nil if capacity.blank?
         | 
| 59 | 
            +
                  [(capacity - purchased_event_purchases_count), 0].max
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def purchased_event_purchases_count
         | 
| 63 | 
            +
                  purchased_event_purchases.length
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
            end
         | 
| @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Just like each EventRegistration has EventTickets and EventRegistrants
         | 
| 4 | 
            +
            # An Event Registration has EventProducts and EventPurchases
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Effective
         | 
| 7 | 
            +
              class EventPurchase < ActiveRecord::Base
         | 
| 8 | 
            +
                acts_as_purchasable
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                log_changes(to: :event) if respond_to?(:log_changes)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                belongs_to :event, counter_cache: true
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                # Basically a category containing all the pricing and unique info about this product purchase
         | 
| 15 | 
            +
                belongs_to :event_product
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                # Every event registrant is charged to a owner
         | 
| 18 | 
            +
                belongs_to :owner, polymorphic: true
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                # This fee when checked out through the event registration
         | 
| 21 | 
            +
                belongs_to :event_registration, polymorphic: true, optional: true
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                effective_resource do
         | 
| 24 | 
            +
                  notes             :text
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  # Acts as Purchasable
         | 
| 27 | 
            +
                  price             :integer
         | 
| 28 | 
            +
                  qb_item_name      :string
         | 
| 29 | 
            +
                  tax_exempt        :boolean
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  timestamps
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                scope :sorted, -> { order(:id) }
         | 
| 35 | 
            +
                scope :deep, -> { all }
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                before_validation(if: -> { event_registration.present? }) do
         | 
| 38 | 
            +
                  self.event ||= event_registration.event
         | 
| 39 | 
            +
                  self.owner ||= event_registration.owner
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                before_validation(if: -> { event_product.present? }) do
         | 
| 43 | 
            +
                  self.price ||= event_product.price
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def to_s
         | 
| 47 | 
            +
                  persisted? ? event_product.to_s : 'product'
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def tax_exempt
         | 
| 51 | 
            +
                  event_product.tax_exempt
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def qb_item_name
         | 
| 55 | 
            +
                  event_product.qb_item_name
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                # This is the Admin Save and Mark Paid action
         | 
| 59 | 
            +
                def mark_paid!
         | 
| 60 | 
            +
                  raise('expected a blank event registration') if event_registration.present?
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  save!
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  order = Effective::Order.new(items: self, user: owner)
         | 
| 65 | 
            +
                  order.purchase!(skip_buyer_validations: true, email: false)
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  true
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
            end
         | 
| @@ -23,6 +23,7 @@ module Effective | |
| 23 23 | 
             
                  tax_exempt            :boolean
         | 
| 24 24 |  | 
| 25 25 | 
             
                  position              :integer
         | 
| 26 | 
            +
                  archived              :boolean
         | 
| 26 27 |  | 
| 27 28 | 
             
                  timestamps
         | 
| 28 29 | 
             
                end
         | 
| @@ -30,11 +31,14 @@ module Effective | |
| 30 31 | 
             
                scope :sorted, -> { order(:position) }
         | 
| 31 32 | 
             
                scope :deep, -> { with_rich_text_body.includes(:purchased_event_registrants) }
         | 
| 32 33 |  | 
| 34 | 
            +
                scope :archived, -> { where(archived: true) }
         | 
| 35 | 
            +
                scope :unarchived, -> { where(archived: false) }
         | 
| 36 | 
            +
             | 
| 33 37 | 
             
                before_validation(if: -> { event.present? }) do
         | 
| 34 38 | 
             
                  self.position ||= (event.event_tickets.map(&:position).compact.max || -1) + 1
         | 
| 35 39 | 
             
                end
         | 
| 36 40 |  | 
| 37 | 
            -
                validates :title, presence: true
         | 
| 41 | 
            +
                validates :title, presence: true, uniqueness: { scope: [:event_id] }
         | 
| 38 42 | 
             
                validates :regular_price, presence: true
         | 
| 39 43 | 
             
                validates :early_bird_price, presence: true, if: -> { event&.early_bird_end_at.present? }
         | 
| 40 44 |  | 
| @@ -46,13 +50,23 @@ module Effective | |
| 46 50 | 
             
                  event.early_bird? ? early_bird_price : regular_price
         | 
| 47 51 | 
             
                end
         | 
| 48 52 |  | 
| 53 | 
            +
                # Available for purchase
         | 
| 54 | 
            +
                def available?
         | 
| 55 | 
            +
                  return false if archived?
         | 
| 56 | 
            +
                  capacity_available?
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 49 59 | 
             
                def capacity_available?
         | 
| 50 | 
            -
                   | 
| 51 | 
            -
             | 
| 60 | 
            +
                  capacity.blank? || (capacity_available > 0)
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                def capacity_available
         | 
| 64 | 
            +
                  return nil if capacity.blank?
         | 
| 65 | 
            +
                  [(capacity - purchased_event_registrants_count), 0].max
         | 
| 52 66 | 
             
                end
         | 
| 53 67 |  | 
| 54 68 | 
             
                def purchased_event_registrants_count
         | 
| 55 | 
            -
                  purchased_event_registrants. | 
| 69 | 
            +
                  purchased_event_registrants.length
         | 
| 56 70 | 
             
                end
         | 
| 57 71 |  | 
| 58 72 | 
             
              end
         | 
| @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            = effective_form_with(model: [:admin, event_product], engine: true) do |f|
         | 
| 2 | 
            +
              = f.hidden_field :event_id
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              = f.text_field :title
         | 
| 5 | 
            +
              = f.number_field :capacity, hint: 'The number of online purchases will be limited to capacity.'
         | 
| 6 | 
            +
              = f.check_box :archived, label: 'Yes, archive this product and make it unavailable for purchase'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              = f.price_field :price
         | 
| 9 | 
            +
              = f.text_field :qb_item_name, label: 'Quickbooks item name'
         | 
| 10 | 
            +
              = f.check_box :tax_exempt
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              = effective_submit(f)
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            = effective_form_with(model: [:admin, event_purchase], engine: true) do |f|
         | 
| 2 | 
            +
              = f.hidden_field :event_id
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              - if f.object.new_record?
         | 
| 5 | 
            +
                = f.select :owner, { 'Users' => current_user.class.all }, polymorphic: true
         | 
| 6 | 
            +
              - else
         | 
| 7 | 
            +
                = f.static_field :owner
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              = render 'effective/event_purchases/fields', f: f, event: event_purchase.event
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              - if f.object.new_record?
         | 
| 12 | 
            +
                = f.submit 'Save and Mark Paid'
         | 
| 13 | 
            +
              - else
         | 
| 14 | 
            +
                = f.submit 'Save'
         | 
| @@ -1,7 +1,14 @@ | |
| 1 1 | 
             
            = effective_form_with(model: [:admin, event_ticket], engine: true) do |f|
         | 
| 2 2 | 
             
              = f.hidden_field :event_id
         | 
| 3 3 |  | 
| 4 | 
            -
               | 
| 5 | 
            -
              =  | 
| 4 | 
            +
              = f.text_field :title
         | 
| 5 | 
            +
              = f.number_field :capacity, hint: 'The number of online purchases will be limited to capacity.'
         | 
| 6 | 
            +
              = f.check_box :archived, label: 'Yes, archive this ticket and make it unavailable for purchase'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              = f.price_field :regular_price
         | 
| 9 | 
            +
              = f.price_field :early_bird_price
         | 
| 10 | 
            +
              = f.text_field :qb_item_name, label: 'Quickbooks item name'
         | 
| 11 | 
            +
              = f.check_box :tax_exempt
         | 
| 12 | 
            +
             | 
| 6 13 |  | 
| 7 14 | 
             
              = effective_submit(f)
         | 
| @@ -3,20 +3,36 @@ | |
| 3 3 | 
             
                = render 'admin/events/form_event', event: event
         | 
| 4 4 |  | 
| 5 5 | 
             
              - if event.persisted?
         | 
| 6 | 
            -
                = tab 'Registrants' do
         | 
| 7 | 
            -
                  - datatable = Admin::EffectiveEventRegistrantsDatatable.new(event_id: event.id)
         | 
| 8 | 
            -
                  = render_inline_datatable(datatable)
         | 
| 9 | 
            -
             | 
| 10 6 | 
             
                = tab 'Content' do
         | 
| 11 7 | 
             
                  = render '/admin/events/form_content', event: event
         | 
| 12 8 |  | 
| 13 9 | 
             
                = tab 'Tickets' do
         | 
| 14 10 | 
             
                  %p An event must have tickets before registration can begin
         | 
| 15 11 |  | 
| 12 | 
            +
                  %h2 Tickets
         | 
| 16 13 | 
             
                  - datatable = Admin::EffectiveEventTicketsDatatable.new(event_id: event.id)
         | 
| 17 14 | 
             
                  = render_inline_datatable(datatable)
         | 
| 18 15 |  | 
| 19 | 
            -
                = tab ' | 
| 16 | 
            +
                = tab 'Products' do
         | 
| 17 | 
            +
                  %h2 Products
         | 
| 18 | 
            +
                  - datatable = Admin::EffectiveEventProductsDatatable.new(event_id: event.id)
         | 
| 19 | 
            +
                  = render_inline_datatable(datatable)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                = tab 'Registrations' do
         | 
| 22 | 
            +
                  %h2 Registrations
         | 
| 23 | 
            +
                  - datatable = Admin::EffectiveEventRegistrationsDatatable.new(event_id: event.id)
         | 
| 24 | 
            +
                  .mb-4= render_inline_datatable(datatable)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                = tab 'Registrants' do
         | 
| 27 | 
            +
                  %h2 Registrants
         | 
| 28 | 
            +
                  - datatable = Admin::EffectiveEventRegistrantsDatatable.new(event_id: event.id)
         | 
| 29 | 
            +
                  .mb-4= render_inline_datatable(datatable)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  %h2 Purchases
         | 
| 32 | 
            +
                  - datatable = Admin::EffectiveEventPurchasesDatatable.new(event_id: event.id)
         | 
| 33 | 
            +
                  = render_inline_datatable(datatable)
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                = tab 'Wizard' do
         | 
| 20 36 | 
             
                  = render '/admin/events/form_event_registration_content', event: event
         | 
| 21 37 |  | 
| 22 38 | 
             
                = tab 'Access' do
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            .card
         | 
| 2 | 
            +
              .card-body
         | 
| 3 | 
            +
                %h5.card-title Event Purchase
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                - if f.object.purchased?
         | 
| 6 | 
            +
                  = f.static_field :event_product, label: 'Purchased event product'
         | 
| 7 | 
            +
                - else
         | 
| 8 | 
            +
                  = f.select :event_product_id, effective_events_event_products_collection(event)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                = f.text_area :notes, label: 'Notes'
         | 
| @@ -0,0 +1,9 @@ | |
| 1 | 
            +
            = card do
         | 
| 2 | 
            +
              .row
         | 
| 3 | 
            +
                .col-sm
         | 
| 4 | 
            +
                  %h5.card-title= event_registration.wizard_step_title(:purchases)
         | 
| 5 | 
            +
                .col-sm-auto.text-right
         | 
| 6 | 
            +
                  = link_to('Edit', wizard_path(:purchases)) if edit_effective_event_registrations_wizard?
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              - datatable = EffectiveEventPurchasesDatatable.new(event_registration: event_registration)
         | 
| 9 | 
            +
              .mb-4= render_simple_datatable(datatable)
         | 
| @@ -1,10 +1,9 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
              . | 
| 3 | 
            -
                . | 
| 4 | 
            -
                  . | 
| 5 | 
            -
             | 
| 6 | 
            -
                   | 
| 7 | 
            -
                    = link_to('Edit', wizard_path(:registrants)) if edit_effective_event_registrations_wizard?
         | 
| 1 | 
            +
            = card do
         | 
| 2 | 
            +
              .row
         | 
| 3 | 
            +
                .col-sm
         | 
| 4 | 
            +
                  %h5.card-title= event_registration.wizard_step_title(:registrants)
         | 
| 5 | 
            +
                .col-sm-auto.text-right
         | 
| 6 | 
            +
                  = link_to('Edit', wizard_path(:registrants)) if edit_effective_event_registrations_wizard?
         | 
| 8 7 |  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 8 | 
            +
              - datatable = EffectiveEventRegistrantsDatatable.new(event_registration: event_registration)
         | 
| 9 | 
            +
              .mb-4= render_simple_datatable(datatable)
         | 
| @@ -1,29 +1,26 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
              . | 
| 3 | 
            -
                % | 
| 1 | 
            +
            = card('Event Registration') do
         | 
| 2 | 
            +
              %table.table.table-sm
         | 
| 3 | 
            +
                %tbody
         | 
| 4 | 
            +
                  %tr
         | 
| 5 | 
            +
                    %th.border-0 Event
         | 
| 6 | 
            +
                    %td.border-0
         | 
| 7 | 
            +
                      = link_to(event_registration.event, effective_events.event_path(event_registration.event))
         | 
| 4 8 |  | 
| 5 | 
            -
             | 
| 6 | 
            -
                  %tbody
         | 
| 9 | 
            +
                  - if request.path.start_with?('/admin')
         | 
| 7 10 | 
             
                    %tr
         | 
| 8 | 
            -
                      %th | 
| 9 | 
            -
                      %td | 
| 10 | 
            -
                        =  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
                          - url = (polymorphic_admin_path(event_registration.owner) rescue "/admin/users/#{event_registration.owner.to_param}/edit")
         | 
| 17 | 
            -
                          = link_to(event_registration.owner, url)
         | 
| 18 | 
            -
                    - else
         | 
| 19 | 
            -
                      %tr
         | 
| 20 | 
            -
                        %th Registered by
         | 
| 21 | 
            -
                        %td= event_registration.owner
         | 
| 11 | 
            +
                      %th Registered by
         | 
| 12 | 
            +
                      %td
         | 
| 13 | 
            +
                        - url = (polymorphic_admin_path(event_registration.owner) rescue "/admin/users/#{event_registration.owner.to_param}/edit")
         | 
| 14 | 
            +
                        = link_to(event_registration.owner, url)
         | 
| 15 | 
            +
                  - else
         | 
| 16 | 
            +
                    %tr
         | 
| 17 | 
            +
                      %th Registered by
         | 
| 18 | 
            +
                      %td= event_registration.owner
         | 
| 22 19 |  | 
| 23 20 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 21 | 
            +
                  - if event_registration.orders.present?
         | 
| 22 | 
            +
                    %tr
         | 
| 23 | 
            +
                      %th Order
         | 
| 24 | 
            +
                      %td
         | 
| 25 | 
            +
                        - event_registration.orders.each do |order|
         | 
| 26 | 
            +
                          = link_to(order, effective_orders.order_path(order))
         | 
| @@ -3,12 +3,13 @@ | |
| 3 3 |  | 
| 4 4 | 
             
              - raise('expected owner to respond to billing_address') unless resource.owner.respond_to?(:billing_address)
         | 
| 5 5 |  | 
| 6 | 
            -
               | 
| 7 | 
            -
                 | 
| 8 | 
            -
                  = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
         | 
| 9 | 
            -
                    = f.hidden_field :id
         | 
| 6 | 
            +
              = card('Billing Address') do
         | 
| 7 | 
            +
                %p Please enter your billing address
         | 
| 10 8 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 9 | 
            +
                = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
         | 
| 10 | 
            +
                  = f.hidden_field :id
         | 
| 13 11 |  | 
| 14 | 
            -
             | 
| 12 | 
            +
                  = f.fields_for(:owner, f.object.owner) do |fu|
         | 
| 13 | 
            +
                    = effective_address_fields(fu, :billing)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  = f.save 'Save and Continue'
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            = render 'layout' do
         | 
| 2 | 
            +
              = render 'effective/event_registrations/content', resource: resource
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              .card
         | 
| 5 | 
            +
                .card-body
         | 
| 6 | 
            +
                  %p Please add one or more products.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
         | 
| 9 | 
            +
                    = f.hidden_field :id
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    = f.has_many :event_purchases do |fp|
         | 
| 12 | 
            +
                      = render('effective/event_purchases/fields', f: fp, event: f.object.event)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    = f.save 'Save and Continue'
         | 
    
        data/config/effective_events.rb
    CHANGED
    
    | @@ -1,7 +1,9 @@ | |
| 1 1 | 
             
            EffectiveEvents.setup do |config|
         | 
| 2 2 | 
             
              config.events_table_name = :events
         | 
| 3 3 | 
             
              config.event_tickets_table_name = :event_tickets
         | 
| 4 | 
            +
              config.event_products_table_name = :event_products
         | 
| 4 5 | 
             
              config.event_registrants_table_name = :event_registrants
         | 
| 6 | 
            +
              config.event_purchases_table_name = :event_purchases
         | 
| 5 7 | 
             
              config.event_registrations_table_name = :event_registrations
         | 
| 6 8 |  | 
| 7 9 | 
             
              # Layout Settings
         | 
    
        data/config/routes.rb
    CHANGED
    
    | @@ -17,7 +17,9 @@ EffectiveEvents::Engine.routes.draw do | |
| 17 17 | 
             
              namespace :admin do
         | 
| 18 18 | 
             
                resources :events, except: [:show]
         | 
| 19 19 | 
             
                resources :event_tickets, except: [:show]
         | 
| 20 | 
            +
                resources :event_products, except: [:show]
         | 
| 20 21 | 
             
                resources :event_registrants, except: [:show]
         | 
| 22 | 
            +
                resources :event_purchases, except: [:show]
         | 
| 21 23 | 
             
                resources :event_registrations, only: [:index, :show]
         | 
| 22 24 | 
             
              end
         | 
| 23 25 |  | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            class CreateEffectiveEvents < ActiveRecord::Migration[6.0]
         | 
| 2 2 | 
             
              def change
         | 
| 3 | 
            -
                create_table  | 
| 3 | 
            +
                create_table <%= @events_table_name %> do |t|
         | 
| 4 4 | 
             
                  t.string :title
         | 
| 5 5 |  | 
| 6 6 | 
             
                  t.string :slug
         | 
| @@ -14,6 +14,7 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0] | |
| 14 14 | 
             
                  t.datetime :early_bird_end_at
         | 
| 15 15 |  | 
| 16 16 | 
             
                  t.integer :event_registrants_count, default: 0
         | 
| 17 | 
            +
                  t.integer :event_purchases_count, default: 0
         | 
| 17 18 |  | 
| 18 19 | 
             
                  t.integer :roles_mask
         | 
| 19 20 | 
             
                  t.boolean :authenticate_user, default: false
         | 
| @@ -21,10 +22,10 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0] | |
| 21 22 | 
             
                  t.timestamps
         | 
| 22 23 | 
             
                end
         | 
| 23 24 |  | 
| 24 | 
            -
                add_index  | 
| 25 | 
            -
                add_index  | 
| 25 | 
            +
                add_index <%= @events_table_name %>, :title
         | 
| 26 | 
            +
                add_index <%= @events_table_name %>, :end_at
         | 
| 26 27 |  | 
| 27 | 
            -
                create_table  | 
| 28 | 
            +
                create_table <%= @event_tickets_table_name %> do |t|
         | 
| 28 29 | 
             
                  t.integer :event_id
         | 
| 29 30 |  | 
| 30 31 | 
             
                  t.string :title
         | 
| @@ -37,11 +38,12 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0] | |
| 37 38 | 
             
                  t.boolean :tax_exempt, default: false
         | 
| 38 39 |  | 
| 39 40 | 
             
                  t.integer :position
         | 
| 41 | 
            +
                  t.boolean :archived, default: false
         | 
| 40 42 |  | 
| 41 43 | 
             
                  t.timestamps
         | 
| 42 44 | 
             
                end
         | 
| 43 45 |  | 
| 44 | 
            -
                create_table  | 
| 46 | 
            +
                create_table <%= @event_registrants_table_name %> do |t|
         | 
| 45 47 | 
             
                  t.integer :event_id
         | 
| 46 48 | 
             
                  t.integer :event_ticket_id
         | 
| 47 49 |  | 
| @@ -65,7 +67,42 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0] | |
| 65 67 | 
             
                  t.timestamps
         | 
| 66 68 | 
             
                end
         | 
| 67 69 |  | 
| 68 | 
            -
                create_table  | 
| 70 | 
            +
                create_table <%= @event_products_table_name %> do |t|
         | 
| 71 | 
            +
                  t.integer :event_id
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  t.string :title
         | 
| 74 | 
            +
                  t.integer :capacity
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  t.integer :price
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  t.string :qb_item_name
         | 
| 79 | 
            +
                  t.boolean :tax_exempt, default: false
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  t.integer :position
         | 
| 82 | 
            +
                  t.boolean :archived, default: false
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  t.timestamps
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                create_table <%= @event_purchases_table_name %> do |t|
         | 
| 88 | 
            +
                  t.integer :event_id
         | 
| 89 | 
            +
                  t.integer :event_product_id
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  t.integer :owner_id
         | 
| 92 | 
            +
                  t.string :owner_type
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  t.integer :event_registration_id
         | 
| 95 | 
            +
                  t.string :event_registration_type
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  t.text :notes
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  t.integer :purchased_order_id
         | 
| 100 | 
            +
                  t.integer :price
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  t.timestamps
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                create_table <%= @event_registrations_table_name %> do |t|
         | 
| 69 106 | 
             
                  t.string :token
         | 
| 70 107 |  | 
| 71 108 | 
             
                  t.integer :event_id
         | 
| @@ -90,9 +127,9 @@ class CreateEffectiveEvents < ActiveRecord::Migration[6.0] | |
| 90 127 | 
             
                  t.datetime :created_at
         | 
| 91 128 | 
             
                end
         | 
| 92 129 |  | 
| 93 | 
            -
                add_index  | 
| 94 | 
            -
                add_index  | 
| 95 | 
            -
                add_index  | 
| 130 | 
            +
                add_index <%= @event_registrations_table_name %>, [:owner_id, :owner_type]
         | 
| 131 | 
            +
                add_index <%= @event_registrations_table_name %>, :status
         | 
| 132 | 
            +
                add_index <%= @event_registrations_table_name %>, :token
         | 
| 96 133 |  | 
| 97 134 | 
             
              end
         | 
| 98 135 | 
             
            end
         | 
    
        data/lib/effective_events.rb
    CHANGED
    
    | @@ -6,7 +6,8 @@ module EffectiveEvents | |
| 6 6 |  | 
| 7 7 | 
             
              def self.config_keys
         | 
| 8 8 | 
             
                [
         | 
| 9 | 
            -
                  :events_table_name, :event_registrants_table_name, :event_tickets_table_name, | 
| 9 | 
            +
                  :events_table_name, :event_registrants_table_name, :event_tickets_table_name,
         | 
| 10 | 
            +
                  :event_registrations_table_name, :event_products_table_name, :event_purchases_table_name,
         | 
| 10 11 | 
             
                  :layout, :per_page, :use_effective_roles,
         | 
| 11 12 | 
             
                  :event_registration_class_name
         | 
| 12 13 | 
             
                ]
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            module  | 
| 1 | 
            +
            module EffectiveEvents
         | 
| 2 2 | 
             
              module Generators
         | 
| 3 3 | 
             
                class InstallGenerator < Rails::Generators::Base
         | 
| 4 4 | 
             
                  include Rails::Generators::Migration
         | 
| @@ -21,6 +21,11 @@ module EffectiveMemberships | |
| 21 21 |  | 
| 22 22 | 
             
                  def create_migration_file
         | 
| 23 23 | 
             
                    @events_table_name  = ':' + EffectiveEvents.events_table_name.to_s
         | 
| 24 | 
            +
                    @event_products_table_name  = ':' + EffectiveEvents.event_products_table_name.to_s
         | 
| 25 | 
            +
                    @event_purchases_table_name  = ':' + EffectiveEvents.event_purchases_table_name.to_s
         | 
| 26 | 
            +
                    @event_registrants_table_name  = ':' + EffectiveEvents.event_registrants_table_name.to_s
         | 
| 27 | 
            +
                    @event_registrations_table_name  = ':' + EffectiveEvents.event_registrations_table_name.to_s
         | 
| 28 | 
            +
                    @event_tickets_table_name = ':' + EffectiveEvents.event_tickets_table_name.to_s
         | 
| 24 29 |  | 
| 25 30 | 
             
                    migration_template ('../' * 3) + 'db/migrate/01_create_effective_events.rb.erb', 'db/migrate/create_effective_events.rb'
         | 
| 26 31 | 
             
                  end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: effective_events
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.7
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Code and Effect
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022-01- | 
| 11 | 
            +
            date: 2022-01-13 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rails
         | 
| @@ -179,25 +179,34 @@ files: | |
| 179 179 | 
             
            - app/assets/javascripts/effective_events/base.js
         | 
| 180 180 | 
             
            - app/assets/stylesheets/effective_events.scss
         | 
| 181 181 | 
             
            - app/assets/stylesheets/effective_events/base.scss
         | 
| 182 | 
            +
            - app/controllers/admin/event_products_controller.rb
         | 
| 183 | 
            +
            - app/controllers/admin/event_purchases_controller.rb
         | 
| 182 184 | 
             
            - app/controllers/admin/event_registrants_controller.rb
         | 
| 183 185 | 
             
            - app/controllers/admin/event_registrations_controller.rb
         | 
| 184 186 | 
             
            - app/controllers/admin/event_tickets_controller.rb
         | 
| 185 187 | 
             
            - app/controllers/admin/events_controller.rb
         | 
| 186 188 | 
             
            - app/controllers/effective/event_registrations_controller.rb
         | 
| 187 189 | 
             
            - app/controllers/effective/events_controller.rb
         | 
| 190 | 
            +
            - app/datatables/admin/effective_event_products_datatable.rb
         | 
| 191 | 
            +
            - app/datatables/admin/effective_event_purchases_datatable.rb
         | 
| 188 192 | 
             
            - app/datatables/admin/effective_event_registrants_datatable.rb
         | 
| 189 193 | 
             
            - app/datatables/admin/effective_event_registrations_datatable.rb
         | 
| 190 194 | 
             
            - app/datatables/admin/effective_event_tickets_datatable.rb
         | 
| 191 195 | 
             
            - app/datatables/admin/effective_events_datatable.rb
         | 
| 196 | 
            +
            - app/datatables/effective_event_purchases_datatable.rb
         | 
| 192 197 | 
             
            - app/datatables/effective_event_registrants_datatable.rb
         | 
| 193 198 | 
             
            - app/datatables/effective_event_registrations_datatable.rb
         | 
| 194 199 | 
             
            - app/datatables/effective_events_datatable.rb
         | 
| 195 200 | 
             
            - app/helpers/effective_events_helper.rb
         | 
| 196 201 | 
             
            - app/models/concerns/effective_events_event_registration.rb
         | 
| 197 202 | 
             
            - app/models/effective/event.rb
         | 
| 203 | 
            +
            - app/models/effective/event_product.rb
         | 
| 204 | 
            +
            - app/models/effective/event_purchase.rb
         | 
| 198 205 | 
             
            - app/models/effective/event_registrant.rb
         | 
| 199 206 | 
             
            - app/models/effective/event_registration.rb
         | 
| 200 207 | 
             
            - app/models/effective/event_ticket.rb
         | 
| 208 | 
            +
            - app/views/admin/event_products/_form.html.haml
         | 
| 209 | 
            +
            - app/views/admin/event_purchases/_form.html.haml
         | 
| 201 210 | 
             
            - app/views/admin/event_registrants/_form.html.haml
         | 
| 202 211 | 
             
            - app/views/admin/event_tickets/_form.html.haml
         | 
| 203 212 | 
             
            - app/views/admin/events/_form.html.haml
         | 
| @@ -205,21 +214,23 @@ files: | |
| 205 214 | 
             
            - app/views/admin/events/_form_content.html.haml
         | 
| 206 215 | 
             
            - app/views/admin/events/_form_event.html.haml
         | 
| 207 216 | 
             
            - app/views/admin/events/_form_event_registration_content.html.haml
         | 
| 217 | 
            +
            - app/views/effective/event_purchases/_fields.html.haml
         | 
| 208 218 | 
             
            - app/views/effective/event_registrants/_fields.html.haml
         | 
| 209 219 | 
             
            - app/views/effective/event_registrations/_content.html.haml
         | 
| 210 220 | 
             
            - app/views/effective/event_registrations/_dashboard.html.haml
         | 
| 211 221 | 
             
            - app/views/effective/event_registrations/_event_registration.html.haml
         | 
| 212 222 | 
             
            - app/views/effective/event_registrations/_layout.html.haml
         | 
| 213 223 | 
             
            - app/views/effective/event_registrations/_orders.html.haml
         | 
| 224 | 
            +
            - app/views/effective/event_registrations/_purchases.html.haml
         | 
| 214 225 | 
             
            - app/views/effective/event_registrations/_registrants.html.haml
         | 
| 215 226 | 
             
            - app/views/effective/event_registrations/_summary.html.haml
         | 
| 216 227 | 
             
            - app/views/effective/event_registrations/billing.html.haml
         | 
| 217 228 | 
             
            - app/views/effective/event_registrations/checkout.html.haml
         | 
| 229 | 
            +
            - app/views/effective/event_registrations/purchases.html.haml
         | 
| 218 230 | 
             
            - app/views/effective/event_registrations/registrants.html.haml
         | 
| 219 231 | 
             
            - app/views/effective/event_registrations/start.html.haml
         | 
| 220 232 | 
             
            - app/views/effective/event_registrations/submitted.html.haml
         | 
| 221 233 | 
             
            - app/views/effective/event_registrations/summary.html.haml
         | 
| 222 | 
            -
            - app/views/effective/event_tickets/_fields.html.haml
         | 
| 223 234 | 
             
            - app/views/effective/events/_dashboard.html.haml
         | 
| 224 235 | 
             
            - app/views/effective/events/_event.html.haml
         | 
| 225 236 | 
             
            - app/views/effective/events/_layout.html.haml
         |