From 5c56683ae8b7a66e47b6f7f5d9dbe587e73fa936 Mon Sep 17 00:00:00 2001 From: Siddhant Bajaj Date: Sat, 3 Jun 2017 16:05:59 +0530 Subject: [PATCH] Introduced Physical Ticket Added PhysicalTicket model and controller. It holds the information about each physical ticket bought at the purchase. Physical Tickets are created after every successfull payment. --- Gemfile | 2 +- app/controllers/payments_controller.rb | 6 ++-- app/controllers/physical_ticket_controller.rb | 12 +++++++ .../ticket_purchases_controller.rb | 2 +- app/models/ability.rb | 1 + app/models/conference.rb | 1 + app/models/physical_ticket.rb | 6 ++++ app/models/ticket_purchase.rb | 13 +++++-- app/models/user.rb | 5 +++ .../conferences/_conference_details.html.haml | 2 ++ app/views/physical_ticket/index.html.haml | 35 +++++++++++++++++++ app/views/physical_ticket/show.html.haml | 0 config/routes.rb | 1 + .../20170603095900_create_physical_tickets.rb | 9 +++++ db/schema.rb | 8 ++++- spec/features/ticket_purchases_spec.rb | 4 +-- spec/models/ticket_purchase_spec.rb | 20 +++++++++-- 17 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 app/controllers/physical_ticket_controller.rb create mode 100644 app/models/physical_ticket.rb create mode 100644 app/views/physical_ticket/index.html.haml create mode 100644 app/views/physical_ticket/show.html.haml create mode 100644 db/migrate/20170603095900_create_physical_tickets.rb diff --git a/Gemfile b/Gemfile index 15b295fa..245080c3 100644 --- a/Gemfile +++ b/Gemfile @@ -20,7 +20,7 @@ gem 'responders', '~> 2.0' # as the database for Active Record # choose only one gem 'mysql2' -#gem 'pg' +# gem 'pg' # for observing records gem 'rails-observers' diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb index e8766548..b5e2c193 100644 --- a/app/controllers/payments_controller.rb +++ b/app/controllers/payments_controller.rb @@ -18,7 +18,7 @@ class PaymentsController < ApplicationController if @payment.purchase && @payment.save update_purchased_ticket_purchases - redirect_to conference_conference_registration_path(@conference.short_title), + redirect_to conference_physical_ticket_index_path, notice: 'Thanks! Your ticket is booked successfully.' else @total_amount_to_pay = Ticket.total_price(@conference, current_user, paid: false) @@ -38,6 +38,8 @@ class PaymentsController < ApplicationController end def update_purchased_ticket_purchases - current_user.ticket_purchases.by_conference(@conference).unpaid.update_all(paid: true, payment_id: @payment.id) + current_user.ticket_purchases.by_conference(@conference).unpaid.each do |ticket_purchase| + ticket_purchase.pay(@payment) + end end end diff --git a/app/controllers/physical_ticket_controller.rb b/app/controllers/physical_ticket_controller.rb new file mode 100644 index 00000000..2354f279 --- /dev/null +++ b/app/controllers/physical_ticket_controller.rb @@ -0,0 +1,12 @@ +class PhysicalTicketController < ApplicationController + before_action :authenticate_user! + load_resource :conference, find_by: :short_title + load_and_authorize_resource + authorize_resource :conference_registrations, class: Registration + + def index + @physical_tickets = current_user.physical_tickets.by_conference(@conference) + end + + def show; end +end diff --git a/app/controllers/ticket_purchases_controller.rb b/app/controllers/ticket_purchases_controller.rb index 1c672d69..3945e154 100644 --- a/app/controllers/ticket_purchases_controller.rb +++ b/app/controllers/ticket_purchases_controller.rb @@ -11,7 +11,7 @@ class TicketPurchasesController < ApplicationController redirect_to new_conference_payment_path, notice: 'Please pay here to get tickets.' elsif current_user.ticket_purchases.by_conference(@conference).paid.any? - redirect_to conference_conference_registration_path(@conference.short_title), + redirect_to conference_physical_ticket_index_path, notice: 'You have free tickets for the conference.' else redirect_to conference_tickets_path(@conference.short_title), diff --git a/app/models/ability.rb b/app/models/ability.rb index cc23a631..bdf554cc 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -87,6 +87,7 @@ class Ability can :index, Ticket can :manage, TicketPurchase, user_id: user.id can [:new, :create], Payment, user_id: user.id + can [:index, :show], PhysicalTicket, user_id: user.id can [:create, :destroy], Subscription, user_id: user.id diff --git a/app/models/conference.rb b/app/models/conference.rb index 0cf16de6..11fab753 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -19,6 +19,7 @@ class Conference < ActiveRecord::Base has_one :email_settings, dependent: :destroy has_one :program, dependent: :destroy has_one :venue, dependent: :destroy + has_many :physical_tickets, through: :ticket_purchases has_many :ticket_purchases, dependent: :destroy has_many :payments, dependent: :destroy has_many :supporters, through: :ticket_purchases, source: :user diff --git a/app/models/physical_ticket.rb b/app/models/physical_ticket.rb new file mode 100644 index 00000000..a0874a6e --- /dev/null +++ b/app/models/physical_ticket.rb @@ -0,0 +1,6 @@ +class PhysicalTicket < ActiveRecord::Base + belongs_to :ticket_purchase + has_one :ticket, through: :ticket_purchase + has_one :conference, through: :ticket_purchase + has_one :user, through: :ticket_purchase +end diff --git a/app/models/ticket_purchase.rb b/app/models/ticket_purchase.rb index d1c370c4..675527ae 100644 --- a/app/models/ticket_purchase.rb +++ b/app/models/ticket_purchase.rb @@ -13,6 +13,8 @@ class TicketPurchase < ActiveRecord::Base delegate :price_cents, to: :ticket delegate :price_currency, to: :ticket + has_many :physical_tickets + scope :paid, -> { where(paid: true) } scope :unpaid, -> { where(paid: false) } scope :by_conference, ->(conference) { where(conference_id: conference.id) } @@ -45,8 +47,8 @@ class TicketPurchase < ActiveRecord::Base purchase = new(ticket_id: ticket.id, conference_id: conference.id, user_id: user.id, - quantity: quantity, - paid: ticket.price_cents.zero?) + quantity: quantity) + purchase.pay(nil) if ticket.price_cents.zero? end purchase end @@ -60,6 +62,13 @@ class TicketPurchase < ActiveRecord::Base purchase.quantity = quantity if quantity > 0 purchase end + + def pay(payment) + update_attributes(paid: true, payment: payment) + PhysicalTicket.transaction do + quantity.times { physical_tickets.create } + end + end end private diff --git a/app/models/user.rb b/app/models/user.rb index 4be77fe8..6ffb739f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -6,6 +6,11 @@ end class User < ActiveRecord::Base rolify + has_many :physical_tickets, through: :ticket_purchases do + def by_conference(conference) + where('ticket_purchases.conference_id = ?', conference) + end + end has_many :users_roles has_many :roles, through: :users_roles, dependent: :destroy diff --git a/app/views/conferences/_conference_details.html.haml b/app/views/conferences/_conference_details.html.haml index bdbd5fc6..d5bafad4 100644 --- a/app/views/conferences/_conference_details.html.haml +++ b/app/views/conferences/_conference_details.html.haml @@ -38,3 +38,5 @@ = link_to 'Subscribe', conference_subscriptions_path(conference.short_title), method: :post, class: 'btn btn-default' - else = link_to 'Unsubscribe', conference_subscriptions_path(conference.short_title), method: :delete, class: 'btn btn-default' + - if current_user && current_user.physical_tickets.by_conference(conference).any? + = link_to "My Tickets", conference_physical_ticket_index_path(conference.short_title), class: 'btn btn-default' diff --git a/app/views/physical_ticket/index.html.haml b/app/views/physical_ticket/index.html.haml new file mode 100644 index 00000000..ce741c39 --- /dev/null +++ b/app/views/physical_ticket/index.html.haml @@ -0,0 +1,35 @@ +.container + .row + .col-md-12.page-header + %h2 + Tickets + .text-muted + Your tickets for the conference + + .col-md-12 + - if @physical_tickets.present? + %table.table.table-bordered.table-striped.table-hover#roles + %thead + %th ID + %th Type + %th User + %th Actions + %tbody + - @physical_tickets.each do |physical_ticket| + %tr + %td= physical_ticket.id + %td= physical_ticket.ticket.title + %td= physical_ticket.user.name + %td + .btn-group + = link_to 'Show', + conference_physical_ticket_path(@conference.short_title, + physical_ticket.id), + class: 'btn btn-primary' + = link_to 'Generate PDF', + conference_physical_ticket_path(@conference.short_title, + physical_ticket.id, + format: :pdf), + class: 'button btn btn-default btn-info' + - else + %h5 No Tickets found! diff --git a/app/views/physical_ticket/show.html.haml b/app/views/physical_ticket/show.html.haml new file mode 100644 index 00000000..e69de29b diff --git a/config/routes.rb b/config/routes.rb index ccca3511..60b03f54 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -126,6 +126,7 @@ Osem::Application.routes.draw do resources :tickets, only: [:index] resources :ticket_purchases, only: [:create, :destroy] resources :payments, only: [:index, :new, :create] + resources :physical_ticket, only: [:index, :show] resource :subscriptions, only: [:create, :destroy] resource :schedule, only: [:show] do member do diff --git a/db/migrate/20170603095900_create_physical_tickets.rb b/db/migrate/20170603095900_create_physical_tickets.rb new file mode 100644 index 00000000..5e0c1d98 --- /dev/null +++ b/db/migrate/20170603095900_create_physical_tickets.rb @@ -0,0 +1,9 @@ +class CreatePhysicalTickets < ActiveRecord::Migration + def change + create_table :physical_tickets do |t| + t.integer :ticket_purchase_id, null: false + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 547d5858..19a3df19 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170531094819) do +ActiveRecord::Schema.define(version: 20170603095900) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -289,6 +289,12 @@ ActiveRecord::Schema.define(version: 20170531094819) do t.datetime "updated_at", null: false end + create_table "physical_tickets", force: :cascade do |t| + t.integer "ticket_purchase_id", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "programs", force: :cascade do |t| t.integer "conference_id" t.integer "rating", default: 0 diff --git a/spec/features/ticket_purchases_spec.rb b/spec/features/ticket_purchases_spec.rb index f8c755a3..958ae645 100644 --- a/spec/features/ticket_purchases_spec.rb +++ b/spec/features/ticket_purchases_spec.rb @@ -101,12 +101,10 @@ feature Registration do click_button 'Continue' - expect(current_path).to eq(conference_conference_registration_path(conference.short_title)) + expect(current_path).to eq(conference_physical_ticket_index_path(conference.short_title)) purchase = TicketPurchase.where(user_id: participant.id, ticket_id: free_ticket.id).first expect(purchase.quantity).to eq(5) expect(purchase.paid).to be true - - expect(page.has_content?("5 #{free_ticket.title} Tickets for $ 0")).to be true end end diff --git a/spec/models/ticket_purchase_spec.rb b/spec/models/ticket_purchase_spec.rb index 0bb33f8e..f11a8187 100644 --- a/spec/models/ticket_purchase_spec.rb +++ b/spec/models/ticket_purchase_spec.rb @@ -34,7 +34,6 @@ describe TicketPurchase do it 'is valid with a quantity greater than zero' do should allow_value(1).for(:quantity) end - end describe 'self#purchase' do @@ -54,7 +53,6 @@ describe TicketPurchase do expect(TicketPurchase.count).to eq(1) expect(purchase.quantity).to eq(10) expect(message.blank?).to be true - end it 'creates a purchase for one ticket' do @@ -116,4 +114,22 @@ describe TicketPurchase do expect(message.blank?).to be true end end + + describe 'after_create' do + let(:ticket_purchase) { create(:ticket_purchase, quantity: 4, paid: true) } + + it 'creates physical tickets equal to the quantity of purchase' do + expect(ticket_purchase.physical_tickets.count).to eq(4) + end + end + + describe 'after_update' do + let(:ticket_purchase) { create(:ticket_purchase, quantity: 5) } + + it 'creates physical tickets if the payment is made successfully' do + ticket_purchase + ticket_purchase.paid = true + expect{ ticket_purchase.save }.to change{ ticket_purchase.physical_tickets.count }.from(0).to(5) + end + end end