# Financial Settings Configuration Guide
## Overview
The Financial Settings system uses a **config-first approach** with database overrides. This ensures that:
1. New companies get sensible defaults immediately
2. Settings can be customized per company
3. System remains functional even without database configuration
4. Easy to maintain and update default values
## Architecture
### Config File
**Location:** `config/financial-settings.php`
Contains all default values organized by category:
- Deposits & Partial Payments
- Tax Rates & VAT
- Payment Gateway
- Refund Rules
- Dynamic Pricing
- Multi-Currency
- Security Deposit
- Invoicing
- Pricing Rules
- Payment Methods
- Fiscal & Compliance
- Notifications
### Helper Class
**Location:** `app/Helpers/FinancialSettingsHelper.php`
Provides methods to:
- Get settings with config fallback
- Initialize settings for new companies
- Calculate deposit amounts
- Get tax rates by category
- Check if features are enabled
### Helper Functions
**Location:** `app/Helpers/helpers.php`
Global helper functions:
- `setting($name, $group, $default)` - Get any setting
- `financial_setting($name, $default)` - Get financial setting (shorthand)
## Usage
### 1. Getting Settings
```php
// Using the setting() helper
$depositEnabled = setting('enable_deposit_payments', 'financial', false);
$taxRate = setting('default_tax_rate', 'financial', 20);
// Using the financial_setting() shorthand
$depositEnabled = financial_setting('enable_deposit_payments', false);
$taxRate = financial_setting('default_tax_rate', 20);
// Using the helper class directly
use App\Helpers\FinancialSettingsHelper;
$depositEnabled = FinancialSettingsHelper::get('enable_deposit_payments');
$taxRate = FinancialSettingsHelper::get('default_tax_rate');
```
### 2. Checking if Features are Enabled
```php
use App\Helpers\FinancialSettingsHelper;
if (FinancialSettingsHelper::isEnabled('deposits')) {
// Deposit payments are enabled
}
if (FinancialSettingsHelper::isEnabled('partial_payments')) {
// Partial payments are enabled
}
if (FinancialSettingsHelper::isEnabled('dynamic_pricing')) {
// Dynamic pricing is enabled
}
```
### 3. Calculating Deposit Amounts
```php
use App\Helpers\FinancialSettingsHelper;
$bookingTotal = 500.00;
$depositAmount = FinancialSettingsHelper::calculateDepositAmount($bookingTotal);
// If deposit type is 'percentage' with 30%: returns 150.00
// If deposit type is 'fixed' with 100: returns 100.00
// If deposits disabled: returns 0.00
```
### 4. Getting Tax Rates
```php
use App\Helpers\FinancialSettingsHelper;
// Get global tax rate
$taxRate = FinancialSettingsHelper::getTaxRate();
// Get tax rate for specific category
$accommodationTax = FinancialSettingsHelper::getTaxRate('accommodation');
$serviceTax = FinancialSettingsHelper::getTaxRate('service');
```
### 5. Initializing Settings for New Company
```php
use App\Helpers\FinancialSettingsHelper;
// When creating a new company
$company = Company::create([...]);
// Initialize all financial settings with defaults
FinancialSettingsHelper::initializeForCompany($company->id, $workspace->id);
```
### 6. Getting All Settings
```php
use App\Helpers\FinancialSettingsHelper;
// Get all settings for current company
$allSettings = FinancialSettingsHelper::getAll();
// Get all settings for specific company
$allSettings = FinancialSettingsHelper::getAll($companyId);
```
## Configuration Examples
### Example 1: Beach Resort Configuration
```php
// config/financial-settings.php
return [
'deposits' => [
'enable_deposit_payments' => true,
'require_deposit_for_booking' => true,
'deposit_type' => 'percentage',
'deposit_percentage' => 50, // 50% deposit for beach spots
'deposit_due_timing' => 'immediately',
],
'tax' => [
'default_tax_rate_type' => 'per_category',
'tax_rates_by_category' => [
['category' => 'spot', 'tax_rate' => 20, 'description' => 'Beach spots VAT'],
['category' => 'service', 'tax_rate' => 10, 'description' => 'Services reduced rate'],
],
],
'dynamic_pricing' => [
'enabled' => true,
'peak_hours_factor' => 1.5, // 50% increase during peak hours
'weekend_factor' => 1.3, // 30% increase on weekends
],
];
```
### Example 2: Hotel Configuration
```php
return [
'deposits' => [
'enable_deposit_payments' => true,
'deposit_type' => 'fixed',
'deposit_fixed_amount' => 100.00,
'deposit_due_timing' => 'days_before',
'deposit_due_days' => 14,
],
'partial_payments' => [
'enable_partial_payments' => true,
'partial_payment_min_installments' => 3,
'partial_payment_max_installments' => 12,
'partial_payment_schedule_type' => 'equal',
],
'security_deposit' => [
'required' => true,
'amount' => 200.00,
'refund_processing_days' => 7,
'auto_refund' => true,
],
];
```
### Example 3: Service Provider Configuration
```php
return [
'deposits' => [
'enable_deposit_payments' => false, // No deposits for services
],
'tax' => [
'default_tax_rate_type' => 'global',
'default_tax_rate' => 0, // Tax-exempt services
'enable_tax_exemptions' => true,
],
'payment_gateway' => [
'provider' => 'stripe',
'auto_capture_payments' => true,
],
'refunds' => [
'refund_policy' => 'flexible',
'allow_partial_refunds' => true,
],
];
```
## Integration with Booking System
### In BookingController
```php
use App\Helpers\FinancialSettingsHelper;
public function store(Request $request)
{
$booking = Booking::create($request->validated());
// Check if deposit is required
if (FinancialSettingsHelper::isEnabled('deposits')) {
$depositAmount = FinancialSettingsHelper::calculateDepositAmount($booking->total);
if (FinancialSettingsHelper::get('require_deposit_for_booking')) {
$booking->status = 'pending_deposit';
$booking->deposit_required = $depositAmount;
$booking->save();
}
}
return redirect()->route('bookings.show', $booking);
}
```
### In InvoiceService
```php
use App\Helpers\FinancialSettingsHelper;
public function generateInvoice(Booking $booking): Invoice
{
$invoice = Invoice::create([
'booking_id' => $booking->id,
'subtotal' => $booking->subtotal,
]);
// Apply tax
$taxRate = FinancialSettingsHelper::getTaxRate('accommodation');
$invoice->tax_rate = $taxRate;
$invoice->tax_amount = $booking->subtotal * ($taxRate / 100);
// Check if tax is inclusive
if (FinancialSettingsHelper::get('tax_inclusive_pricing')) {
// Extract tax from total
$invoice->total = $booking->subtotal;
$invoice->tax_amount = $booking->subtotal - ($booking->subtotal / (1 + ($taxRate / 100)));
} else {
// Add tax to total
$invoice->total = $booking->subtotal + $invoice->tax_amount;
}
$invoice->save();
return $invoice;
}
```
### In PricingService
```php
use App\Helpers\FinancialSettingsHelper;
public function calculatePrice(VenueSpot $spot, Carbon $date, Carbon $time): float
{
$basePrice = $spot->price;
if (!FinancialSettingsHelper::isEnabled('dynamic_pricing')) {
return $basePrice;
}
$price = $basePrice;
// Apply weekend pricing
if ($date->isWeekend()) {
$factor = FinancialSettingsHelper::get('weekend_pricing_factor', 1.0);
$price *= $factor;
}
// Apply peak hours pricing
$peakStart = config('financial-settings.dynamic_pricing.peak_hours.start');
$peakEnd = config('financial-settings.dynamic_pricing.peak_hours.end');
if ($time->between($peakStart, $peakEnd)) {
$factor = FinancialSettingsHelper::get('peak_hours_pricing_factor', 1.0);
$price *= $factor;
}
return $price;
}
```
## Company Creation Hook
### In CompanyObserver or CompanySeeder
```php
use App\Helpers\FinancialSettingsHelper;
class CompanyObserver
{
public function created(Company $company)
{
// Initialize financial settings with defaults
FinancialSettingsHelper::initializeForCompany($company->id);
// Or with workspace
if ($company->defaultWorkspace) {
FinancialSettingsHelper::initializeForCompany(
$company->id,
$company->defaultWorkspace->id
);
}
}
}
```
## Environment Variables
Some settings can be overridden via environment variables:
```env
# Payment Gateway
PAYMENT_GATEWAY_API_KEY=sk_test_...
PAYMENT_GATEWAY_SECRET_KEY=sk_secret_...
PAYMENT_GATEWAY_MODE=test
PAYMENT_GATEWAY_WEBHOOK_SECRET=whsec_...
# Currency Conversion
CURRENCY_API_KEY=your_api_key_here
```
## Updating Config Defaults
When you need to change default values:
1. **Update config file:**
```php
// config/financial-settings.php
'deposits' => [
'deposit_percentage' => 40, // Changed from 30
],
```
2. **Existing companies keep their settings** (database values)
3. **New companies get new defaults** automatically
4. **To apply to existing companies:**
```php
// Run in tinker or migration
Company::each(function ($company) {
// Only update if not customized
$setting = Setting::where('company_id', $company->id)
->where('name', 'deposit_percentage')
->first();
if (!$setting) {
FinancialSettingsHelper::initializeForCompany($company->id);
}
});
```
## Best Practices
1. **Always use helper functions** instead of direct database queries
2. **Provide sensible defaults** in config file
3. **Document custom settings** in company notes
4. **Test with config values** before saving to database
5. **Use feature flags** (`isEnabled()`) before applying logic
6. **Cache frequently accessed settings** if needed
7. **Validate settings** before saving to database
8. **Log setting changes** for audit trail
## Troubleshooting
### Settings not loading
```php
// Clear config cache
php artisan config:clear
// Dump autoload
composer dump-autoload
```
### Wrong values returned
```php
// Check if database has override
$setting = Setting::where('name', 'deposit_percentage')
->where('company_id', session('selected_company'))
->first();
dd($setting->payload); // Database value
dd(config('financial-settings.deposits.deposit_percentage')); // Config value
```
### Initialize missing settings
```php
use App\Helpers\FinancialSettingsHelper;
// In tinker
FinancialSettingsHelper::initializeForCompany(1); // Company ID 1
```
## Summary
✅ **Config file** provides defaults for all settings
✅ **Database** stores company-specific overrides
✅ **Helper class** manages fallback logic
✅ **Helper functions** provide easy access
✅ **Automatic initialization** for new companies
✅ **Feature flags** for conditional logic
✅ **Calculation helpers** for common operations
✅ **Environment variables** for sensitive data
This system ensures your application always has valid financial settings, whether from database or config defaults!