# Booking Payment System Implementation Guide
## Overview
Complete deposit payment system with check-in/check-out payment flow integrated with Financial Settings.
## Architecture
### 1. Database Structure
#### Payments Table (`payments`)
Tracks all payment transactions for bookings with stages:
- **deposit** - Initial deposit payment (online via client UI)
- **check_in** - Remaining balance payment at check-in (in-person)
- **check_out** - Additional charges payment at check-out (in-person)
- **full** - Full payment upfront
- **partial** - Partial payment installments
- **refund** - Refund transactions
#### Booking Payment Fields (added to `bookings` table)
- `payment_status` - Overall payment status
- `deposit_amount` - Required deposit amount
- `deposit_paid` - Boolean flag
- `deposit_paid_at` - Timestamp
- `total_amount` - Total booking amount
- `paid_amount` - Total amount paid
- `remaining_amount` - Remaining balance
- `tax_amount` - Tax amount
- `subtotal_amount` - Subtotal before tax
- `payment_confirmed` - Payment confirmation flag
- `payment_confirmed_at` - Confirmation timestamp
### 2. Models
#### BookingPayment Model
- Tracks individual payment transactions
- Scoped by company and workspace
- Supports multiple payment methods
- Tracks payment stages and status
- Includes fiscal receipt integration
#### Booking Model (Updated)
Added relationships:
- `payments()` - All payment transactions
- `bookingServices()` - Services in booking
- `bookingPackages()` - Packages in booking
- `bookingSpots()` - Spots in booking
- `bookingProducts()` - Products in booking
### 3. BookingPaymentService
Comprehensive service for all payment calculations and operations.
#### Key Methods
**Calculation Methods:**
```php
// Calculate total booking amount with tax
calculateBookingTotal(Booking $booking): array
// Calculate deposit amount based on settings
calculateDepositAmount(Booking $booking): float
// Calculate remaining balance after deposit
calculateRemainingBalance(Booking $booking): float
// Calculate amount due at check-in
calculateCheckInAmount(Booking $booking): float
// Calculate amount due at check-out (additional charges)
calculateCheckOutAmount(Booking $booking): float
// Get total paid amount
getTotalPaidAmount(Booking $booking): float
```
**Status Check Methods:**
```php
// Check if deposit has been paid
isDepositPaid(Booking $booking): bool
// Check if booking is fully paid
isFullyPaid(Booking $booking): bool
// Get payment status: 'unpaid', 'partially_paid', 'deposit_paid', 'paid'
getPaymentStatus(Booking $booking): string
// Check if booking can be confirmed (deposit requirement)
canConfirmBooking(Booking $booking): bool
```
**Payment Processing Methods:**
```php
// Process deposit payment (online)
processDepositPayment(Booking $booking, string $paymentMethod, ?string $transactionId): BookingPayment
// Process check-in payment (in-person)
processCheckInPayment(Booking $booking, float $amount, string $paymentMethod): BookingPayment
// Process check-out payment (in-person)
processCheckOutPayment(Booking $booking, float $amount, string $paymentMethod): BookingPayment
// Get payment summary
getPaymentSummary(Booking $booking): array
```
## Payment Flow
### 1. Booking Creation (Client UI)
When a client creates a booking:
```php
use App\Services\BookingPaymentService;
$paymentService = new BookingPaymentService();
// Calculate totals
$totals = $paymentService->calculateBookingTotal($booking);
// Calculate deposit required
$depositAmount = $paymentService->calculateDepositAmount($booking);
// If deposit is enabled and required
if (financial_setting('enable_deposit_payments') &&
financial_setting('require_deposit_for_booking')) {
// Show payment form for deposit
// Redirect to payment gateway
// Process payment
$payment = $paymentService->processDepositPayment(
$booking,
'stripe', // or 'paypal', 'card', etc.
$transactionId
);
// Update booking
$booking->update([
'deposit_amount' => $depositAmount,
'deposit_paid' => true,
'deposit_paid_at' => now(),
'payment_status' => 'deposit_paid',
'status' => 'confirmed', // Auto-confirm if deposit paid
]);
}
```
### 2. Check-In Process
When staff performs check-in:
```php
$paymentService = new BookingPaymentService();
// Calculate amount due at check-in
$checkInAmount = $paymentService->calculateCheckInAmount($booking);
if ($checkInAmount > 0) {
// Show payment form to staff
// Process in-person payment
$payment = $paymentService->processCheckInPayment(
$booking,
$checkInAmount,
'cash' // or 'card', 'bank_transfer'
);
// Update booking
$booking->update([
'paid_amount' => $paymentService->getTotalPaidAmount($booking),
'remaining_amount' => $paymentService->calculateRemainingBalance($booking),
'payment_status' => $paymentService->getPaymentStatus($booking),
'checked_in_at' => now(),
'status' => 'checked_in',
]);
}
```
### 3. Check-Out Process
When staff performs check-out:
```php
$paymentService = new BookingPaymentService();
// Calculate any additional charges
$checkOutAmount = $paymentService->calculateCheckOutAmount($booking);
if ($checkOutAmount > 0) {
// Show payment form for additional charges
$payment = $paymentService->processCheckOutPayment(
$booking,
$checkOutAmount,
'card'
);
// Update booking
$booking->update([
'paid_amount' => $paymentService->getTotalPaidAmount($booking),
'remaining_amount' => 0,
'payment_status' => 'paid',
'checked_out_at' => now(),
'status' => 'completed',
]);
}
```
## Tax Calculation
The service automatically applies tax based on Financial Settings:
```php
// Tax settings from config/financial-settings.php
'tax' => [
'default_tax_rate_type' => 'global', // or 'per_category'
'default_tax_rate' => 20.0,
'tax_inclusive_pricing' => true, // Tax included in price
'tax_display_mode' => 'separate', // How to display tax
'tax_rates_by_category' => [
['category' => 'accommodation', 'tax_rate' => 20],
['category' => 'service', 'tax_rate' => 10],
],
]
```
### Tax Calculation Logic
**Tax-Inclusive Pricing (default):**
```php
// Price already includes tax - extract it
$taxAmount = $price - ($price / (1 + ($taxRate / 100)));
$netAmount = $price - $taxAmount;
```
**Tax-Exclusive Pricing:**
```php
// Tax is added on top
$netAmount = $price;
$taxAmount = $price * ($taxRate / 100);
$total = $netAmount + $taxAmount;
```
**Category-Specific Rates:**
```php
// Each item type can have different tax rate
- Accommodation: 20%
- Services: 10%
- Products: 20%
- Packages: Based on contents
```
## Integration Points
### 1. Client Booking Flow
**File:** `app/Filament/Client/Resources/BookingResource.php` (or similar)
```php
use App\Services\BookingPaymentService;
protected function afterCreate(): void
{
$paymentService = new BookingPaymentService();
// Calculate and store totals
$totals = $paymentService->calculateBookingTotal($this->record);
$depositAmount = $paymentService->calculateDepositAmount($this->record);
$this->record->update([
'total_amount' => $totals['total'],
'subtotal_amount' => $totals['subtotal'],
'tax_amount' => $totals['tax_amount'],
'deposit_amount' => $depositAmount,
]);
// If deposit required, redirect to payment
if ($depositAmount > 0 && financial_setting('require_deposit_for_booking')) {
return redirect()->route('client.booking.payment', $this->record);
}
}
```
### 2. Check-In Action
**File:** `app/Filament/Resources/BookingResource/Pages/CheckIn.php`
```php
use App\Services\BookingPaymentService;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Select;
public function form(Form $form): Form
{
$paymentService = new BookingPaymentService();
$amountDue = $paymentService->calculateCheckInAmount($this->record);
return $form->schema([
TextInput::make('amount_due')
->label('Amount Due')
->default($amountDue)
->disabled()
->prefix('€'),
Select::make('payment_method')
->label('Payment Method')
->options([
'cash' => 'Cash',
'card' => 'Card',
'bank_transfer' => 'Bank Transfer',
])
->required()
->visible(fn() => $amountDue > 0),
]);
}
protected function handleCheckIn(array $data): void
{
$paymentService = new BookingPaymentService();
$amountDue = $paymentService->calculateCheckInAmount($this->record);
if ($amountDue > 0) {
$paymentService->processCheckInPayment(
$this->record,
$amountDue,
$data['payment_method']
);
}
$this->record->update([
'status' => 'checked_in',
'checked_in_at' => now(),
'payment_status' => $paymentService->getPaymentStatus($this->record),
]);
}
```
### 3. Check-Out Action
**File:** `app/Filament/Resources/BookingResource/Pages/CheckOut.php`
```php
use App\Services\BookingPaymentService;
public function form(Form $form): Form
{
$paymentService = new BookingPaymentService();
$amountDue = $paymentService->calculateCheckOutAmount($this->record);
return $form->schema([
TextInput::make('additional_charges')
->label('Additional Charges')
->default($amountDue)
->numeric()
->prefix('€'),
Select::make('payment_method')
->label('Payment Method')
->options([
'cash' => 'Cash',
'card' => 'Card',
])
->required()
->visible(fn() => $amountDue > 0),
]);
}
protected function handleCheckOut(array $data): void
{
$paymentService = new BookingPaymentService();
if ($data['additional_charges'] > 0) {
$paymentService->processCheckOutPayment(
$this->record,
$data['additional_charges'],
$data['payment_method']
);
}
$this->record->update([
'status' => 'completed',
'checked_out_at' => now(),
'payment_status' => 'paid',
]);
}
```
## Usage Examples
### Get Payment Summary
```php
$paymentService = new BookingPaymentService();
$summary = $paymentService->getPaymentSummary($booking);
/*
Returns:
[
'subtotal' => 100.00,
'tax_amount' => 20.00,
'total' => 120.00,
'deposit_required' => 36.00,
'deposit_paid' => true,
'total_paid' => 36.00,
'remaining_balance' => 84.00,
'payment_status' => 'deposit_paid',
'fully_paid' => false,
'items' => [...],
]
*/
```
### Check Payment Status
```php
$paymentService = new BookingPaymentService();
if (!$paymentService->canConfirmBooking($booking)) {
// Deposit not paid - cannot confirm
return back()->withErrors(['Deposit payment required']);
}
if ($paymentService->isFullyPaid($booking)) {
// Booking is fully paid
}
$status = $paymentService->getPaymentStatus($booking);
// Returns: 'unpaid', 'partially_paid', 'deposit_paid', 'paid'
```
## Migration Steps
1. **Run migrations:**
```bash
php artisan migrate
```
2. **Update existing bookings** (if needed):
```php
use App\Services\BookingPaymentService;
$paymentService = new BookingPaymentService();
Booking::chunk(100, function ($bookings) use ($paymentService) {
foreach ($bookings as $booking) {
$totals = $paymentService->calculateBookingTotal($booking);
$booking->update([
'total_amount' => $totals['total'],
'subtotal_amount' => $totals['subtotal'],
'tax_amount' => $totals['tax_amount'],
]);
}
});
```
3. **Configure Financial Settings:**
- Enable deposit payments
- Set deposit type (percentage/fixed)
- Set deposit percentage
- Configure tax rates
- Set tax-inclusive pricing
4. **Implement UI components:**
- Client booking payment page
- Check-in payment modal
- Check-out payment modal
- Payment history view
## Next Steps
1. Create payment gateway integration (Stripe/PayPal)
2. Add payment receipt generation
3. Implement fiscal receipt printing
4. Add payment notifications (email/SMS)
5. Create payment reports and analytics
6. Add refund processing
7. Implement partial payment installments
## Summary
✅ **Database structure** - Payments table and booking payment fields
✅ **Models** - BookingPayment model with relationships
✅ **Service layer** - Comprehensive BookingPaymentService
✅ **Tax calculation** - Automatic tax calculation based on settings
✅ **Payment stages** - Deposit, check-in, check-out flow
✅ **Status tracking** - Payment status and validation
✅ **Integration ready** - Ready for UI implementation
The system is now ready for UI integration and payment gateway setup!