This document contains historical information about bugs discovered and fixed during the implementation of the Customer Pays Fees feature. This is preserved for reference but is not part of the current operational documentation.
- Only updated
Payments::CalculateFeewith fee rates per payable type Stripe::CreatePaymentIntentandPayments::Createstill hardcodedbooking_fee- Root cause of subsequent bugs: Multiple fee calculation points with inconsistent rates
- Admin credit card payments for 6+ payable types were overcharging customers
- Root cause: Multiple fee calculation points with inconsistent rates between services
- Solution: Single source of truth in model layer with explicit
fee_amountparameter - Added comprehensive controller specs to prevent regression
- Confirmation entries were debiting A/R for full amount including fees ($85.00)
- Payment entries were crediting A/R for service amount only ($81.60)
- Result: A/R balance showed fee amount ($3.40) instead of $0.00 after payment
- Root cause: Confirmation services didn't exclude fee from A/R amounts
- Solution: Added
service_amount_for_arhelper, applied to both debits and credits - Fixed in
EventSignups::RecordConfirmationandBookings::RecordConfirmation
- Customer-facing booking and voucher payments were double-charging fees
- Affected controllers failed to pass
fee_amountparameter toCreatePaymentIntent - Result: Service calculated fees again on already-fee-inclusive amounts
Status: FIXED
Affected Controllers:
app/controllers/customer/bookings_controller.rb- paygo and regular booking payment flowsapp/controllers/customer/vouchers_controller.rb- voucher payment flow
Problem:
Both controllers calculated amounts including fees but did NOT pass fee_amount parameter to CreatePaymentIntent. This caused CreatePaymentIntent to calculate and add fees AGAIN, resulting in double-charging.
Impact Before Fix:
- Paygo bookings: Customers charged 5-10% extra (e.g., €105 becomes €110.25)
- Regular bookings: Customers charged 5-10% extra on remaining balance
- Voucher payments: Customers charged 5-10% extra
- Affected ALL customer-facing facility bookings and vouchers when CUSTOMER_PAYS_FEES enabled
Fix Applied:
# customer/bookings_controller.rb - NOW FIXED
def payment_intent
amount, fee_amount_cents = calculate_payment_amounts
result = ::Stripe::CreatePaymentIntent.call!(@booking.customer, amount, description: @booking.payment_description, fee_amount: fee_amount_cents)
render json: { clientSecret: result.payload.client_secret }, status: :created
end
private
def calculate_payment_amounts
if params[:paygo].present?
# Paygo: Calculate fee on initial total
base_amount = @booking.initial_total
amount = @booking.customer_pays_service_fee? ? base_amount * (1 + @booking.venue.booking_fee) : base_amount
fee_amount_cents = @booking.customer_pays_service_fee? ? (base_amount * @booking.venue.booking_fee * 100).to_i : 0
else
# Regular payment: Calculate fee on amount due
base_amount = @booking.amount_due
amount = @booking.amount_due(for_stripe: true)
fee_amount_cents = ((amount - base_amount) * 100).to_i
end
[amount, fee_amount_cents]
end
# customer/vouchers_controller.rb - NOW FIXED
def payment_intent
voucher = current_customer.vouchers.find(params[:id])
base_amount = voucher.amount_due
amount = voucher.amount_due(for_stripe: true)
fee_amount_cents = ((amount - base_amount) * 100).to_i
result = ::Stripe::CreatePaymentIntent.call!(voucher.customer, amount, description: voucher.description, recipient: current_venue, fee_amount: fee_amount_cents)
render json: { clientSecret: result.payload.client_secret }, status: :created
endTest Coverage Added:
- ✅
spec/controllers/customer/bookings_controller_spec.rb- Tests for paygo and regular payments, fees enabled/disabled - ✅
spec/controllers/customer/vouchers_controller_spec.rb- Tests for fees enabled/disabled - Both test suites verify correct
fee_amountparameter is passed toCreatePaymentIntent
Related Work: This fix also corrected the admin booking overview to always display base amounts (not fee-inclusive amounts) everywhere except the payment modal fee banner. The fee banner only appears when paying with credit card via Stripe.
Status: FIXED
Affected Controller: app/controllers/admin/stripe_controller.rb
Problem: The controller had backwards logic for when to add fees:
- It ONLY added fees for Invoices (Pattern 1)
- It used base amount for Bookings (wrong - should add fees for all payables)
What Actually Happened:
- View passed:
booking.amount_due(€30.00 base) +booking.service_fee(€1.50) - Controller created PaymentIntent with: €30.00 (wrong - didn't add fee!)
- Payment record stored: €31.50 (correct)
- Stripe capture tried: €31.50 from €30.00 PaymentIntent → ERROR: "amount_too_large"
Fix Applied:
# app/controllers/admin/stripe_controller.rb
def payment_intent
base_amount_param = params[:amount].to_d
fee_amount_dollars = params[:fee_amount]&.to_d || 0
# Add fees for ALL payables when customer_pays_fees is enabled
amount = if @customer && current_venue.enabled?(Feature::CUSTOMER_PAYS_FEES) && fee_amount_dollars.positive?
base_amount_param + fee_amount_dollars
else
base_amount_param
end
fee_amount_cents = (fee_amount_dollars * 100).to_i
result = ::Stripe::CreatePaymentIntent.call!(
@customer,
amount,
recipient: current_venue,
description: params[:description],
fee_amount: fee_amount_cents
)
render json: { clientSecret: result.payload.client_secret }, status: :created
endTest Coverage Updated:
- Updated
spec/controllers/admin/stripe_controller_spec.rbto expect fee addition for all payables - Removed incorrect pattern-based tests
- All admin payment flows now correctly tested
Status: FIXED
Affected File: app/views/mailers/_booking_details.html.haml
Problem:
The email template was using payable.subtotal_text to display the "Booking" amount in the fee breakdown. However, subtotal represents total - tax (not "total - fee"), resulting in incorrect amounts being displayed (€27.27 instead of €30.00).
Fix Applied:
Changed line 57 from payable.subtotal_text to payable.total_text.
Result: Booking confirmation emails now correctly display:
- Booking: €30.00 (base amount)
- Transaction Fee: €1.50 (5% fee)
- Total: €31.50 (base + fee)
Status: NOT FIXED - requires review
Controller: app/controllers/customer/slots_controller.rb
Potential Issue: Individual slot payment flow may have similar double-fee bug pattern.
Next Steps: Review customer/slots_controller.rb:payment_intent action and add specs if needed.
- Multiple Fee Calculation Points: Having fee logic in multiple places (services, controllers, models) led to inconsistency
- Implicit vs Explicit: Not explicitly passing
fee_amountparameter caused services to recalculate fees - Pattern Confusion: Trying to distinguish "Pattern 1 vs Pattern 2" added complexity that didn't match reality
- Accounting Distinction: Not clearly separating "service amount" from "total with fees" for A/R tracking
- Single Source of Truth: Fee calculation in model layer (
CustomerPayableFeesconcern) - Explicit Parameters: Always pass
fee_amountparameter to prevent recalculation - Comprehensive Testing: Controller specs verify correct parameter passing
- Clear Separation: Accounting helper methods (
service_amount_for_ar) for A/R vs revenue
- Always pass
fee_amount: When callingCreatePaymentIntentwith fee-inclusive amounts - Test both flows: Admin and customer-facing payment actions
- Check accounting: Verify A/R entries use service amount, not total with fees
- Document clearly: Don't over-complicate with "patterns" - just describe what happens
Before Fixes:
- Customer-facing bookings: Double-charged on fees (5-10% overcharge)
- Customer-facing vouchers: Double-charged on fees (5-10% overcharge)
- Admin bookings: Payments failed with "amount_too_large" error
- Booking emails: Showed incorrect amounts
- A/R balances: Incorrect balances after payment (showing fee amount instead of $0)
After Fixes:
- ✅ All payment flows correctly calculate and charge fees once
- ✅ Admin payments succeed with correct amounts
- ✅ Emails display correct amounts
- ✅ A/R balances correctly track service amounts
- ✅ Comprehensive test coverage prevents regression
Added Specs:
spec/controllers/customer/bookings_controller_spec.rb(4 examples)spec/controllers/customer/vouchers_controller_spec.rb(2 examples)- Updated
spec/controllers/admin/stripe_controller_spec.rb(12 examples)
Existing Specs Verified:
- Customer::InvoicesController (6 examples)
- Customer::EventSignupsController (144 examples)
- Customer::Memberships::BillingPeriodsController (111 examples)
- All model specs with
CustomerPayableFeesconcern
Total: 279+ examples covering fee calculation and payment intent creation across all payables.