Skip to content

Wallet Module Documentation

Overview

The Wallet Module provides a closed-loop digital payment system for the hotel. Every customer has a "Wallet" that can hold funds (Deposits, Refunds, Loyalty Rewards). These funds can be used to settle Folios instantly. It acts as a Liability Ledger ($ held on behalf of guests).

Key Features

  • Store of Value: Holds prepaid funds in local currency.
  • Loyalty Integration: Automatically awards points for deposits (incentivizing cash flow).
  • Accounting & Liability: Real-time GL posting. Deposits are Liabilities (IOUs), Payments reduce Liability.
  • Fraud Prevention: Transactions are immutable. Wallets can be frozen.

Architecture

Domain Layer (app/Domain/Wallet)

Models (2 Models)

CustomerWallet (CustomerWallet.php)
  • Table: customer_wallets
  • Description: The container for balance.
  • Key Fields:
    • customer_id: Owner.
    • balance: Current funds (Decimal 10,2).
    • is_active: Freeze switch.
  • Relationships:
    • transactions(): History.
WalletTransaction (WalletTransaction.php)
  • Table: wallet_transactions
  • Description: The immutable ledger line.
  • Key Fields:
    • type: DEPOSIT | PAYMENT | REFUND.
    • amount: Transaction value.
    • balance_after: Snapshot of wallet at that moment.
    • description: Context (e.g. "Payment for Invoice #102").
    • somxchange_ref: External gateway reference.

Services

WalletService (WalletService.php)

Purpose: High-security financial state management.

Key Methods:

deposit(wallet, amount, ref)

Adds funds.

  • Logic:
    1. Checks is_active.
    2. Updates Balance: balance += amount.
    3. Creates Transaction (DEPOSIT).
    4. Accounting:
      • Dr Asset (102-SX: SomXchange Clearing).
      • Cr Liability (205: Guest Deposits).
    5. Loyalty: Calls awardLoyaltyPoints().
deduct(wallet, amount, desc)

Spends funds.

  • Logic:
    1. Checks is_active.
    2. Funds Check: Throws exception if balance < amount.
    3. Updates Balance: balance -= amount.
    4. Creates Transaction (PAYMENT).
    5. Accounting:
      • Dr Liability (205: Guest Deposits).
      • Cr Asset/Receivable (103: Accounts Receivable).
refund(wallet, amount, desc)

Returns funds (reversal).

  • Logic:
    1. Updates Balance: balance += amount.
    2. Creates Transaction (REFUND).
    3. Accounting:
      • Dr Asset/Receivable (103).
      • Cr Liability (205).

Accounting Integration

The module relies on specific General Ledger codes to function.

TransactionDebit Account KeyCredit Account KeyLogic
Depositasset.cash.somxchangeliability.walletWe received cash (Asset), but owe service (Liability).
Paymentliability.walletasset.arWe fulfilled service (Liability reduced), offsetting the AR Invoice (Asset reduced).

Implementation: Accounts are resolved dynamically via AccountingMapService.


Audit Findings & Improvements

Strengths

  • Loyalty Hook: The awardLoyaltyPoints integration is a clever feature for "Financial Gamification", encouraging guests to keep money in the ecosystem.
  • Immutable History: The service never "edits" a transaction. It only creates new ones. This is correct for financial auditing.

Issues Identified

Major

  • Critical Race Condition: [FIXED] deposit and deduct methods now use lockingForUpdate() to prevent race conditions during concurrent transactions.

Minor

  • Hardcoded Accounts: [FIXED] Logic now uses AccountingMapService to resolve ASSET_CASH_SOMXCHANGE and LIABILITY_WALLET keys.
  • Loyalty Config: Uses config('somxchange.loyalty...'). This couples the generic Wallet module to a specific Gateway provider (SomXchange) in naming.

Configuration

Config: config/somxchange.php (Legacy naming)

php
return [
    'loyalty' => [
        'points_per_deposit' => 1,
        'minimum_deposit_for_points' => 10,
    ]
];

Module Version: 2.0 Status: Stable (Race condition fixed with lockForUpdate())