# Aperonight - Technical Architecture ## Overview Aperonight is a Ruby on Rails web application designed for proposing night parties in Paris and allowing event makers to create their own events. The application serves two primary user groups: ### For Customers: - View upcoming and past parties - Book tickets with customizable bundles (simple entry, VIP, group passes, etc.) - Complete secure payments via credit card, PayPal, or bank transfer - Access mobile-friendly interface for ticket management - Receive unique, scannable tickets (QR codes) ### For Promoters: - Create and schedule parties - Define custom ticket bundles and pricing - Aggregate events from external platforms (Shogun, Bizouk, Weezevent) - Scan tickets at events using mobile devices ## Technical Architecture ### 1. Database Schema ```ruby # User - Handles both customers and promoters create_table :users do |t| t.string :email t.string :password_digest t.string :role # customer or promoter t.timestamps end # Event - Events created by promoters create_table :events do |t| t.string :name t.text :description t.datetime :start_time t.datetime :end_time t.string :location t.integer :promoter_id t.timestamps end # TicketType - Customizable bundles defined by promoters create_table :ticket_types do |t| t.string :name t.text :description t.decimal :price t.integer :event_id t.timestamps end # Ticket - Individual ticket instances purchased by customers create_table :tickets do |t| t.string :uuid t.string :qr_code t.integer :event_id t.integer :user_id t.integer :ticket_type_id t.boolean :used, default: false t.timestamps end # Payment - Transaction records for ticket purchases create_table :payments do |t| t.string :payment_method # credit_card, paypal, bank_account t.string :transaction_id t.integer :user_id t.integer :ticket_id t.decimal :amount t.timestamps end ``` ### 2. Core Models ```ruby class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :tickets has_many :payments has_many :parties, foreign_key: 'promoter_id' end class Event < ApplicationRecord belongs_to :promoter, class_name: 'User' has_many :tickets has_many :ticket_types end class TicketType < ApplicationRecord belongs_to :event has_many :tickets end class Ticket < ApplicationRecord belongs_to :event belongs_to :user belongs_to :ticket_type has_one :payment before_create :generate_uuid_and_qr_code private def generate_uuid_and_qr_code self.uuid = SecureRandom.uuid self.qr_code = RQRCode::QRCode.new(self.uuid).as_svg end end class Payment < ApplicationRecord belongs_to :user belongs_to :ticket enum payment_method: { credit_card: 'credit_card', paypal: 'paypal', bank_account: 'bank_account' } after_create :process_payment private def process_payment case self.payment_method when 'credit_card' process_stripe_payment when 'paypal' process_paypal_payment when 'bank_account' process_bank_account_payment end end end ``` ### 3. Key Controllers #### Parties Controller ```ruby class PartiesController < ApplicationController before_action :authenticate_user! before_action :set_event, only: [:show, :edit, :update, :destroy] def index @parties = Event.all end def show @ticket_types = @event.ticket_types end def new @event = Event.new @event.ticket_types.build end def create @event = current_user.parties.build(event_params) if @event.save redirect_to @event, notice: 'Event was successfully created.' else render :new end end private def set_event @event = Event.find(params[:id]) end def event_params params.require(:event).permit( :name, :description, :start_time, :end_time, :location, ticket_types_attributes: [:id, :name, :description, :price, :_destroy] ) end end ``` #### Tickets Controller ```ruby class TicketsController < ApplicationController before_action :authenticate_user! before_action :set_event, only: [:new, :create] def new @ticket = Ticket.new end def create @ticket = current_user.tickets.build(ticket_params) if @ticket.save redirect_to @ticket, notice: 'Ticket was successfully booked.' else render :new end end def scan end def validate qr_code = params[:qr_code] ticket = Ticket.find_by(qr_code: qr_code) if ticket && !ticket.used ticket.update(used: true) render json: { valid: true } else render json: { valid: false } end end private def set_event @event = Event.find(params[:event_id]) end def ticket_params params.require(:ticket).permit(:ticket_type_id, :event_id) end end ``` ### 4. Payment Integration #### Stripe Configuration ```ruby # config/initializers/stripe.rb Rails.configuration.stripe = { publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'], secret_key: ENV['STRIPE_SECRET_KEY'] } Stripe.api_key = Rails.configuration.stripe[:secret_key] ``` #### PayPal Configuration ```ruby # config/initializers/paypal.rb PayPal::SDK.configure({ mode: ENV['PAYPAL_MODE'], # 'sandbox' or 'live' client_id: ENV['PAYPAL_CLIENT_ID'], client_secret: ENV['PAYPAL_CLIENT_SECRET'] }) ``` ### 5. Frontend Considerations #### Mobile Ticket Scanning ```erb Scan Ticket

Scan Ticket

``` ### 6. Routes Configuration ```ruby # config/routes.rb Rails.application.routes.draw do devise_for :users resources :parties do resources :ticket_types, only: [:new, :create, :edit, :update, :destroy] end resources :ticket_types, only: [:index, :show] resources :tickets do resources :payments, only: [:new, :create] collection do post 'validate' end end get 'paypal_success', to: 'payments#paypal_success' get 'paypal_cancel', to: 'payments#paypal_cancel' get 'tickets/scan', to: 'tickets#scan' root 'parties#index' end ``` ## Implementation Recommendations ### Authentication & Authorization - Use Devise for user authentication - Implement Pundit or CanCanCan for role-based access control - Distinguish clearly between customer and promoter permissions ### Payment Processing - Integrate Stripe for credit card payments - Add PayPal support through official SDK - Consider Plaid for bank account integration ### Performance & Scalability - Implement Redis for caching frequently accessed data - Use CDN for static assets (images, CSS, JS) - Employ background job processing (Sidekiq) for emails and payments - Optimize database queries with proper indexing ### Security Considerations - Validate all user inputs - Sanitize HTML output to prevent XSS - Secure payment processing with PCI compliance - Implement rate limiting for API endpoints - Regular security audits and dependency updates