One user one registration ticket

A user cannot have more than one registration ticket per conference.
This commit is contained in:
siddhantbajaj 2017-08-12 03:01:36 +05:30
parent de1fa448a2
commit 27bf79996d
8 changed files with 104 additions and 21 deletions

View file

@ -19,7 +19,7 @@ class TicketPurchasesController < ApplicationController
error: 'Please get at least one ticket to continue.' error: 'Please get at least one ticket to continue.'
end end
else else
redirect_to conference_conference_registration_path(@conference.short_title), redirect_to conference_tickets_path(@conference.short_title),
error: "Oops, something went wrong with your purchase! #{message}" error: "Oops, something went wrong with your purchase! #{message}"
end end
end end

View file

@ -5,7 +5,8 @@ class TicketPurchase < ActiveRecord::Base
belongs_to :payment belongs_to :payment
validates :ticket_id, :user_id, :conference_id, :quantity, presence: true validates :ticket_id, :user_id, :conference_id, :quantity, presence: true
validate :one_registration_ticket_per_user
validate :registration_ticket_already_purchased, on: :create
validates :quantity, numericality: { greater_than: 0 } validates :quantity, numericality: { greater_than: 0 }
delegate :title, to: :ticket delegate :title, to: :ticket
@ -25,6 +26,9 @@ class TicketPurchase < ActiveRecord::Base
def self.purchase(conference, user, purchases) def self.purchase(conference, user, purchases)
errors = [] errors = []
if count_purchased_registration_tickets(conference, purchases) > 1
errors.push('You cannot buy more than one registration tickets.')
else
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
conference.tickets.each do |ticket| conference.tickets.each do |ticket|
quantity = purchases[ticket.id.to_s].to_i quantity = purchases[ticket.id.to_s].to_i
@ -34,12 +38,12 @@ class TicketPurchase < ActiveRecord::Base
else else
purchase_ticket(conference, quantity, ticket, user) purchase_ticket(conference, quantity, ticket, user)
end end
if purchase && !purchase.save if purchase && !purchase.save
errors.push(purchase.errors.full_messages) errors.push(purchase.errors.full_messages)
end end
end end
end end
end
errors.join('. ') errors.join('. ')
end end
@ -71,6 +75,18 @@ class TicketPurchase < ActiveRecord::Base
end end
Mailbot.ticket_confirmation_mail(self).deliver_later Mailbot.ticket_confirmation_mail(self).deliver_later
end end
def one_registration_ticket_per_user
if ticket.try(:registration_ticket?) && quantity != 1
errors.add(:quantity, 'cannot be greater than one for registration tickets.')
end
end
def registration_ticket_already_purchased
if ticket.try(:registration_ticket?) && user.tickets.for_registration(conference).present?
errors.add(:quantity, 'cannot be greater than one for registration tickets.')
end
end
end end
private private
@ -79,3 +95,9 @@ def set_week
self.week = created_at.strftime('%W') self.week = created_at.strftime('%W')
save! save!
end end
def count_purchased_registration_tickets(conference, purchases)
conference.tickets.for_registration.inject(0) do |sum, registration_ticket|
sum + purchases[registration_ticket.id.to_s].to_i
end
end

View file

@ -51,7 +51,11 @@ class User < ActiveRecord::Base
has_many :events_registrations, through: :registrations has_many :events_registrations, through: :registrations
has_many :ticket_purchases, dependent: :destroy has_many :ticket_purchases, dependent: :destroy
has_many :payments, dependent: :destroy has_many :payments, dependent: :destroy
has_many :tickets, through: :ticket_purchases, source: :ticket has_many :tickets, through: :ticket_purchases, source: :ticket do
def for_registration conference
where(conference: conference, registration_ticket: true).first
end
end
has_many :votes, dependent: :destroy has_many :votes, dependent: :destroy
has_many :voted_events, through: :votes, source: :events has_many :voted_events, through: :votes, source: :events
has_many :subscriptions, dependent: :destroy has_many :subscriptions, dependent: :destroy

View file

@ -109,7 +109,7 @@
You haven't bought any tickets. You haven't bought any tickets.
= link_to 'Please get some tickets to support us!', conference_tickets_path(@conference.short_title) = link_to 'Please get some tickets to support us!', conference_tickets_path(@conference.short_title)
%p %p
(Your participation won't be valid without getting a ticket) (Your participation won't be valid without getting a registration ticket)
.row .row
.col-md-12 .col-md-12

View file

