Prepay Capture Scheduling

This document explains how to set up automatic payment capture for authorized prepayments.

Overview

When customers place orders with credit card prepayment, we authorize the card (hold funds) but don't charge until delivery. On the delivery date, we automatically capture (charge) the authorization.

How It Works

  1. Order Creation: Customer pays with credit card → card is authorized (funds held)
  2. Order Status: payment_status = "authorized"
  3. Delivery Date: Automated job captures the authorization → payment_status = "paid"

Manual Execution

Run the capture job manually:

bin/rails payments:capture_authorized

Test capture for a specific order:

bin/rails payments:test_capture[ORDER-123456]

Automated Scheduling

Option 1: Cron Job (Recommended)

Add to your server's crontab (crontab -e):

# Capture authorized payments daily at 6 AM
0 6 * * * cd /path/to/quarry_rentals && bin/rails payments:capture_authorized >> log/payment_capture.log 2>&1

Option 2: Kamal with Cron

Add to config/deploy.yml:

accessories:
  cron:
    image: alpine:latest
    command: crond -f
    volumes:
      - ./config/crontab:/etc/crontabs/root:ro

Create config/crontab:

0 6 * * * cd /rails && bin/rails payments:capture_authorized

Option 3: Whenever Gem (Alternative)

Add to Gemfile:

gem 'whenever', require: false

Create config/schedule.rb:

set :output, "log/cron.log"
set :environment, "production"

every 1.day, at: '6:00 am' do
  rake "payments:capture_authorized"
end

Deploy schedule:

whenever --update-crontab

Monitoring

Check Logs

# View payment capture logs
tail -f log/production.log | grep -i capture

# View specific capture job logs
kamal app logs | grep CaptureAuthorizedPaymentsJob

Monitor Failed Captures

Failed captures will:

  1. Log errors to log/production.log
  2. Send alert email to admins
  3. Leave order in authorized status (can be retried)

Retry Failed Captures

# List orders still needing capture
bin/rails runner "Order.needing_capture.each { |o| puts '#{o.order_number} - #{o.delivery_date}' }"

# Retry a specific order
bin/rails payments:test_capture[ORDER-123456]

Security Notes

Troubleshooting

Authorization Not Found

Issue: "No authorization found for order"

Solution: Check payment_transactions table for transaction_type = 'auth_only'

order = Order.find_by(order_number: "ORDER-123")
order.payment_transactions.where(transaction_type: "auth_only")

Capture Fails

Common reasons:

Solution: Contact customer for new payment method

Wrong Payment Status

Issue: Order shows "paid" but no capture transaction

Solution: Verify transaction history:

order.payment_transactions.order(created_at: :desc).each do |txn|
  puts "#{txn.transaction_type} - #{txn.status} - $#{txn.amount} - #{txn.created_at}"
end