# Aperonight - Technical Documentation for AI Agents ## 🤖 Agent Implementation Guide This document provides technical details for AI agents working on the Aperonight ticket selling system. ## 🏗️ System Architecture ### Core Components #### 1. User Management (`app/models/user.rb`) - **Devise Integration**: Complete authentication system with registration, login, password reset - **Relationships**: Users can create events and purchase tickets - **Validations**: Email format, password strength, optional name fields #### 2. Event System (`app/models/event.rb`) - **States**: `draft`, `published`, `canceled`, `sold_out` with enum management - **Geographic Data**: Latitude/longitude for venue mapping - **Relationships**: Belongs to user, has many ticket types and tickets through ticket types - **Scopes**: Featured events, published events, upcoming events with proper ordering #### 3. Ticket Management - **TicketType** (`app/models/ticket_type.rb`): Defines ticket categories with pricing, quantity, sale periods - **Ticket** (`app/models/ticket.rb`): Individual tickets with unique QR codes, status tracking, price storage #### 4. Payment Processing (`app/controllers/events_controller.rb`) - **Stripe Integration**: Complete checkout session creation and payment confirmation - **Session Management**: Proper handling of payment success/failure with ticket generation - **Security**: Authentication required, cart validation, availability checking ### Database Schema Key Points ```sql -- Users table (managed by Devise) CREATE TABLE users ( id bigint PRIMARY KEY, email varchar(255) UNIQUE NOT NULL, encrypted_password varchar(255) NOT NULL, first_name varchar(255), last_name varchar(255), -- Devise fields: confirmation, reset tokens, etc. ); -- Events table CREATE TABLE events ( id bigint PRIMARY KEY, user_id bigint REFERENCES users(id), name varchar(100) NOT NULL, slug varchar(100) NOT NULL, description text(1000) NOT NULL, venue_name varchar(100) NOT NULL, venue_address varchar(200) NOT NULL, latitude decimal(10,8) NOT NULL, longitude decimal(11,8) NOT NULL, start_time datetime NOT NULL, end_time datetime, state integer DEFAULT 0, -- enum: draft=0, published=1, canceled=2, sold_out=3 featured boolean DEFAULT false, image varchar(500) ); -- Ticket types define pricing and availability CREATE TABLE ticket_types ( id bigint PRIMARY KEY, event_id bigint REFERENCES events(id), name varchar(255) NOT NULL, description text, price_cents integer NOT NULL, quantity integer NOT NULL, sale_start_at datetime, sale_end_at datetime, requires_id boolean DEFAULT false, minimum_age integer ); -- Individual tickets with QR codes CREATE TABLE tickets ( id bigint PRIMARY KEY, user_id bigint REFERENCES users(id), ticket_type_id bigint REFERENCES ticket_types(id), qr_code varchar(255) UNIQUE NOT NULL, price_cents integer NOT NULL, status varchar(255) DEFAULT 'active' -- active, used, expired, refunded ); ``` ## 🎯 Key Implementation Details ### 1. Dashboard Metrics (`app/controllers/pages_controller.rb`) ```ruby # User-specific metrics with optimized queries @booked_events = current_user.tickets .joins(:ticket_type, :event) .where(events: { state: :published }) .count # Event counts for different timeframes @events_today = Event.published .where("DATE(start_time) = ?", Date.current) .count # User's actual booked events (not just count) @user_booked_events = Event.joins(ticket_types: :tickets) .where(tickets: { user: current_user, status: 'active' }) .distinct .limit(5) ``` ### 2. Stripe Payment Flow #### Checkout Initiation (`events#checkout`) 1. **Cart Validation**: Parse JSON cart data, validate ticket types and quantities 2. **Availability Check**: Ensure sufficient tickets available before payment 3. **Stripe Session**: Create checkout session with line items, success/cancel URLs 4. **Metadata Storage**: Store order details in Stripe session metadata for later retrieval ```ruby # Key Stripe configuration session = Stripe::Checkout::Session.create({ payment_method_types: ['card'], line_items: line_items, mode: 'payment', success_url: payment_success_url(event_id: @event.id, session_id: '{CHECKOUT_SESSION_ID}'), cancel_url: event_url(@event.slug, @event), customer_email: current_user.email, metadata: { event_id: @event.id, user_id: current_user.id, order_items: order_items.to_json } }) ``` #### Payment Confirmation (`events#payment_success`) 1. **Session Retrieval**: Get Stripe session with payment status 2. **Ticket Creation**: Generate tickets based on order items from metadata 3. **QR Code Generation**: Automatic unique QR code creation via model callbacks 4. **Success Page**: Display tickets with download links ### 3. PDF Ticket Generation (`app/services/ticket_pdf_generator.rb`) ```ruby class TicketPdfGenerator def generate Prawn::Document.new(page_size: [350, 600], margin: 20) do |pdf| # Header with branding pdf.fill_color "2D1B69" pdf.font "Helvetica", style: :bold, size: 24 pdf.text "ApéroNight", align: :center # Event details pdf.text ticket.event.name, align: :center # QR Code generation qr_code_data = { ticket_id: ticket.id, qr_code: ticket.qr_code, event_id: ticket.event.id, user_id: ticket.user.id }.to_json qrcode = RQRCode::QRCode.new(qr_code_data) pdf.print_qr_code(qrcode, extent: 120, align: :center) end.render end end ``` ### 4. Frontend Cart Management (`app/javascript/controllers/ticket_cart_controller.js`) - **Stimulus Controller**: Manages cart state and interactions - **Authentication Check**: Validates user login before checkout - **Session Storage**: Preserves cart when redirecting to login - **Dynamic Updates**: Real-time cart total and ticket count updates ## 🔧 Development Patterns ### Model Validations ```ruby # Event validations validates :name, presence: true, length: { minimum: 3, maximum: 100 } validates :latitude, numericality: { greater_than_or_equal_to: -90, less_than_or_equal_to: 90 } # Ticket QR code generation before_validation :generate_qr_code, on: :create def generate_qr_code loop do self.qr_code = SecureRandom.uuid break unless Ticket.exists?(qr_code: qr_code) end end ``` ### Controller Patterns ```ruby # Authentication for sensitive actions before_action :authenticate_user!, only: [:checkout, :payment_success, :download_ticket] # Strong parameters private def event_params params.require(:event).permit(:name, :description, :venue_name, :venue_address, :latitude, :longitude, :start_time, :image) end ``` ### View Helpers and Partials - **Metric Cards**: Reusable component for dashboard statistics - **Event Items**: Consistent event display across pages - **Flash Messages**: Centralized notification system ## 🚀 Deployment Considerations ### Environment Variables ```bash # Required for production STRIPE_PUBLISHABLE_KEY=pk_live_... STRIPE_SECRET_KEY=sk_live_... STRIPE_WEBHOOK_SECRET=whsec_... DATABASE_URL=mysql2://user:pass@host/db RAILS_MASTER_KEY=... ``` ### Database Indexes ```sql -- Performance indexes for common queries CREATE INDEX idx_events_published_start_time ON events (state, start_time); CREATE INDEX idx_tickets_user_status ON tickets (user_id, status); CREATE INDEX idx_ticket_types_event ON ticket_types (event_id); ``` ### Security Considerations - **CSRF Protection**: Rails default protection enabled - **Strong Parameters**: All user inputs filtered - **Authentication**: Devise handles session security - **Payment Security**: Stripe handles sensitive payment data ## 🧪 Testing Strategy ### Key Test Cases 1. **User Authentication**: Registration, login, logout flows 2. **Event Creation**: Validation, state management, relationships 3. **Booking Process**: Cart validation, payment processing, ticket generation 4. **PDF Generation**: QR code uniqueness, ticket format 5. **Dashboard Metrics**: Query accuracy, performance ### Seed Data Structure ```ruby # Creates test users, events, and ticket types users = User.create!([...]) events = Event.create!([...]) ticket_types = TicketType.create!([...]) ``` ## 📝 Code Style & Conventions - **Ruby Style**: Follow Rails conventions and Rubocop rules - **Database**: Use Rails migrations for all schema changes - **JavaScript**: Stimulus controllers for interactive behavior - **CSS**: Tailwind utility classes with custom components - **Documentation**: Inline comments for complex business logic This architecture provides a solid foundation for a scalable ticket selling platform with proper separation of concerns, security, and user experience.