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.'
end
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}"
end
end

View file

@ -5,7 +5,8 @@ class TicketPurchase < ActiveRecord::Base
belongs_to :payment
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 }
delegate :title, to: :ticket
@ -25,18 +26,21 @@ class TicketPurchase < ActiveRecord::Base
def self.purchase(conference, user, purchases)
errors = []
ActiveRecord::Base.transaction do
conference.tickets.each do |ticket|
quantity = purchases[ticket.id.to_s].to_i
# if the user bought the ticket and is still unpaid, just update the quantity
purchase = if ticket.bought?(user) && ticket.unpaid?(user)
update_quantity(conference, quantity, ticket, user)
else
purchase_ticket(conference, quantity, ticket, user)
end
if purchase && !purchase.save
errors.push(purchase.errors.full_messages)
if count_purchased_registration_tickets(conference, purchases) > 1
errors.push('You cannot buy more than one registration tickets.')
else
ActiveRecord::Base.transaction do
conference.tickets.each do |ticket|
quantity = purchases[ticket.id.to_s].to_i
# if the user bought the ticket and is still unpaid, just update the quantity
purchase = if ticket.bought?(user) && ticket.unpaid?(user)
update_quantity(conference, quantity, ticket, user)
else
purchase_ticket(conference, quantity, ticket, user)
end
if purchase && !purchase.save
errors.push(purchase.errors.full_messages)
end
end
end
end
@ -71,6 +75,18 @@ class TicketPurchase < ActiveRecord::Base
end
Mailbot.ticket_confirmation_mail(self).deliver_later
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
private
@ -79,3 +95,9 @@ def set_week
self.week = created_at.strftime('%W')
save!
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 :ticket_purchases, 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 :voted_events, through: :votes, source: :events
has_many :subscriptions, dependent: :destroy

View file

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

View file

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

View file

@ -14,6 +14,7 @@
%thead
%tr
%th Ticket
%th Registration Ticket
%th Quantity
%th Price
%th Total
@ -21,6 +22,7 @@
- @conference.tickets.each do |ticket|
= render partial: 'ticket', f: f, locals: {ticket: ticket}
%tr
%td
%td
%td
%td.col-sm-1.col-md-1.text-center
@ -46,4 +48,4 @@
.col-md-13
%p.text-muted.text-center
%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
let!(:ticket) { create(:ticket) }
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) }
context 'as a participant' do
@ -106,6 +108,38 @@ feature Registration do
expect(purchase.quantity).to eq(5)
expect(purchase.paid).to be true
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
context 'who is registered' do

View file

@ -34,6 +34,22 @@ describe TicketPurchase do
it 'is valid with a quantity greater than zero' do
should allow_value(1).for(:quantity)
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
describe 'self#purchase' do