This document explains how Eventickat calculates ticket prices using a reverse pricing model where organizers specify what they want to receive, and the system calculates what customers will pay.
Organizer sets: Price = 50,000 MMK
Platform deducts: Fees & taxes
Organizer receives: 50,000 - fees = ??? (unknown until after)
Problem: Organizer doesn't know their actual payout until after fees are deducted.
Organizer sets: Payout = 50,000 MMK (what they want to receive)
System calculates: Price = 56,952 MMK (what customer pays)
Platform guarantees: Organizer receives exactly 50,000 MMK
Benefit: Organizer knows their exact revenue upfront. All fees are added on top.
-
Transparency for Organizers
- They know exactly what they'll earn
- No surprises after fees are deducted
- Easier financial planning
-
Simplicity for Customers
- They see one final price
- No separate fee line items
- Clean checkout experience
-
Platform Control
- Platform controls commission structure
- Can adjust fees without affecting organizer revenue
- Clear audit trail
Every ticket price is composed of exactly four components:
What: Money the organizer receives
Set by: Event organizer
Example: 50,000 MMK
What: Commission the platform earns
Based on: Payout amount (not final price)
Calculation: Percentage or fixed amount
Storage: Percentage stored as number (5 = 5%)
Example: 5% of 50,000 = 2,500 MMK
What: Government tax (e.g., VAT, commercial tax)
Based on: Final price (creates circular dependency)
Calculation: Percentage of final price
Example: 5% of final price
What: Payment gateway processing fee
Based on: Final price (creates circular dependency)
Calculation: Percentage + fixed amount
Storage: Rate stored as decimal (0.025 = 2.5%)
Example: 2.5% of final price
Platform Fee (platform_fee_rules table):
- Stored as percentage:
fee_value = 5means 5% - Must divide by 100 in calculation
Payment Fee & Tax (settings table):
- Stored as decimal:
rate = 0.05means 5% - Use directly in calculation (no division)
Why different?
- Platform fee rules are admin-managed (easier to input as 5 vs 0.05)
- Payment/tax settings are JSON config (standard decimal format)
We need to calculate:
price = payout_amount + platform_fee + tax_amount + payment_fee
But BOTH tax_amount and payment_fee depend on price:
tax_amount = price × tax_rate
payment_fee = (price × payment_rate) + payment_fixed
This creates TWO circular references:
tax_amount needs price
payment_fee needs price
price needs both tax_amount and payment_fee
We solve for price algebraically:
Let P = final price
Given:
- tax_amount = P × tax_rate (rate is decimal: 0.05 = 5%)
- payment_fee = (P × payment_rate) + payment_fixed (rate is decimal: 0.025 = 2.5%)
- P = payout_amount + platform_fee + tax_amount + payment_fee
Substitute:
P = payout_amount + platform_fee + (P × tax_rate) + (P × payment_rate) + payment_fixed
Rearrange:
P - (P × tax_rate) - (P × payment_rate) = payout_amount + platform_fee + payment_fixed
P × (1 - tax_rate - payment_rate) = base
Therefore:
P = base / (1 - tax_rate - payment_rate)
Where:
base = payout_amount + platform_fee + payment_fixed
Important: Rates are stored as decimals (0.05 = 5%), not percentages (5).
MMK (Myanmar Kyat) has no decimal subdivisions:
- ✓ Valid: 56,757 MMK
- ✗ Invalid: 56,757.50 MMK (no 0.50 Kyat exists)
All monetary values must be integers for:
- Legal compliance (currency regulations)
- Payment gateway compatibility
- Customer clarity (no confusing decimals)
Step 1: Calculate Price (Round Up)
price = ceil(base / (1 - tax_rate - payment_rate))Why ceil? Ensures customer pays enough to cover all fees. Better to round up 1 MMK than undercharge.
Step 2: Calculate Individual Fees
platform_fee = round(payout_amount × platform_fee_rate / 100)
tax_amount = round(price × tax_rate)
payment_fee_calculated = round(price × payment_rate + payment_fixed)Step 3: Absorb Rounding Difference
payment_fee = price - payout_amount - platform_fee - tax_amountWhy absorb in payment_fee?
- Payout amount: Fixed (organizer expectation)
- Platform fee: Fixed (business rule)
- Tax amount: Legal requirement (must be accurate)
- Payment fee: Variable (can absorb 1-2 MMK differences)
Mathematical Guarantee:
price = payout_amount + platform_fee + payment_fee + tax_amount
Always true, enforced by code:
if ($sum !== $price) {
throw new Exception("Fee breakdown sum doesn't match price");
}Benefits for Auditing:
- Database queries can validate sum = price
- No rounding discrepancies
- Clean financial reports
- Transparent fee breakdown
Organizer creates event ticket and sets:
- Payout amount: 50,000 MMK
System looks up applicable platform fee rule based on:
- Event-specific rule (highest priority)
- Organizer-specific rule (medium priority)
- Default rule (fallback)
Calculation:
- Rule: 5% PERCENTAGE
- Platform fee = 50,000 × 0.05 = 2,500 MMK
System retrieves tax configuration:
- Tax type: VAT
- Tax rate: 0.05 (5% as decimal)
- Applies to: Final price
Note: Tax will be calculated from final price (see Step 4)
System retrieves payment fee settings for payment method:
- Payment method: VISA
- Payment rate: 0.025 (2.5% as decimal)
- Payment fixed: 0 MMK
Calculation:
base = payout_amount + platform_fee + payment_fixed
base = 50,000 + 2,500 + 0
base = 52,500 MMK
price = ceil(base / (1 - tax_rate - payment_rate))
price = ceil(52,500 / (1 - 0.05 - 0.025))
price = ceil(52,500 / 0.925)
price = ceil(56,756.76)
price = 56,757 MMK (integer)
Now calculate tax and payment fee from the final price:
tax_amount = round(price × tax_rate)
tax_amount = round(56,757 × 0.05)
tax_amount = round(2,837.85)
tax_amount = 2,838 MMK (integer)
payment_fee_calculated = round(price × payment_rate + payment_fixed)
payment_fee_calculated = round(56,757 × 0.025 + 0)
payment_fee_calculated = round(1,418.925)
payment_fee_calculated = 1,419 MMK (initial)
Adjust payment_fee to ensure exact sum:
payment_fee = price - payout_amount - platform_fee - tax_amount
payment_fee = 56,757 - 50,000 - 2,500 - 2,838
payment_fee = 1,419 MMK (final, exact)
Verification:
50,000 + 2,500 + 1,419 + 2,838 = 56,757 ✓ (exact match)
Customer pays: 56,757 MMK (integer, no decimals)
Let's verify the math adds up:
Component Amount (MMK)
────────────────────────────────
Payout amount 50,000 ← Organizer receives
Platform fee 2,500 ← Platform earns
Payment fee 1,419 ← Gateway charges
Tax amount 2,838 ← Tax authority
────────────────────────────────
Total Price 56,757 ← Customer pays ✓
Verification:
- Customer pays: 56,757
- Organizer gets: 50,000
- Platform + fees + tax: 6,757
- Math checks out ✓
Timing: When organizer creates ticket
Input: Payout amount (50,000 MMK)
Output: Calculated price (56,757 MMK)
Purpose: Show organizer what customers will pay
Stored in: event_tickets table (payout_amount, price)
Timing: When customer completes payment
Input: Payout amount from event_tickets
Output: Recalculated fee breakdown
Purpose: Create immutable pricing snapshot
Stored in: purchase_tickets table (all fee components)
Why recalculate?
- Platform fee rules may have changed
- Payment method affects payment fee
- Creates audit trail
- Ensures accuracy at point of sale
Payout amount: 0
All fees: 0
Final price: 0
Logic: No fees apply to free tickets
Two approaches:
- Normal payout: 50,000 MMK → Price: 56,952 MMK
- Early bird payout: 40,000 MMK → Early price: 45,562 MMK
- Organizer receives different amounts
- Payout stays: 50,000 MMK
- Early price: 45,000 MMK (promotional loss)
- Organizer still receives 50,000 MMK
- Platform absorbs difference
Current Implementation: Approach A (separate early_price field)
Different payment methods have different fees:
- AYAPAY: 0% + 0 MMK
- VISA: 2.5% + 0 MMK
- KPAY: 0% + 0 MMK
- PAYPAL: 5% + 0 MMK
Challenge: Should ticket price vary by payment method?
AYAPAY selected: Price = 56,000 MMK
VISA selected: Price = 57,200 MMK
Problem: Customer sees price change, causes confusion.
Organizer selects accepted payment methods and system uses highest fee rate:
Event Settings:
Accepted Methods: VISA, KPAY, AYAPAY
Highest Fee: VISA (2.5%)
Payment Fee Override Rate: 0.025
Payment Fee Override Fixed: 0
Result:
Price shown: 57,200 MMK (calculated with 2.5%)
VISA selected: 57,200 MMK ✓
KPAY selected: 57,200 MMK ✓ (customer pays same, platform absorbs difference)
Benefits:
- Consistent price displayed
- No checkout surprises
- Platform can incentivize lower-fee methods
- Industry standard practice (Eventbrite, Ticketmaster)
Storage: platform_fee_rules table
Scope: Default / Organizer-specific / Event-specific
Type: PERCENTAGE or FIXED
Time-based: Uses effective_from and effective_to
Priority:
- Event-specific rule (if exists)
- Organizer-specific rule (if exists)
- Default rule (fallback)
Storage: settings table (key: payment_fee_rules)
Format: JSON with fee per payment method
Structure: {percent: X, fixed: Y} per method
Storage: settings table (key: tax_rules)
Format: JSON with tax configuration
Fields:
- Country code
- Currency
- Tax type (VAT, commercial tax, etc.)
- Tax rate (decimal)
- Applies to (TICKET / PLATFORM_FEE / BOTH)
When a customer purchases a ticket, we store a complete snapshot:
payout_amount- What organizer receives (integer)platform_fee- Platform commission (integer, calculated once)payment_fee- Gateway fee (integer, calculated once)tax_amount- Tax collected (integer, calculated once)price- What customer paid (integer)net_amount- Total amount charged (integer, same as price)currency- Currency code
Problem with recalculation:
- Platform fee rules may have changed
- Tax rates may have changed
- Payment fee settings may have changed
- Creates audit nightmare
- Breaks financial promises
Solution:
- Calculate once at purchase time
- Store complete breakdown (all integers)
- Settlement only aggregates stored values
- Historical accuracy guaranteed
Verify Fee Breakdown Sums Match Price:
-- Should return 0 rows (all tickets valid)
SELECT
id,
price,
(payout_amount + platform_fee + payment_fee + tax_amount) as calculated_sum,
(price - (payout_amount + platform_fee + payment_fee + tax_amount)) as difference
FROM purchase_tickets
WHERE price != (payout_amount + platform_fee + payment_fee + tax_amount);Verify No Decimal Values:
-- Should return 0 rows (all integers)
SELECT id, price, platform_fee, payment_fee, tax_amount
FROM purchase_tickets
WHERE price != FLOOR(price)
OR platform_fee != FLOOR(platform_fee)
OR payment_fee != FLOOR(payment_fee)
OR tax_amount != FLOOR(tax_amount);Monthly Revenue Breakdown:
SELECT
DATE_FORMAT(created_at, '%Y-%m') as month,
COUNT(*) as tickets_sold,
SUM(price) as total_revenue,
SUM(payout_amount) as organizer_payouts,
SUM(platform_fee) as platform_revenue,
SUM(payment_fee) as payment_fees,
SUM(tax_amount) as taxes_collected
FROM purchase_tickets
GROUP BY DATE_FORMAT(created_at, '%Y-%m')
ORDER BY month DESC;Customer Payment (56,952 MMK)
↓
├─→ Payout to Organizer (50,000 MMK)
├─→ Platform Commission (2,500 MMK)
├─→ Payment Gateway (1,652 MMK)
└─→ Tax Authority (2,500 MMK)
Platform collects from gateway: 56,952 MMK
Platform pays to organizer: 50,000 MMK
Platform keeps: 2,500 MMK (commission)
Platform forwards to tax authority: 2,500 MMK
Payment gateway already kept: 1,652 MMK (deducted at payment time)
On Event Page:
VIP Ticket
Price: 56,952 MMK
At Checkout:
VIP Ticket × 1
Total: 56,952 MMK
Payment Method: [Select ▼]
After Payment:
Receipt
VIP Ticket: 56,952 MMK
Total Paid: 56,952 MMK
- Platform fee breakdown
- Payment processing fee
- Tax calculation details
- Organizer payout amount
Why hidden?
- Cleaner user experience
- Reduces confusion
- Industry standard practice
- Single price is easier to understand
When creating ticket:
Ticket Name: VIP Pass
Payout Amount: 50,000 MMK ← You set this
System shows:
Customer Price: 56,952 MMK ← System calculated
Your Payout: 50,000 MMK ← Guaranteed
Platform Fee: 2,500 MMK (5%)
Payment Fee: ~1,652 MMK (varies by method)
Tax: 2,500 MMK (5%)
At settlement:
Tickets Sold: 100
Payout per Ticket: 50,000 MMK
Total Payout: 5,000,000 MMK ← Exact amount promised
Benefits:
- Predictable revenue
- No fee surprises
- Easy financial planning
- Clear commission structure
The organizer's payout is the foundation of all pricing. Everything else is calculated from it.
Customers see and pay one price. No hidden fees at checkout.
Platform fee is clear and auditable but not shown to customers.
Once calculated and purchased, pricing is never recalculated.
Platform fees can vary by organizer, event, or time without breaking old tickets.
The Reverse Pricing Model:
- Organizer sets payout amount (what they want)
- System adds platform fee (based on payout)
- System adds tax (based on payout)
- System calculates price algebraically (including payment fee)
- Customer sees and pays final price
- All components stored as immutable snapshot
- Settlement uses stored values (never recalculates)
- Organizer receives exact payout promised
Core Philosophy: Organizers should know exactly what they'll earn. Customers should see exactly what they'll pay. Platform handles all the math in between.
End of document.