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.
This commit is contained in:
Siddhant Bajaj 2017-06-03 16:05:59 +05:30 committed by siddhantbajaj
parent 1c38b091cc
commit 5c56683ae8
17 changed files with 115 additions and 12 deletions

View file

@ -20,7 +20,7 @@ gem 'responders', '~> 2.0'
# as the database for Active Record # as the database for Active Record
# choose only one # choose only one
gem 'mysql2' gem 'mysql2'
#gem 'pg' # gem 'pg'
# for observing records # for observing records
gem 'rails-observers' gem 'rails-observers'

View file

@ -18,7 +18,7 @@ class PaymentsController < ApplicationController
if @payment.purchase && @payment.save if @payment.purchase && @payment.save
update_purchased_ticket_purchases 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.' notice: 'Thanks! Your ticket is booked successfully.'
else else
@total_amount_to_pay = Ticket.total_price(@conference, current_user, paid: false) @total_amount_to_pay = Ticket.total_price(@conference, current_user, paid: false)
@ -38,6 +38,8 @@ class PaymentsController < ApplicationController
end end
def update_purchased_ticket_purchases 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
end end

View file

@ -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

View file

@ -11,7 +11,7 @@ class TicketPurchasesController < ApplicationController
redirect_to new_conference_payment_path, redirect_to new_conference_payment_path,
notice: 'Please pay here to get tickets.' notice: 'Please pay here to get tickets.'
elsif current_user.ticket_purchases.by_conference(@conference).paid.any? 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.' notice: 'You have free tickets for the conference.'
else else
redirect_to conference_tickets_path(@conference.short_title), redirect_to conference_tickets_path(@conference.short_title),

View file

@ -87,6 +87,7 @@ class Ability
can :index, Ticket can :index, Ticket
can :manage, TicketPurchase, user_id: user.id can :manage, TicketPurchase, user_id: user.id
can [:new, :create], Payment, 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 can [:create, :destroy], Subscription, user_id: user.id

View file

@ -19,6 +19,7 @@ class Conference < ActiveRecord::Base
has_one :email_settings, dependent: :destroy has_one :email_settings, dependent: :destroy
has_one :program, dependent: :destroy has_one :program, dependent: :destroy
has_one :venue, dependent: :destroy has_one :venue, dependent: :destroy
has_many :physical_tickets, through: :ticket_purchases
has_many :ticket_purchases, dependent: :destroy has_many :ticket_purchases, dependent: :destroy
has_many :payments, dependent: :destroy has_many :payments, dependent: :destroy
has_many :supporters, through: :ticket_purchases, source: :user has_many :supporters, through: :ticket_purchases, source: :user

View file

@ -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

View file

@ -13,6 +13,8 @@ class TicketPurchase < ActiveRecord::Base
delegate :price_cents, to: :ticket delegate :price_cents, to: :ticket
delegate :price_currency, to: :ticket delegate :price_currency, to: :ticket
has_many :physical_tickets
scope :paid, -> { where(paid: true) } scope :paid, -> { where(paid: true) }
scope :unpaid, -> { where(paid: false) } scope :unpaid, -> { where(paid: false) }
scope :by_conference, ->(conference) { where(conference_id: conference.id) } scope :by_conference, ->(conference) { where(conference_id: conference.id) }
@ -45,8 +47,8 @@ class TicketPurchase < ActiveRecord::Base
purchase = new(ticket_id: ticket.id, purchase = new(ticket_id: ticket.id,
conference_id: conference.id, conference_id: conference.id,
user_id: user.id, user_id: user.id,
quantity: quantity, quantity: quantity)
paid: ticket.price_cents.zero?) purchase.pay(nil) if ticket.price_cents.zero?
end end
purchase purchase
end end
@ -60,6 +62,13 @@ class TicketPurchase < ActiveRecord::Base
purchase.quantity = quantity if quantity > 0 purchase.quantity = quantity if quantity > 0
purchase purchase
end end
def pay(payment)
update_attributes(paid: true, payment: payment)
PhysicalTicket.transaction do
quantity.times { physical_tickets.create }
end
end
end end
private private

View file

@ -6,6 +6,11 @@ end
class User < ActiveRecord::Base class User < ActiveRecord::Base
rolify 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 :users_roles
has_many :roles, through: :users_roles, dependent: :destroy has_many :roles, through: :users_roles, dependent: :destroy

View file

@ -38,3 +38,5 @@
= link_to 'Subscribe', conference_subscriptions_path(conference.short_title), method: :post, class: 'btn btn-default' = link_to 'Subscribe', conference_subscriptions_path(conference.short_title), method: :post, class: 'btn btn-default'
- else - else
= link_to 'Unsubscribe', conference_subscriptions_path(conference.short_title), method: :delete, class: 'btn btn-default' = 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'

View file

@ -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!

View file

View file

@ -126,6 +126,7 @@ Osem::Application.routes.draw do
resources :tickets, only: [:index] resources :tickets, only: [:index]
resources :ticket_purchases, only: [:create, :destroy] resources :ticket_purchases, only: [:create, :destroy]
resources :payments, only: [:index, :new, :create] resources :payments, only: [:index, :new, :create]
resources :physical_ticket, only: [:index, :show]
resource :subscriptions, only: [:create, :destroy] resource :subscriptions, only: [:create, :destroy]
resource :schedule, only: [:show] do resource :schedule, only: [:show] do
member do member do

View file

@ -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

View file

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # 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 # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -289,6 +289,12 @@ ActiveRecord::Schema.define(version: 20170531094819) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end 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| create_table "programs", force: :cascade do |t|
t.integer "conference_id" t.integer "conference_id"
t.integer "rating", default: 0 t.integer "rating", default: 0

View file

@ -101,12 +101,10 @@ feature Registration do
click_button 'Continue' 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 purchase = TicketPurchase.where(user_id: participant.id, ticket_id: free_ticket.id).first
expect(purchase.quantity).to eq(5) expect(purchase.quantity).to eq(5)
expect(purchase.paid).to be true expect(purchase.paid).to be true
expect(page.has_content?("5 #{free_ticket.title} Tickets for $ 0")).to be true
end end
end end

View file

@ -34,7 +34,6 @@ describe TicketPurchase do
it 'is valid with a quantity greater than zero' do it 'is valid with a quantity greater than zero' do
should allow_value(1).for(:quantity) should allow_value(1).for(:quantity)
end end
end end
describe 'self#purchase' do describe 'self#purchase' do
@ -54,7 +53,6 @@ describe TicketPurchase do
expect(TicketPurchase.count).to eq(1) expect(TicketPurchase.count).to eq(1)
expect(purchase.quantity).to eq(10) expect(purchase.quantity).to eq(10)
expect(message.blank?).to be true expect(message.blank?).to be true
end end
it 'creates a purchase for one ticket' do it 'creates a purchase for one ticket' do
@ -116,4 +114,22 @@ describe TicketPurchase do
expect(message.blank?).to be true expect(message.blank?).to be true
end end
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 end