@ -1,5 +1,5 @@
%tr %tr
%td.col-sm-8.col-md-6 %td.col-sm-8.col-md-4
.media .media
.media-body .media-body
%h4.media-heading %h4.media-heading
@ -7,9 +7,14 @@
%h5.media-heading %h5.media-heading
- unless ticket.description.blank? - unless ticket.description.blank?
= markdown(ticket.description) = markdown(ticket.description)
%td.col-sm-1.col-md-2.text-center
= ticket.registration_ticket? ? 'Yes' : 'No'
%td.col-sm-1.col-md-1 %td.col-sm-1.col-md-1
= text_field_tag("tickets[][#{ticket.id}]", 0, - options = { type: 'number', min: 0, class: "form-control quantity", 'data-id' => ticket.id }
type: 'number', min: 0, class: "form-control quantity", 'data-id' => ticket.id) - if ticket.registration_ticket?
- options[:max] = 1
- options[:disabled] = current_user.tickets.for_registration(ticket.conference).present?
= text_field_tag("tickets[][#{ticket.id}]", 0, options)
%td.col-sm-1.col-md-1.text-center %td.col-sm-1.col-md-1.text-center
= ticket.price.symbol = ticket.price.symbol
%span{id: "price_#{ticket.id}"} %span{id: "price_#{ticket.id}"}

View file

@ -14,6 +14,7 @@
%thead %thead
%tr %tr
%th Ticket %th Ticket
%th Registration Ticket
%th Quantity %th Quantity
%th Price %th Price
%th Total %th Total
@ -21,6 +22,7 @@
- @conference.tickets.each do |ticket| - @conference.tickets.each do |ticket|
= render partial: 'ticket', f: f, locals: {ticket: ticket} = render partial: 'ticket', f: f, locals: {ticket: ticket}
%tr %tr
%td
%td %td
%td %td
%td.col-sm-1.col-md-1.text-center %td.col-sm-1.col-md-1.text-center
@ -46,4 +48,4 @@
.col-md-13 .col-md-13
%p.text-muted.text-center %p.text-muted.text-center
%small %small
* Getting a ticket is mandatory. Your participation will not be valid until you get a ticket. * Getting a registration ticket is mandatory. Your participation will not be valid until you get a registration ticket.

View file

@ -3,7 +3,9 @@ require 'spec_helper'
feature Registration do feature Registration do
let!(:ticket) { create(:ticket) } let!(:ticket) { create(:ticket) }
let!(:free_ticket) { create(:ticket, price_cents: 0) } let!(:free_ticket) { create(:ticket, price_cents: 0) }
let!(:conference) { create(:conference, title: 'ExampleCon', tickets: [ticket, free_ticket], registration_period: create(:registration_period, start_date: 3.days.ago)) } let!(:first_registration_ticket) { create(:registration_ticket, price_cents: 0) }
let!(:second_registration_ticket) { create(:registration_ticket, price_cents: 0) }
let!(:conference) { create(:conference, title: 'ExampleCon', tickets: [ticket, free_ticket, first_registration_ticket, second_registration_ticket], registration_period: create(:registration_period, start_date: 3.days.ago)) }
let!(:participant) { create(:user) } let!(:participant) { create(:user) }
context 'as a participant' do context 'as a participant' do
@ -106,6 +108,38 @@ feature Registration do
expect(purchase.quantity).to eq(5) expect(purchase.quantity).to eq(5)
expect(purchase.paid).to be true expect(purchase.paid).to be true
end end
scenario 'purchases more than one registration tickets of a single type' do
visit root_path
click_link 'Register'
expect(current_path).to eq(new_conference_conference_registration_path(conference.short_title))
click_button 'Register'
fill_in "tickets__#{first_registration_ticket.id}", with: '5'
expect(current_path).to eq(conference_tickets_path(conference.short_title))
click_button 'Continue'
expect(current_path).to eq(conference_tickets_path(conference.short_title))
end
scenario 'purchases one registration ticket of a different types' do
visit root_path
click_link 'Register'
expect(current_path).to eq(new_conference_conference_registration_path(conference.short_title))
click_button 'Register'
fill_in "tickets__#{first_registration_ticket.id}", with: '1'
fill_in "tickets__#{second_registration_ticket.id}", with: '1'
expect(current_path).to eq(conference_tickets_path(conference.short_title))
click_button 'Continue'
expect(flash).to eq('Oops, something went wrong with your purchase! You cannot buy more than one registration tickets.')
expect(current_path).to eq(conference_tickets_path(conference.short_title))
end
end end
context 'who is registered' do context 'who is registered' do

View file

@ -34,6 +34,22 @@ 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
describe 'one_registration_ticket_per_user' do
let(:registration_ticket) { create(:registration_ticket) }
let(:ticket_purchase) { build(:ticket_purchase, ticket: registration_ticket, quantity: 1) }
it 'it is valid, if quantity for registration tickets is less than or equal to one' do
expect(ticket_purchase.valid?).to eq true
end
it 'it is not valid, if quantity for registration tickets is greater than to one' do
ticket_purchase.quantity = 4
expect(ticket_purchase.valid?).to eq false
expect(ticket_purchase.errors[:quantity]).to eq ['cannot be greater than one for registration tickets.']
end
end
end end
describe 'self#purchase' do describe 'self#purchase' do