# 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 - **Promoter System**: Professional accounts can create and manage events with Stripe integration #### 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 - **Payout Management**: Event-level payout tracking and status management #### 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 - **Order System** (`app/models/order.rb`): Groups tickets into orders with payment status tracking #### 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 #### 5. Financial System - **Earnings** (`app/models/earning.rb`): Tracks revenue from paid orders, excluding refunded tickets - **Payouts** (`app/models/payout.rb`): Manages promoter payout requests and processing - **Platform Fees**: €0.50 fixed fee + 1.5% of ticket price, per ticket ### 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), is_professionnal boolean DEFAULT false, -- Professional account flag stripe_connected_account_id varchar(255), -- Stripe Connect account for payouts -- 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 payout_status integer, -- enum: not_requested=0, requested=1, processing=2, completed=3, failed=4 payout_requested_at datetime, 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 ); -- Orders group tickets and track payment status CREATE TABLE orders ( id bigint PRIMARY KEY, user_id bigint REFERENCES users(id), event_id bigint REFERENCES events(id), status varchar(255) DEFAULT 'draft', -- draft, pending_payment, paid, completed, cancelled, expired total_amount_cents integer DEFAULT 0, payment_attempts integer DEFAULT 0, expires_at datetime, last_payment_attempt_at datetime ); -- Individual tickets with QR codes CREATE TABLE tickets ( id bigint PRIMARY KEY, order_id bigint REFERENCES orders(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', -- draft, active, used, expired, refunded first_name varchar(255), last_name varchar(255) ); -- Earnings track revenue from paid orders CREATE TABLE earnings ( id bigint PRIMARY KEY, event_id bigint REFERENCES events(id), user_id bigint REFERENCES users(id), order_id bigint REFERENCES orders(id), amount_cents integer, -- Promoter payout amount (after fees) fee_cents integer, -- Platform fees status integer DEFAULT 0, -- enum: pending=0, paid=1 stripe_payout_id varchar(255) ); -- Payouts track promoter payout requests CREATE TABLE payouts ( id bigint PRIMARY KEY, user_id bigint REFERENCES users(id), event_id bigint REFERENCES events(id), amount_cents integer NOT NULL, -- Gross amount fee_cents integer NOT NULL DEFAULT 0, -- Platform fees status integer DEFAULT 0, -- enum: pending=0, processing=1, completed=2, failed=3 stripe_payout_id varchar(255), total_orders_count integer DEFAULT 0, refunded_orders_count integer DEFAULT 0 ); ``` ## 🎯 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 5. **Earnings Creation**: Automatically creates earnings records for promoter payout tracking ### 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 ## 🔄 Application Workflows ### 1. User Registration & Onboarding 1. User registers with email/password 2. Completes onboarding process to set up profile 3. Can browse and purchase tickets as a customer ### 2. Promoter Account Setup 1. User requests professional account status 2. Connects Stripe account for payment processing 3. Can create and manage events ### 3. Event Creation & Management 1. Promoter creates event in draft state 2. Adds ticket types with pricing and quantities 3. Publishes event to make it publicly available 4. Manages event status (publish/unpublish/cancel) ### 4. Ticket Purchase Flow 1. User adds tickets to cart 2. Proceeds to checkout with Stripe 3. Payment processing through Stripe 4. Order and ticket creation upon successful payment 5. Email confirmation sent to user 6. Automatic earnings record creation for promoter ### 5. Financial Workflows #### Platform Fee Structure - **Fixed Fee**: €0.50 per ticket - **Percentage Fee**: 1.5% of ticket price per ticket - **Calculation Example**: - 1 ticket at €20.00: €0.50 + (€20.00 × 1.5%) = €0.50 + €0.30 = €0.80 total fees - 3 tickets at €25.00 each: (3 × €0.50) + (3 × €25.00 × 1.5%) = €1.50 + €1.13 = €2.63 total fees #### Earnings Tracking 1. When order is marked as paid, earnings record is automatically created 2. Earnings amount = Total ticket sales - Platform fees 3. Only non-refunded tickets are counted in earnings 4. Earnings remain in "pending" status until payout is requested #### Payout Request Process 1. Event ends (current time >= event end_time) 2. Promoter requests payout through event management interface 3. System calculates total earnings for the event (excluding refunded tickets) 4. Creates payout record with gross amount, fees, and net amount 5. Updates event payout status to "requested" 6. Admin processes payout through Stripe 7. Payout status updated to "processing" then "completed" or "failed" ### 6. Refund Management 1. Tickets can be marked as refunded 2. Refunded tickets are excluded from earnings calculations 3. Promoters do not receive payouts for refunded tickets ## 🔧 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); CREATE INDEX idx_orders_event_status ON orders (event_id, status); CREATE INDEX idx_earnings_event_status ON earnings (event_id, status); ``` ### 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 - **Authorization**: Proper access controls for promoter vs customer actions ## 🧪 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 6. **Financial Workflows**: Fee calculations, payout processing, refund handling ### Seed Data Structure ```ruby # Creates test users, events, and ticket types users = User.create!([...]) events = Event.create!([...]) ticket_types = TicketType.create!([...]) ``` ## 🛠️ Available Development Tools ### AST-Grep for Mass Code Replacement The system has `ast-grep` installed for structural code search and replacement. This tool is particularly useful for: - **Mass refactoring**: Rename methods, classes, or variables across the codebase - **Pattern-based replacements**: Update code patterns using AST matching - **Language-aware transformations**: Safer than regex for code modifications #### Usage Examples: ```bash # Find all method calls to a specific method ast-grep --pattern 'find_by_$FIELD($VALUE)' --lang ruby # Replace method calls with new syntax ast-grep --pattern 'find_by_$FIELD($VALUE)' --rewrite 'find_by($FIELD: $VALUE)' --lang ruby # Search for specific Rails patterns ast-grep --pattern 'validates :$FIELD, presence: true' --lang ruby # Mass rename across multiple files ast-grep --pattern 'old_method_name($$ARGS)' --rewrite 'new_method_name($$ARGS)' --lang ruby --update-all ``` #### Best Practices: - Always run with `--dry-run` first to preview changes - Use `--lang ruby` for Ruby files to ensure proper AST parsing - Test changes in a branch before applying to main codebase - Particularly useful for Rails conventions and ActiveRecord pattern updates ## 📝 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 - **Mass Changes**: Use `ast-grep` for structural code replacements instead of simple find/replace This architecture provides a solid foundation for a scalable ticket selling platform with proper separation of concerns, security, and user experience.