artfully_ose 1.0.0.rc4 → 1.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +661 -0
- data/app/assets/fonts/FontAwesome.otf +0 -0
- data/app/assets/fonts/fontawesome-webfont.eot +0 -0
- data/app/assets/fonts/fontawesome-webfont.svg +284 -0
- data/app/assets/fonts/fontawesome-webfont.ttf +0 -0
- data/app/assets/fonts/fontawesome-webfont.woff +0 -0
- data/app/assets/images/chosen-sprite.png +0 -0
- data/app/assets/javascripts/application.js +88 -44
- data/app/assets/javascripts/box-office.js +7 -3
- data/app/assets/javascripts/custom/grouped-form.js +1 -1
- data/app/assets/javascripts/custom/modernizr.custom.12828.js +4 -0
- data/app/assets/javascripts/custom/people.js +30 -1
- data/app/assets/javascripts/jquery-lib/chosen.jquery.js +1026 -0
- data/app/assets/javascripts/jquery-lib/jquery.jeditable.js +1 -1
- data/app/assets/javascripts/jquery-lib/jquery.mask-money.js +90 -60
- data/app/assets/javascripts/store/store.js +112 -67
- data/app/assets/stylesheets/application.sass +174 -1
- data/app/assets/stylesheets/bootstrap-overrides.css +51 -13
- data/app/assets/stylesheets/bootstrap.css +4 -379
- data/app/assets/stylesheets/font-awesome.sass +759 -0
- data/app/assets/stylesheets/jquery/chosen.scss +397 -0
- data/app/assets/stylesheets/printing.css +5 -1
- data/app/assets/stylesheets/sass/store.sass +18 -3
- data/app/concerns/itemable.rb +11 -0
- data/app/concerns/oh_noes.rb +24 -0
- data/app/controllers/actions_controller.rb +39 -20
- data/app/controllers/addresses_controller.rb +2 -2
- data/app/controllers/artfully_ose_controller.rb +15 -1
- data/app/controllers/charts_controller.rb +6 -2
- data/app/controllers/contributions_controller.rb +28 -1
- data/app/controllers/discounts_controller.rb +65 -0
- data/app/controllers/discounts_reports_controller.rb +22 -0
- data/app/controllers/events_controller.rb +48 -45
- data/app/controllers/exchanges_controller.rb +10 -10
- data/app/controllers/imports_controller.rb +38 -20
- data/app/controllers/index_controller.rb +1 -1
- data/app/controllers/memberships_controller.rb +1 -0
- data/app/controllers/merges_controller.rb +1 -1
- data/app/controllers/orders_controller.rb +6 -12
- data/app/controllers/organizations_controller.rb +0 -1
- data/app/controllers/people_controller.rb +10 -12
- data/app/controllers/refunds_controller.rb +2 -2
- data/app/controllers/returns_controller.rb +0 -1
- data/app/controllers/sales_controller.rb +9 -6
- data/app/controllers/searches_controller.rb +53 -0
- data/app/controllers/sections_controller.rb +12 -1
- data/app/controllers/segments_controller.rb +23 -10
- data/app/controllers/shows_controller.rb +37 -28
- data/app/controllers/slices_controller.rb +37 -0
- data/app/controllers/statements_controller.rb +4 -4
- data/app/controllers/store/checkouts_controller.rb +14 -12
- data/app/controllers/store/events_controller.rb +1 -1
- data/app/controllers/store/orders_controller.rb +32 -5
- data/app/controllers/store/store_controller.rb +4 -0
- data/app/controllers/venues_controller.rb +6 -2
- data/app/helpers/artfully_ose_helper.rb +31 -5
- data/app/helpers/discounts_helper.rb +3 -0
- data/app/helpers/people_helper.rb +2 -19
- data/app/mailers/order_mailer.rb +21 -3
- data/app/mailers/producer_mailer.rb +9 -1
- data/app/mailers/reports_mailer.rb +12 -0
- data/app/models/action.rb +29 -3
- data/app/models/actions/get_action.rb +4 -0
- data/app/models/actions/go_action.rb +18 -0
- data/app/models/actions/refund_action.rb +14 -0
- data/app/models/address.rb +6 -16
- data/app/models/adjustments.rb +10 -0
- data/app/models/box_office.rb +1 -1
- data/app/models/carts/cart.rb +35 -24
- data/app/models/chart.rb +16 -8
- data/app/models/checkout.rb +32 -9
- data/app/models/comp.rb +2 -8
- data/app/models/contribution.rb +111 -25
- data/app/models/daily_donation_report.rb +45 -0
- data/app/models/daily_ticket_report.rb +51 -0
- data/app/models/discount.rb +137 -0
- data/app/models/discounts/buy_one_get_one_free_discount_type.rb +20 -0
- data/app/models/discounts/discount_type.rb +66 -0
- data/app/models/discounts/dollars_off_tickets_discount_type.rb +32 -0
- data/app/models/discounts/percentage_off_tickets_discount_type.rb +25 -0
- data/app/models/discounts_report.rb +87 -0
- data/app/models/donation.rb +2 -0
- data/app/models/door_list.rb +5 -4
- data/app/models/event.rb +45 -16
- data/app/models/exchange.rb +26 -15
- data/app/models/ext/delayed_indexing.rb +24 -0
- data/app/models/ext/due.rb +7 -0
- data/app/models/ext/ext.rb +37 -0
- data/app/models/ext/integrations.rb +30 -0
- data/app/models/ext/resellable.rb +8 -1
- data/app/models/gateway_transaction.rb +47 -0
- data/app/models/import.rb +83 -101
- data/app/models/import_error.rb +1 -1
- data/app/models/import_row.rb +1 -1
- data/app/models/imports/donations_import.rb +103 -0
- data/app/models/imports/events_import.rb +207 -0
- data/app/models/imports/people_import.rb +41 -0
- data/app/models/imports/processing.rb +53 -0
- data/app/models/imports/rollback.rb +11 -0
- data/app/models/imports/status.rb +48 -0
- data/app/models/imports/validations.rb +31 -0
- data/app/models/item.rb +112 -29
- data/app/models/job/action_job.rb +29 -0
- data/app/models/job/daily_email_report_job.rb +11 -0
- data/app/models/job/tag_job.rb +15 -0
- data/app/models/kit.rb +14 -6
- data/app/models/kits/mailchimp_kit.rb +448 -0
- data/app/models/kits/reseller_kit.rb +2 -2
- data/app/models/kits/sponsored_donation_kit.rb +2 -2
- data/app/models/orders/application_order.rb +3 -1
- data/app/models/orders/comp_order.rb +15 -2
- data/app/models/orders/exchange_order.rb +8 -0
- data/app/models/orders/imported_order.rb +7 -0
- data/app/models/orders/order.rb +164 -51
- data/app/models/orders/refund_order.rb +14 -1
- data/app/models/orders/unrefundable.rb +5 -0
- data/app/models/orders/web_order.rb +1 -1
- data/app/models/organization.rb +38 -7
- data/app/models/parsed_row.rb +167 -0
- data/app/models/payments/comp_payment.rb +10 -1
- data/app/models/payments/credit_card_payment.rb +63 -10
- data/app/models/payments/payment.rb +28 -0
- data/app/models/person.rb +115 -43
- data/app/models/refund.rb +28 -28
- data/app/models/return.rb +2 -0
- data/app/models/sale.rb +8 -5
- data/app/models/search.rb +117 -0
- data/app/models/section.rb +18 -0
- data/app/models/segment.rb +14 -4
- data/app/models/show.rb +14 -4
- data/app/models/slices.rb +82 -0
- data/app/models/statement.rb +170 -3
- data/app/models/temp_discount.rb +14 -0
- data/app/models/ticket.rb +42 -134
- data/app/models/ticket/pricing.rb +45 -0
- data/app/models/ticket/reports.rb +10 -7
- data/app/models/ticket/sale_transitions.rb +44 -0
- data/app/models/ticket/transfers.rb +50 -0
- data/app/models/user.rb +10 -2
- data/app/models/valuation/lifetime_donations.rb +35 -0
- data/app/models/venue.rb +12 -1
- data/app/presenters/event_presenter.rb +41 -0
- data/app/views/actions/_list.html.haml +1 -2
- data/app/views/actions/new.html.haml +1 -1
- data/app/views/contributions/_form.html.haml +40 -0
- data/app/views/contributions/_sidebar.html.haml +12 -0
- data/app/views/contributions/edit.html.haml +11 -0
- data/app/views/contributions/index.html.haml +2 -2
- data/app/views/contributions/new.html.haml +5 -35
- data/app/views/discounts/_discount_section_fields.html.haml +25 -0
- data/app/views/discounts/_form.html.haml +95 -0
- data/app/views/discounts/edit.html.haml +16 -0
- data/app/views/discounts/index.html.haml +33 -0
- data/app/views/discounts/new.html.haml +16 -0
- data/app/views/discounts_reports/index.html.haml +76 -0
- data/app/views/events/_discount_section_fields.html.haml +25 -0
- data/app/views/events/_glance.html.haml +4 -1
- data/app/views/events/_list.html.haml +2 -4
- data/app/views/events/_menu.html.haml +3 -3
- data/app/views/events/_section_fields.html.haml +32 -15
- data/app/views/events/_share_and_sell.haml +2 -1
- data/app/views/events/edit.html.haml +7 -6
- data/app/views/events/image.html.haml +1 -0
- data/app/views/events/index.html.haml +3 -1
- data/app/views/events/messages.html.haml +1 -0
- data/app/views/events/prices.html.haml +2 -1
- data/app/views/events/resell.html.haml +1 -1
- data/app/views/events/show.html.haml +25 -1
- data/app/views/events/storefront_link.html.haml +1 -1
- data/app/views/events/temp_discount_form.html.haml +108 -0
- data/app/views/events/temp_discounts_index.html.haml +38 -0
- data/app/views/events/widget.html.haml +14 -1
- data/app/views/exchanges/new.html.haml +50 -73
- data/app/views/imports/{_imported.html.haml → donations/_approved.html.haml} +2 -5
- data/app/views/imports/donations/_caching.html.haml +17 -0
- data/app/views/imports/donations/_failed.html.haml +5 -0
- data/app/views/imports/donations/_imported.html.haml +9 -0
- data/app/views/imports/donations/_importing.html.haml +12 -0
- data/app/views/imports/donations/_invalid.html.haml +5 -0
- data/app/views/imports/donations/_new.html.haml +99 -0
- data/app/views/imports/donations/_pending.html.haml +41 -0
- data/app/views/imports/events/_approved.html.haml +10 -0
- data/app/views/imports/events/_caching.html.haml +17 -0
- data/app/views/imports/events/_failed.html.haml +5 -0
- data/app/views/imports/events/_imported.html.haml +9 -0
- data/app/views/imports/events/_importing.html.haml +12 -0
- data/app/views/imports/events/_invalid.html.haml +5 -0
- data/app/views/imports/events/_new.html.haml +95 -0
- data/app/views/imports/events/_pending.html.haml +35 -0
- data/app/views/imports/index.html.haml +41 -18
- data/app/views/imports/new.html.haml +1 -93
- data/app/views/imports/{_approved.html.haml → people/_approved.html.haml} +0 -1
- data/app/views/imports/{_caching.html.haml → people/_caching.html.haml} +0 -0
- data/app/views/imports/people/_failed.html.haml +5 -0
- data/app/views/imports/people/_imported.html.haml +25 -0
- data/app/views/imports/{_importing.html.haml → people/_importing.html.haml} +1 -2
- data/app/views/imports/people/_invalid.html.haml +5 -0
- data/app/views/imports/people/_new.html.haml +120 -0
- data/app/views/imports/people/_pending.html.haml +39 -0
- data/app/views/imports/shared/_date_format.html.haml +14 -0
- data/app/views/imports/shared/_failed.html.haml +18 -0
- data/app/views/imports/shared/_inspect_modal.html.haml +11 -0
- data/app/views/imports/shared/_invalid.html.haml +18 -0
- data/app/views/imports/shared/_knowledge_base.haml +2 -0
- data/app/views/imports/shared/_sidebar.html.haml +5 -0
- data/app/views/imports/show.html.haml +2 -2
- data/app/views/index/dashboard.html.haml +4 -2
- data/app/views/layouts/_custom_css_includes.haml +0 -0
- data/app/views/layouts/_custom_js_includes.haml +0 -0
- data/app/views/layouts/_google_analytics.html.haml +3 -3
- data/app/views/layouts/_menu.html.haml +6 -2
- data/app/views/layouts/application.html.haml +4 -0
- data/app/views/layouts/{devise.html.haml → devise_layout.html.haml} +0 -0
- data/app/views/order_mailer/confirmation_for.html.haml +3 -2
- data/app/views/order_mailer/confirmation_for.text.haml +3 -2
- data/app/views/orders/_grouped_form_help.haml +4 -0
- data/app/views/orders/_item_table.haml +15 -4
- data/app/views/orders/_order_sidebar.html.haml +27 -6
- data/app/views/orders/index.html.haml +1 -12
- data/app/views/orders/show.html.haml +1 -1
- data/app/views/organizations/_form.html.haml +20 -6
- data/app/views/organizations/edit.html.haml +2 -1
- data/app/views/organizations/new.html.haml +1 -0
- data/app/views/organizations/show.html.haml +7 -1
- data/app/views/people/_form.html.haml +5 -2
- data/app/views/people/_key_relationships.html.haml +1 -1
- data/app/views/people/_list.html.haml +1 -12
- data/app/views/people/_person_summary_sidebar.html.haml +82 -50
- data/app/views/people/_relationship_table_row.html.haml +1 -1
- data/app/views/people/edit.html.haml +3 -1
- data/app/views/people/index.html.haml +7 -1
- data/app/views/people/new.html.haml +2 -0
- data/app/views/people/show.html.haml +2 -0
- data/app/views/refunds/new.html.haml +4 -6
- data/app/views/reports_mailer/daily.html.haml +67 -0
- data/app/views/reports_mailer/daily.text.erb +16 -0
- data/app/views/sales/new.html.haml +5 -20
- data/app/views/searches/_form.html.haml +43 -0
- data/app/views/searches/_person.html.haml +7 -0
- data/app/views/searches/new.html.haml +10 -0
- data/app/views/searches/show.html.haml +64 -0
- data/app/views/sections/edit.html.haml +12 -0
- data/app/views/segments/index.html.haml +8 -4
- data/app/views/segments/show.html.haml +39 -5
- data/app/views/shared/_door_list_table.haml +24 -0
- data/app/views/shared/_event_image_icon.html.haml +1 -1
- data/app/views/shared/_preload_assets.html.haml +2 -0
- data/app/views/shared/_tags.html.haml +3 -2
- data/app/views/shows/_glance.html.haml +8 -2
- data/app/views/shows/_ticket_table.html.haml +17 -10
- data/app/views/shows/_upcoming.html.haml +1 -1
- data/app/views/shows/door_list.html.haml +2 -24
- data/app/views/shows/index.html.haml +3 -3
- data/app/views/shows/new.html.haml +2 -2
- data/app/views/shows/show.html.haml +1 -1
- data/app/views/slices/_data.json +50 -0
- data/app/views/slices/index.html.haml +58 -0
- data/app/views/statements/_discounts_table.html.haml +26 -0
- data/app/views/statements/_order_location_table.html.haml +20 -0
- data/app/views/statements/_payment_method_table.haml +20 -0
- data/app/views/statements/{_played_shows.html.haml → _shows.html.haml} +3 -3
- data/app/views/statements/_ticket_type_table.haml +20 -0
- data/app/views/statements/_top_stats.haml +12 -0
- data/app/views/statements/show.html.haml +24 -32
- data/app/views/store/events/_show.html.haml +11 -5
- data/app/views/store/events/show.html.haml +24 -5
- data/app/views/users/registrations/edit.html.erb +1 -1
- data/app/views/venues/edit.html.haml +1 -0
- data/config/artfully.yml.sample +3 -0
- data/config/initializers/active_model_serializer.rb +3 -0
- data/config/initializers/braintree_error_mapping.rb +5 -0
- data/config/initializers/devise.rb +1 -1
- data/config/locales/en.yml +1 -0
- data/config/routes.rb +31 -8
- data/db/migrate/0000_set_up_artfully.rb +9 -11
- data/db/migrate/20120809212802_add_do_not_email_to_people.rb +5 -0
- data/db/migrate/20120831200120_create_advanced_search.rb +30 -0
- data/db/migrate/20120926201927_add_email_to_organization.rb +5 -0
- data/db/migrate/20121001143351_add_import_id_orders_events.rb +6 -0
- data/db/migrate/20121006024736_add_import_to_actions.rb +5 -0
- data/db/migrate/20121011180654_add_type_to_imports.rb +14 -0
- data/db/migrate/20121024143846_create_discounts.rb +15 -0
- data/db/migrate/20121026131454_deleted_at_to_orders_items_actions.rb +7 -0
- data/db/migrate/20121026203948_add_initial_price_to_tickets.rb +5 -0
- data/db/migrate/20121029183949_change_initial_price_to_cart_price.rb +5 -0
- data/db/migrate/20121113144826_migrate_donation_types.rb +41 -0
- data/db/migrate/20121115020441_add_salutation_to_people.rb +5 -0
- data/db/migrate/20121130004314_add_visibility_to_sections.rb +6 -0
- data/db/migrate/20121205184343_add_discount_to_ticket.rb +6 -0
- data/db/migrate/20121206212835_add_discount_to_carts_and_items.rb +7 -0
- data/db/migrate/20121211193728_add_deleted_at_to_discounts.rb +5 -0
- data/db/migrate/20121212022026_add_uuid_to_show_and_event.rb +9 -0
- data/db/migrate/20121212023203_set_uuids.rb +11 -0
- data/db/migrate/20121217201422_add_minimum_ticket_count_to_discounts.rb +5 -0
- data/db/migrate/20121221154152_add_shows_and_sections_to_discounts.rb +5 -0
- data/db/migrate/20130103153946_make_shows_and_sections_habtm.rb +19 -0
- data/db/migrate/20130108213102_add_original_price_to_items.rb +10 -0
- data/db/migrate/20130111211929_convert_discounts_sections_to_array_of_strings.rb +14 -0
- data/db/migrate/20130114200128_add_discount_code_to_search.rb +5 -0
- data/db/migrate/20130114212408_add_limit_to_discounts.rb +5 -0
- data/db/migrate/20130116203331_add_title_to_person.rb +5 -0
- data/db/migrate/20130122143845_install_audited.rb +28 -0
- data/db/migrate/20130131024955_add_gateway_transactions.rb +13 -0
- data/db/migrate/20130301144159_add_receive_daily_sales_report_boolean_to_organizations.rb +5 -0
- data/db/migrate/20130306213416_add_subscribed_lists_to_people.rb +5 -0
- data/db/migrate/20130308193328_people_arent_dummies.rb +6 -0
- data/db/migrate/20130312173340_add_categories_to_events.rb +6 -0
- data/db/migrate/20130319110520_add_transaction_id_index.rb +6 -0
- data/db/migrate/20130320192827_add_index_to_notes.rb +8 -0
- data/db/migrate/20130324173939_add_index_to_import_rows.rb +5 -0
- data/db/migrate/20130325190110_add_indexes_to_actions.rb +9 -0
- data/db/migrate/20130326173653_add_lifetime_donations_to_people_and_searches.rb +9 -0
- data/lib/artfully_ose.rb +5 -1
- data/lib/artfully_ose/common_abilities.rb +6 -9
- data/lib/artfully_ose/engine.rb +19 -5
- data/lib/artfully_ose/version.rb +1 -1
- data/lib/email_validator.rb +6 -0
- metadata +442 -138
- data/MIT-LICENSE +0 -20
- data/app/controllers/pages_controller.rb +0 -29
- data/app/models/import_person.rb +0 -78
- data/app/views/imports/_failed.html.haml +0 -20
- data/app/views/imports/_pending.html.haml +0 -35
- data/app/views/index/splash.html.erb +0 -160
- data/app/views/segments/new.html.haml +0 -20
data/app/models/statement.rb
CHANGED
@@ -1,18 +1,41 @@
|
|
1
|
+
###
|
2
|
+
#
|
3
|
+
# Statement uses items from a show to calculate things like gross, net, and
|
4
|
+
# cut the data up into various sections. The reason we don't use tickets is:
|
5
|
+
#
|
6
|
+
# * Item is the table of record for revenue
|
7
|
+
# * a Ticket can have many items (refunds, exchanges, etc...) It's awkward (and db intensive)
|
8
|
+
# to get the sold_item for a ticket
|
9
|
+
#
|
10
|
+
# The downside is that this approach requires a bit of hoop jumping in Row (see if, elsif, else block)
|
11
|
+
# which is indeed ugly.
|
12
|
+
#
|
13
|
+
###
|
1
14
|
class Statement
|
15
|
+
include Ext::Due
|
16
|
+
|
2
17
|
attr_accessor :datetime,
|
3
18
|
:tickets_sold,
|
4
19
|
:tickets_comped,
|
5
20
|
:potential_revenue,
|
6
21
|
:gross_revenue,
|
7
22
|
:processing,
|
8
|
-
:net_revenue
|
23
|
+
:net_revenue,
|
24
|
+
:cc_net,
|
25
|
+
:settled,
|
26
|
+
:payment_method_rows,
|
27
|
+
:order_location_rows,
|
28
|
+
:ticket_type_rows,
|
29
|
+
:discount_rows
|
9
30
|
|
10
|
-
def self.for_show(show,
|
11
|
-
if show.nil?
|
31
|
+
def self.for_show(show, imported=false)
|
32
|
+
if show.nil?
|
12
33
|
return new
|
13
34
|
end
|
14
35
|
|
15
36
|
new.tap do |statement|
|
37
|
+
|
38
|
+
# Some of this overlaps with Ticket::Glance. Consider refactoring to combine the two.
|
16
39
|
statement.datetime = show.datetime_local_to_event
|
17
40
|
statement.tickets_sold = show.tickets.select{|t| t.sold?}.size
|
18
41
|
statement.tickets_comped = show.tickets.select{|t| t.comped?}.size
|
@@ -20,6 +43,150 @@ class Statement
|
|
20
43
|
statement.gross_revenue = show.items.inject(0) { |gross, item| gross += item.price }
|
21
44
|
statement.net_revenue = show.items.inject(0) { |net, item| net += item.net }
|
22
45
|
statement.processing = statement.gross_revenue - statement.net_revenue
|
46
|
+
|
47
|
+
statement.calculate_due(show, imported)
|
48
|
+
|
49
|
+
#
|
50
|
+
# PAYMENT METHOD
|
51
|
+
#
|
52
|
+
payment_method_hash = show.items.group_by { |item| item.order.payment_method }
|
53
|
+
statement.payment_method_rows = {}
|
54
|
+
|
55
|
+
# Initialize with the three common payment types
|
56
|
+
statement.payment_method_rows[::CreditCardPayment.payment_method.downcase] = PaymentTypeRow.new(::CreditCardPayment.payment_method)
|
57
|
+
statement.payment_method_rows[::CashPayment.payment_method.downcase] = PaymentTypeRow.new(::CashPayment.payment_method)
|
58
|
+
statement.payment_method_rows[::CompPayment.payment_method.downcase] = PaymentTypeRow.new(::CompPayment.payment_method)
|
59
|
+
|
60
|
+
payment_method_hash.each do |payment_method, items|
|
61
|
+
payment_method = (payment_method.try(:downcase) || "")
|
62
|
+
row = statement.payment_method_rows[payment_method] || PaymentTypeRow.new(payment_method)
|
63
|
+
items.each {|item| row << item}
|
64
|
+
statement.payment_method_rows[payment_method] = row
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# ORDER LOCATION
|
69
|
+
#
|
70
|
+
order_location_hash = show.items.group_by do |item|
|
71
|
+
item.order.original_order.location
|
72
|
+
end
|
73
|
+
|
74
|
+
statement.order_location_rows = {}
|
75
|
+
statement.order_location_rows[::WebOrder.location] = OrderLocationRow.new(::WebOrder.location)
|
76
|
+
statement.order_location_rows[BoxOffice::Order.location] = OrderLocationRow.new(BoxOffice::Order.location)
|
77
|
+
|
78
|
+
order_location_hash.each do |order_location, items|
|
79
|
+
row = statement.order_location_rows[order_location] || OrderLocationRow.new(order_location)
|
80
|
+
items.each {|item| row << item}
|
81
|
+
statement.order_location_rows[order_location] = row
|
82
|
+
end
|
83
|
+
|
84
|
+
statement.build_discount_rows(show.items)
|
85
|
+
statement.build_ticket_type_rows(show, show.items)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# TODO: These are super-related to the procs in class Slices. Get these two on the same page and DRY it up
|
91
|
+
#
|
92
|
+
def build_ticket_type_rows(show, items)
|
93
|
+
self.ticket_type_rows = {}
|
94
|
+
|
95
|
+
show.chart.sections.each do |section|
|
96
|
+
self.ticket_type_rows[section.name] = TicketTypeRow.new(section.name)
|
97
|
+
end
|
98
|
+
|
99
|
+
items.each do |item|
|
100
|
+
row = self.ticket_type_rows[item.product.section.name] || TicketTypeRow.new(item.product.section.name)
|
101
|
+
row << item
|
102
|
+
self.ticket_type_rows[item.product.section.name] = row
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def build_discount_rows(items)
|
107
|
+
self.discount_rows = {}
|
108
|
+
items.each do |item|
|
109
|
+
unless item.discount.nil?
|
110
|
+
row = self.discount_rows[item.discount.code] || DiscountRow.new(item.discount.code, item.discount.to_s)
|
111
|
+
row << item
|
112
|
+
row.discount += (item.original_price - item.price)
|
113
|
+
self.discount_rows[item.discount.code] = row
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
module Row
|
119
|
+
attr_accessor :tickets,
|
120
|
+
:gross,
|
121
|
+
:processing,
|
122
|
+
:net
|
123
|
+
|
124
|
+
def<<(item)
|
125
|
+
if item.refund?
|
126
|
+
self.tickets = self.tickets - 1
|
127
|
+
elsif item.exchanged? || item.return?
|
128
|
+
#Noop
|
129
|
+
else
|
130
|
+
self.tickets = self.tickets + 1
|
131
|
+
end
|
132
|
+
|
133
|
+
self.gross = self.gross + item.price
|
134
|
+
self.processing = self.processing + (item.realized_price - item.net)
|
135
|
+
self.net = self.net + item.net
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class TicketTypeRow
|
140
|
+
include Row
|
141
|
+
attr_accessor :ticket_type
|
142
|
+
|
143
|
+
def initialize(ticket_type)
|
144
|
+
self.ticket_type = ticket_type
|
145
|
+
self.tickets = 0
|
146
|
+
self.gross = 0
|
147
|
+
self.processing = 0
|
148
|
+
self.net = 0
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class DiscountRow
|
153
|
+
include Row
|
154
|
+
attr_accessor :discount_code, :type, :discount
|
155
|
+
|
156
|
+
def initialize(discount_code, type)
|
157
|
+
self.discount_code = discount_code
|
158
|
+
self.type = type
|
159
|
+
self.tickets = 0
|
160
|
+
self.gross = 0
|
161
|
+
self.processing = 0
|
162
|
+
self.net = 0
|
163
|
+
self.discount = 0
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class OrderLocationRow
|
168
|
+
include Row
|
169
|
+
attr_accessor :order_location
|
170
|
+
|
171
|
+
def initialize(order_location)
|
172
|
+
self.order_location = order_location
|
173
|
+
self.tickets = 0
|
174
|
+
self.gross = 0
|
175
|
+
self.processing = 0
|
176
|
+
self.net = 0
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class PaymentTypeRow
|
181
|
+
include Row
|
182
|
+
attr_accessor :payment_method
|
183
|
+
|
184
|
+
def initialize(payment_method)
|
185
|
+
self.payment_method = payment_method
|
186
|
+
self.tickets = 0
|
187
|
+
self.gross = 0
|
188
|
+
self.processing = 0
|
189
|
+
self.net = 0
|
23
190
|
end
|
24
191
|
end
|
25
192
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# only exsist for mockuping up the discount form
|
2
|
+
# remove after Discount and DiscountSections model is created
|
3
|
+
|
4
|
+
class TempDiscount < Event
|
5
|
+
attr_accessor :code, :active, :promotion_type, :minimum_purchase, :maximum_purchase, :show_ids, :limit, :unlimited_capacity
|
6
|
+
|
7
|
+
has_many :discount_sections
|
8
|
+
end
|
9
|
+
|
10
|
+
class DiscountSection < Section
|
11
|
+
attr_accessor :temp_discount_id, :section, :section_id
|
12
|
+
|
13
|
+
attr_accessible :section
|
14
|
+
end
|
data/app/models/ticket.rb
CHANGED
@@ -1,20 +1,27 @@
|
|
1
1
|
class Ticket < ActiveRecord::Base
|
2
|
-
|
3
2
|
include ActiveRecord::Transitions
|
3
|
+
include Ext::Resellable::Ticket
|
4
|
+
include Ext::Integrations::Ticket
|
5
|
+
include Ticket::Pricing
|
6
|
+
include Ticket::Transfers
|
7
|
+
include Ticket::SaleTransitions
|
8
|
+
extend ActionView::Helpers::TextHelper
|
4
9
|
|
5
|
-
attr_accessible :section_id, :section, :price, :venue
|
10
|
+
attr_accessible :section_id, :section, :price, :venue, :cart_price
|
6
11
|
|
7
12
|
belongs_to :buyer, :class_name => "Person"
|
8
13
|
belongs_to :show
|
9
14
|
belongs_to :organization
|
10
15
|
belongs_to :section
|
11
|
-
|
12
16
|
belongs_to :cart
|
17
|
+
belongs_to :discount
|
13
18
|
|
14
19
|
has_many :items, :foreign_key => "product_id"
|
15
20
|
|
16
21
|
delegate :event, :to => :show
|
17
22
|
|
23
|
+
before_validation :set_cart_price
|
24
|
+
|
18
25
|
def self.sold_after(datetime)
|
19
26
|
sold.where("sold_at > ?", datetime)
|
20
27
|
end
|
@@ -33,12 +40,13 @@ class Ticket < ActiveRecord::Base
|
|
33
40
|
state :sold
|
34
41
|
state :comped
|
35
42
|
|
36
|
-
event(:on_sale)
|
37
|
-
event(:off_sale)
|
38
|
-
event(:exchange, :success => :
|
39
|
-
event(:sell, :success => :
|
40
|
-
event(:comp)
|
41
|
-
event(:
|
43
|
+
event(:on_sale) { transitions :from => [ :on_sale, :off_sale ], :to => :on_sale }
|
44
|
+
event(:off_sale) { transitions :from => [ :on_sale, :off_sale ], :to => :off_sale }
|
45
|
+
event(:exchange, :success => :record_exchange) { transitions :from => [ :on_sale, :off_sale ], :to => :sold }
|
46
|
+
event(:sell, :success => :record_sale) { transitions :from => [ :on_sale ], :to => :sold }
|
47
|
+
event(:comp, :success => :record_comp) { transitions :from => [ :on_sale, :off_sale ], :to => :comped }
|
48
|
+
event(:return_to_inventory) { transitions :from => [ :comped, :sold ], :to => :on_sale }
|
49
|
+
event(:return_off_sale) { transitions :from => [ :comped, :sold ], :to => :off_sale }
|
42
50
|
end
|
43
51
|
|
44
52
|
def datetime
|
@@ -53,6 +61,16 @@ class Ticket < ActiveRecord::Base
|
|
53
61
|
where(:state => [:off_sale, :on_sale])
|
54
62
|
end
|
55
63
|
|
64
|
+
def self.to_sentence(tickets)
|
65
|
+
shows_string = tickets.map(&:show).uniq.length > 1 ? ", multiple shows" : " on " + I18n.localize(tickets.first.show.datetime_local_to_event, :format => :day_time_at)
|
66
|
+
events_string = tickets.map(&:show).map(&:event).uniq.length > 1 ? "multiple events" : tickets.first.show.event.name + shows_string
|
67
|
+
pluralize(tickets.length, "ticket") + " to " + events_string
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Unfortunately named. This will return available tickets, not a count of available tickets
|
72
|
+
# as is the idiom elsewhere in the app
|
73
|
+
#
|
56
74
|
def self.available(params = {}, limit = 4)
|
57
75
|
conditions = params.dup
|
58
76
|
conditions[:state] ||= :on_sale
|
@@ -71,8 +89,7 @@ class Ticket < ActiveRecord::Base
|
|
71
89
|
def sold_item
|
72
90
|
items.select(&:purchased?).first ||
|
73
91
|
items.select(&:settled?).first ||
|
74
|
-
items.select(&:comped?).first
|
75
|
-
items.select(&:exchangee?).first
|
92
|
+
items.select(&:comped?).first
|
76
93
|
end
|
77
94
|
|
78
95
|
def special_instructions
|
@@ -99,66 +116,6 @@ class Ticket < ActiveRecord::Base
|
|
99
116
|
!expired?
|
100
117
|
end
|
101
118
|
|
102
|
-
def take_off_sale
|
103
|
-
begin
|
104
|
-
off_sale!
|
105
|
-
rescue Transitions::InvalidTransition
|
106
|
-
return false
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def put_on_sale
|
111
|
-
begin
|
112
|
-
on_sale!
|
113
|
-
rescue Transitions::InvalidTransition
|
114
|
-
return false
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def sell_to(buyer, time=Time.now)
|
119
|
-
begin
|
120
|
-
self.buyer = buyer
|
121
|
-
self.sold_price = self.price
|
122
|
-
self.sold_at = time
|
123
|
-
self.sell!
|
124
|
-
rescue Transitions::InvalidTransition
|
125
|
-
return false
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
def exchange_to(buyer, time=Time.now)
|
130
|
-
begin
|
131
|
-
self.buyer = buyer
|
132
|
-
self.sold_price = 0
|
133
|
-
self.sold_at = time
|
134
|
-
self.exchange!
|
135
|
-
rescue Transitions::InvalidTransition => e
|
136
|
-
puts e
|
137
|
-
return false
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def comp_to(buyer, time=Time.now)
|
142
|
-
begin
|
143
|
-
self.buyer = buyer
|
144
|
-
self.sold_price = 0
|
145
|
-
self.sold_at = time
|
146
|
-
self.comp!
|
147
|
-
rescue Transitions::InvalidTransition => e
|
148
|
-
puts e
|
149
|
-
return false
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def change_price(new_price)
|
154
|
-
unless self.committed? or new_price.to_i < 0
|
155
|
-
self.price = new_price
|
156
|
-
self.save!
|
157
|
-
else
|
158
|
-
return false
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
119
|
def committed?
|
163
120
|
sold? or comped?
|
164
121
|
end
|
@@ -187,80 +144,31 @@ class Ticket < ActiveRecord::Base
|
|
187
144
|
super if destroyable?
|
188
145
|
end
|
189
146
|
|
190
|
-
def return!
|
191
|
-
self.buyer = nil
|
192
|
-
self.sold_price = nil
|
193
|
-
self.sold_at = nil
|
194
|
-
self.buyer_id = nil
|
195
|
-
save
|
196
|
-
do_return!
|
197
|
-
end
|
198
|
-
|
199
|
-
def self.put_on_sale(tickets)
|
200
|
-
return false if tickets.blank?
|
201
|
-
attempt_transition(tickets, :on_sale) do
|
202
|
-
Ticket.update_all({ :state => :on_sale }, { :id => tickets.collect(&:id)})
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def self.take_off_sale(tickets)
|
207
|
-
return false if tickets.blank?
|
208
|
-
attempt_transition(tickets, :off_sale) do
|
209
|
-
Ticket.update_all({ :state => :off_sale }, { :id => tickets.collect(&:id)})
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
147
|
def repriceable?
|
214
148
|
not committed?
|
215
149
|
end
|
216
150
|
|
217
|
-
def reseller
|
218
|
-
order =
|
219
|
-
Reseller::Order.
|
220
|
-
includes(:organization, :items).
|
221
|
-
where("items.product_type" => "Ticket", "items.product_id" => id).
|
222
|
-
first
|
223
|
-
|
224
|
-
order.organization if order
|
225
|
-
end
|
226
|
-
|
227
151
|
#Bulk creation of tickets should use this method to ensure all tickets are created the same
|
228
152
|
#Reminder that this returns a ActiveRecord::Import::Result, not an array of tickets
|
229
153
|
def self.create_many(show, section, quantity, on_sale = false)
|
230
154
|
new_tickets = []
|
231
|
-
|
232
|
-
|
233
|
-
:venue => show.event.venue.name,
|
234
|
-
:price => section.price,
|
235
|
-
:section => section,
|
236
|
-
})
|
237
|
-
t.show = show
|
238
|
-
t.organization = show.organization
|
239
|
-
t.state = 'on_sale' if on_sale
|
240
|
-
new_tickets << t
|
155
|
+
quantity.times do
|
156
|
+
new_tickets << build_one(show, section, section.price, quantity, on_sale)
|
241
157
|
end
|
242
158
|
|
243
159
|
result = Ticket.import(new_tickets)
|
244
160
|
result
|
245
161
|
end
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
def metric_sold
|
259
|
-
RestfulMetrics::Client.add_metric(ENV["RESTFUL_METRICS_APP"], "ticket_sold", 1)
|
260
|
-
end
|
261
|
-
|
262
|
-
def metric_exchanged
|
263
|
-
RestfulMetrics::Client.add_metric(ENV["RESTFUL_METRICS_APP"], "ticket_exchanged", 1)
|
264
|
-
end
|
265
|
-
|
162
|
+
|
163
|
+
def self.build_one(show, section, price, quantity, on_sale = false)
|
164
|
+
t = Ticket.new({
|
165
|
+
:venue => show.event.venue.name,
|
166
|
+
:price => price,
|
167
|
+
:section => section,
|
168
|
+
})
|
169
|
+
t.show = show
|
170
|
+
t.organization = show.organization
|
171
|
+
t.state = 'on_sale' if on_sale
|
172
|
+
t
|
173
|
+
end
|
266
174
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Ticket::Pricing
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
def remove_from_cart
|
5
|
+
self.update_column(:cart_id, nil)
|
6
|
+
end
|
7
|
+
|
8
|
+
#
|
9
|
+
# This is guarded with sold? Because of the DelayedJob that expires tickets. The job
|
10
|
+
# Removes them from cart regardless of state. If they've been sold, we want that information retained
|
11
|
+
#
|
12
|
+
def reset_price!
|
13
|
+
return false if sold?
|
14
|
+
|
15
|
+
self.cart_price = self.price
|
16
|
+
self.discount = nil
|
17
|
+
self.sold_price = nil
|
18
|
+
self.save
|
19
|
+
end
|
20
|
+
|
21
|
+
def exchange_prices_from(old_ticket)
|
22
|
+
self.sold_price = old_ticket.sold_price
|
23
|
+
self.cart_price = old_ticket.sold_price
|
24
|
+
self.discount_id= old_ticket.discount_id
|
25
|
+
self.cart_id = nil
|
26
|
+
self.save
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_cart_price
|
30
|
+
self.cart_price ||= self.price
|
31
|
+
end
|
32
|
+
|
33
|
+
def cart_price
|
34
|
+
self[:cart_price] || self.price
|
35
|
+
end
|
36
|
+
|
37
|
+
def change_price(new_price)
|
38
|
+
unless self.committed? or new_price.to_i < 0
|
39
|
+
self.price = new_price
|
40
|
+
self.save!
|
41
|
+
else
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|