diff --git a/README.md b/README.md index 30625af..8b1b910 100644 --- a/README.md +++ b/README.md @@ -7,60 +7,64 @@ [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/hpwebdeveloper/laravel-pay-pocket/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/hpwebdeveloper/laravel-pay-pocket/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain) [![Imports](https://github.com/HPWebdeveloper/laravel-pay-pocket/actions/workflows/check_imports.yml/badge.svg?branch=main)](https://github.com/HPWebdeveloper/laravel-pay-pocket/actions/workflows/check_imports.yml) - **Laravel Pay Pocket** is a package designed for Laravel applications, offering the flexibility to manage multiple wallet types within two dedicated database tables, `wallets` and `wallets_logs`. **Demo** https://github.com/HPWebdeveloper/demo-pay-pocket **Note:** This package does not handle payments from payment platforms, but instead offers the concept of virtual money, deposit, and withdrawal. -* **Author**: Hamed Panjeh -* **Vendor**: hpwebdeveloper -* **Package**: laravel-pay-pocket -* **Alias name**: Laravel PPP (Laravel Pay Pocket Package) -* **Version**: `1.x` -* **PHP Version**: 8.1+ -* **Laravel Version**: `10.x` -* **[Composer](https://getcomposer.org/):** `composer require hpwebdeveloper/laravel-pay-pocket` - +- **Author**: Hamed Panjeh +- **Vendor**: hpwebdeveloper +- **Package**: laravel-pay-pocket +- **Alias name**: Laravel PPP (Laravel Pay Pocket Package) +- **Version**: `1.x` +- **PHP Version**: 8.1+ +- **Laravel Version**: `10.x` +- **[Composer](https://getcomposer.org/):** `composer require hpwebdeveloper/laravel-pay-pocket` ### Support Policy -| Version | Laravel | PHP | Release date | End of improvements | End of support | -|---------|----------------|---------------|--------------|---------------------|----------------| -| 1.x | ^10.0 | 8.1, 8.2, 8.3 | Nov 30, 2023 | Mar 1, 2024 | | | -| x.x | | | | | | | - +| Version | Laravel | PHP | Release date | End of improvements | End of support | +| ------- | ------- | ------------- | ------------ | ------------------- | -------------- | --- | +| 1.x | ^10.0 | 8.1, 8.2, 8.3 | Nov 30, 2023 | Mar 1, 2024 | | | +| x.x | | | | | | | ## Installation: -- **Step 1:** You can install the package via composer: +- **Step 1:** You can install the package via composer: ```bash composer require hpwebdeveloper/laravel-pay-pocket ``` -- **Step 2:** Publish and run the migrations with: +- **Step 2:** Publish and run the migrations with: ```bash php artisan vendor:publish --tag="pay-pocket-migrations" php artisan migrate ``` + You have successfully added two dedicated database tables, `wallets` and `wallets_logs`, without making any modifications to the `users` table. -- **Step 3:** Publish the wallet types using +- **Step 3:** Publish the wallet types using ```bash php artisan vendor:publish --tag="pay-pocket-wallets" ``` +- **Step 4:** Publish the config file + +```bash +php artisan vendor:publish --tag="pay-pocket-config" +``` + This command will automatically publish the `WalletEnums.php` file into your application's `app/Enums` directory. ## Preparation ### Prepare User Model -To use this package you need to implement the `WalletOperations` into `User` model and utilize the `ManagesWallet` trait. +To use this package you need to implement the `WalletOperations` into `User` model and utilize the `ManagesWallet` trait. ```php @@ -75,9 +79,10 @@ class User extends Authenticatable implements WalletOperations ### Prepare Wallets -In Laravel Pay Pocket, you have the flexibility to define the order in which wallets are prioritized for payments through the use of Enums. The order of wallets in the Enum file determines their priority level. The first wallet listed has the highest priority and will be used first for deducting order values. +In Laravel Pay Pocket, you have the flexibility to define the order in which wallets are prioritized for payments through the use of Enums. The order of wallets in the Enum file determines their priority level. The first wallet listed has the highest priority and will be used first for deducting order values. For example, consider the following wallet types defined in the Enum class (published in step 3 of installation): + ```php namespace App\Enums; @@ -88,49 +93,108 @@ enum WalletEnums: string } ``` -**You have complete freedom to name your wallets as per your requirements and even add more wallet types to the Enum list.** +**You have complete freedom to name your wallets as per your requirements and even add more wallet types to the Enum list.** In this particular setup, `wallet_1` (`WALLET1`) is given the **highest priority**. When an order payment is processed, the system will first attempt to use `wallet_1` to cover the cost. If `wallet_1` does not have sufficient funds, `wallet_2` (`WALLET2`) will be used next. ### Example: + If the balance in `wallet_1` is 10 and the balance in `wallet_2` is 20, and you need to pay an order value of 15, the payment process will first utilize the entire balance of `wallet_1`. Since `wallet_1`'s balance is insufficient to cover the full amount, the remaining 5 will be deducted from `wallet_2`. After the payment, `wallet_2` will have a remaining balance of 15." ## Usage, APIs and Operations: + ### Deposit +```php +deposit(type: 'wallet_1', amount: 123.45, detail: null) +``` + +Deposit funds into `wallet_1` + ```php $user = auth()->user(); +$user->deposit('wallet_1', 123.45); +``` -$user->deposit('wallet_1', 123.45); // Deposit funds into 'wallet_1' +Deposit funds into `wallet_2` -$user->deposit('wallet_2', 67.89); // Deposit funds into 'wallet_2' +```php +$user = auth()->user(); +$user->deposit('wallet_2', 67.89); +``` -// Or using provided facade +Or using provided facade +```php use HPWebdeveloper\LaravelPayPocket\Facades\LaravelPayPocket; +$user = auth()->user(); LaravelPayPocket::deposit($user, 'wallet_1', 123.45); ``` + Note: `wallet_1` and `wallet_2` must already be defined in the `WalletEnums`. +#### Transaction Info ([#8][i8]) + +In a case where you want to enter descriptions for a particular transaction, the `$detail` param allows you to provide information about why a transaction happened. + +```php +$user = auth()->user(); +$user->deposit('wallet_1', 67.89, 'You ordered pizza.'); +``` + ### Pay + +```php +pay(amount: 12.34, allowedWallets: [], detail: null) +``` + +Pay the value using the total combined balance available across all allowed wallets + ```php -// Pay the value using the total combined balance available across all wallets +$user = auth()->user(); $user->pay(12.34); - -// Or using provided facade +``` +Or using provided facade + +```php use HPWebdeveloper\LaravelPayPocket\Facades\LaravelPayPocket; +$user = auth()->user(); LaravelPayPocket::pay($user, 12.34); ``` +By default the sytem will attempt to pay using all available wallets exept the `allowedWallets` param is provided. + +#### Allowed Wallets ([#8][i8]) + +Sometimes you want to mark a wallet as restricted so that when the `pay()` method is called, the system does not attempt to charge that wallet, a possible use case is an escrow wallet, the `$allowedWallets` param of the pay method allows you to do just that. + +```php +$user = auth()->user(); +$user->pay(12.34, ['wallet_1']); +``` + +#### Transaction Info ([#8][i8]) + +In a case where you want to enter descriptions for a particular transaction, the `$detail` param allows you to provide information about why a transaction happened. + +```php +$user = auth()->user(); +$user->pay(12.34, [], 'You ordered pizza.'); +``` + +[i8]: https://github.com/HPWebdeveloper/laravel-pay-pocket/issues/8 + ### Balance -- **Wallets** +- **Wallets** + ```php +$user = auth()->user(); $user->walletBalance // Total combined balance available across all wallets // Or using provided facade @@ -138,8 +202,10 @@ $user->walletBalance // Total combined balance available across all wallets LaravelPayPocket::checkBalance($user); ``` -- **Particular Wallet** +- **Particular Wallet** + ```php +$user = auth()->user(); $user->getWalletBalanceByType('wallet_1') // Balance available in wallet_1 $user->getWalletBalanceByType('wallet_2') // Balance available in wallet_2 @@ -149,15 +215,32 @@ LaravelPayPocket::walletBalanceByType($user, 'wallet_1'); ``` ### Exceptions -Upon examining the `src/Exceptions` directory within the source code, + +Upon examining the `src/Exceptions` directory within the source code, you will discover a variety of exceptions tailored to address each scenario of invalid entry. Review the [demo](https://github.com/HPWebdeveloper/demo-pay-pocket) that accounts for some of the exceptions. ### Log +Getting your transaction logs is a pretty straight forward process + +```php +$user = auth()->user(); +$query = $user->wallets() + ->where('type', \App\Enums\WalletEnums::WALLET1) + ->first() + ->logs(); +``` + +This will return an instance of `\Illuminate\Database\Eloquent\Relations\MorphMany` +from there you can handle any manipulations with your data. + +```php +$logs = $query->get(); +``` + A typical `wallets_logs` table. ![Laravel Pay Pocket Log](https://github.com/HPWebdeveloper/laravel-pay-pocket/assets/16323354/a242d335-8bd2-4af1-aa38-4e95b8870941) - ## Testing ```bash @@ -185,9 +268,9 @@ Please review [our security policy](../../security/policy) on how to report secu ## Credits -- [Hamed Panjeh](https://github.com/HPWebdeveloper) -- [All Contributors](../../contributors) -- Icon in the above image: pocket by Creative Mahira from [Noun Project](https://thenounproject.com/browse/icons/term/pocket/) (CC BY 3.0) +- [Hamed Panjeh](https://github.com/HPWebdeveloper) +- [All Contributors](../../contributors) +- Icon in the above image: pocket by Creative Mahira from [Noun Project](https://thenounproject.com/browse/icons/term/pocket/) (CC BY 3.0) ## License diff --git a/config/pay-pocket.php b/config/pay-pocket.php index 4cb9728..1b65891 100644 --- a/config/pay-pocket.php +++ b/config/pay-pocket.php @@ -2,5 +2,11 @@ // config for HPWebdeveloper/LaravelPayPocket return [ - -]; + 'log_reference_length' => 12, + 'log_reference_prefix' => null, + /** + * The log reference generator should be static + * The third array item should contain optional parameters to pass to the generator + */ + 'log_reference_generator' => [\Illuminate\Support\Str::class, 'random', [15]], +]; \ No newline at end of file diff --git a/database/migrations/update_wallets_logs_table.php.stub b/database/migrations/update_wallets_logs_table.php.stub new file mode 100644 index 0000000..5ae26a8 --- /dev/null +++ b/database/migrations/update_wallets_logs_table.php.stub @@ -0,0 +1,38 @@ +string('detail')->nullable()->after('status'); + } + if (!Schema::hasColumn('wallets_logs', 'reference')) { + $table->string('reference')->nullable()->after('ip'); + } + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('wallets_logs', function (Blueprint $table) { + if (Schema::hasColumn('wallets_logs', 'detail')) { + $table->dropColumn('detail'); + } + if (Schema::hasColumn('wallets_logs', 'reference')) { + $table->dropColumn('reference'); + } + }); + } +}; diff --git a/src/Facades/LaravelPayPocket.php b/src/Facades/LaravelPayPocket.php index 1c33b5f..06f8ce6 100644 --- a/src/Facades/LaravelPayPocket.php +++ b/src/Facades/LaravelPayPocket.php @@ -6,6 +6,11 @@ /** * @see \HPWebdeveloper\LaravelPayPocket\Services\PocketServices + * + * @method static void pay($user, int|float $orderValue, array $allowedWallets = [], ?string $detail = null) + * @method static bool deposit($user, string $type, int|float $amount, ?string $detail = null) + * @method static int|float checkBalance($user) + * @method static int|float walletBalanceByType($user, string $type) */ class LaravelPayPocket extends Facade { diff --git a/src/Interfaces/WalletOperations.php b/src/Interfaces/WalletOperations.php index 42742ef..a8198d4 100644 --- a/src/Interfaces/WalletOperations.php +++ b/src/Interfaces/WalletOperations.php @@ -4,13 +4,51 @@ interface WalletOperations { - public function getWalletBalanceAttribute(); + /** + * Get User's Wallet Balance + * + * @return int|float + */ + public function getWalletBalanceAttribute(): int|float; - public function getWalletBalanceByType(string $walletType); + /** + * Get the balance of a specific wallet type. + * + * + * @param string $walletType + * + * @return float|int + */ + public function getWalletBalanceByType(string $walletType): float|int; - public function hasSufficientBalance($value): bool; + /** + * Check if User's wallet balance is more than given value + * + * @param int|float $value + * + * @return bool + */ + public function hasSufficientBalance(int|float $value): bool; - public function pay(int|float $orderValue); + /** + * Pay the order value from the user's wallets. + * + * @param int|float $orderValue + * @param array $allowedWallets + * @param ?string $detail + * + * @throws InsufficientBalanceException + */ + public function pay(int|float $orderValue, array $allowedWallets = [], ?string $detail = null): void; - public function deposit(string $type, int|float $amount): bool; + /** + * Deposit an amount to the user's wallet of a specific type. + * + * @param string $type + * @param int|float $amount + * @param ?string $detail + * + * @return bool + */ + public function deposit(string $type, int|float $amount, ?string $detail = null): bool; } diff --git a/src/LaravelPayPocketServiceProvider.php b/src/LaravelPayPocketServiceProvider.php index f58c9ae..4166a74 100644 --- a/src/LaravelPayPocketServiceProvider.php +++ b/src/LaravelPayPocketServiceProvider.php @@ -18,13 +18,28 @@ public function configurePackage(Package $package): void ->name('laravel-pay-pocket') ->hasConfigFile() ->hasViews() - ->hasMigrations('create_wallets_logs_table', 'create_wallets_table'); + ->hasMigrations( + 'create_wallets_logs_table', + 'create_wallets_table', + 'update_wallets_logs_table' + ); } public function bootingPackage() { $this->publishes([ - __DIR__.'/../Enums/' => app_path('Enums'), + __DIR__ . '/../Enums/' => app_path('Enums'), ], 'pay-pocket-wallets'); + + + $this->publishes([ + __DIR__ . '/../config/pay-pocket.php' => config_path('pay-pocket.php'), + ], 'pay-pocket-config'); + } + + public function registeringPackage() + { + // Automatically apply the package configuration + $this->mergeConfigFrom(__DIR__ . '/../config/pay-pocket.php', 'pay-pocket'); } -} +} \ No newline at end of file diff --git a/src/Models/WalletsLog.php b/src/Models/WalletsLog.php index ca751e2..0f55988 100644 --- a/src/Models/WalletsLog.php +++ b/src/Models/WalletsLog.php @@ -16,7 +16,14 @@ class WalletsLog extends Model use HasFactory; protected $fillable = [ - 'from', 'to', 'type', 'ip', 'value', 'wallet_name', + 'from', + 'to', + 'type', + 'ip', + 'value', + 'wallet_name', + 'detail', + 'reference', ]; public function loggable(): MorphTo @@ -30,4 +37,4 @@ public function changeStatus($status) return $this->save(); } -} +} \ No newline at end of file diff --git a/src/Services/PocketServices.php b/src/Services/PocketServices.php index 1fe31cc..43fd785 100644 --- a/src/Services/PocketServices.php +++ b/src/Services/PocketServices.php @@ -4,22 +4,60 @@ class PocketServices { - public function deposit($user, $type, $amount) + /** + * Deposit an amount to the user's wallet of a specific type. + * + * @param $user + * @param string $type + * @param int|float $amount + * @param ?string $detail + * + * @return bool + */ + public function deposit($user, string $type, int|float $amount, ?string $detail = null): bool { - return $user->deposit($type, $amount); + return $user->deposit($type, $amount, $detail); } - public function pay($user, $orderValue) + /** + * Pay the order value from the user's wallets. + * + * @param $user + * @param int|float $orderValue + * @param array $allowedWallets + * @param ?string $detail + * + * @return void + * @throws InsufficientBalanceException + */ + public function pay($user, $orderValue, array $allowedWallets = [], ?string $detail = null): void { - return $user->pay($orderValue); + return $user->pay($orderValue, $allowedWallets, $detail); } - public function checkBalance($user) + /** + * Get the balance of the user. + * + * + * @param $user + * + * @return float|int + */ + public function checkBalance($user): float|int { return $user->walletBalance; } - public function walletBalanceByType($user, $type) + /** + * Get the balance of a specific wallet type. + * + * + * @param $user + * @param string $type + * + * @return float|int + */ + public function walletBalanceByType($user, string $type): float|int { return $user->getWalletBalanceByType($type); } diff --git a/src/Traits/BalanceOperation.php b/src/Traits/BalanceOperation.php index ae895ef..a08ae70 100644 --- a/src/Traits/BalanceOperation.php +++ b/src/Traits/BalanceOperation.php @@ -2,12 +2,16 @@ namespace HPWebdeveloper\LaravelPayPocket\Traits; +use Illuminate\Support\Str; + trait BalanceOperation { protected $createdLog; /** - * Check if Balance is more than zero. + * Check if Balance is more than zero. + * + * @return bool */ public function hasBalance(): bool { @@ -15,32 +19,56 @@ public function hasBalance(): bool } /** - * Decrement Balance and create a log entry. + * Decrement Balance and create a log entry. + * + * @param int|float $value + * @param ?string $detail + * + * @return void */ - public function decrementAndCreateLog($value): void + public function decrementAndCreateLog($value, ?string $detail = null): void { - $this->createLog('dec', $value); + $this->createLog('dec', $value, $detail); $this->decrement('balance', $value); } /** - * Increment Balance and create a log entry. + * Increment Balance and create a log entry. + * + * @param int|float $value + * @param ?string $detail + * + * @return void */ - public function incrementAndCreateLog($value): void + public function incrementAndCreateLog($value, ?string $detail = null): void { - $this->createLog('inc', $value); + $this->createLog('inc', $value, $detail); $this->increment('balance', $value); } /** - * Create a new log record + * Create a new log record + * + * @param string $logType + * @param int|float $value + * @param ?string $detail + * + * @return void */ - protected function createLog($logType, $value): void + protected function createLog($logType, $value, ?string $detail = null): void { $currentBalance = $this->balance ?? 0; $newBalance = $logType === 'dec' ? $currentBalance - $value : $currentBalance + $value; + $refGen = config('pay-pocket.log_reference_generator', [Str::class, 'random', [12]]); + + $reference = config('pay-pocket.log_reference_prefix', ''); + + $reference .= isset($refGen[0], $refGen[1]) + ? $refGen[0]::{$refGen[1]}(...$refGen[2] ?? []) + : Str::random(config('pay-pocket.log_reference_length', 12)); + $this->createdLog = $this->logs()->create([ 'wallet_name' => $this->type->value, 'from' => $currentBalance, @@ -48,8 +76,10 @@ protected function createLog($logType, $value): void 'type' => $logType, 'ip' => \Request::ip(), 'value' => $value, + 'detail' => $detail, + 'reference' => $reference ]); $this->createdLog->changeStatus('Done'); } -} +} \ No newline at end of file diff --git a/src/Traits/HandlesDeposit.php b/src/Traits/HandlesDeposit.php index 108c1ac..b7a310c 100644 --- a/src/Traits/HandlesDeposit.php +++ b/src/Traits/HandlesDeposit.php @@ -14,8 +14,14 @@ trait HandlesDeposit { /** * Deposit an amount to the user's wallet of a specific type. + * + * @param string $type + * @param int|float $amount + * @param ?string $detail + * + * @return bool */ - public function deposit(string $type, int|float $amount): bool + public function deposit(string $type, int|float $amount, ?string $detail = null): bool { $depositable = $this->getDepositableTypes(); @@ -27,10 +33,10 @@ public function deposit(string $type, int|float $amount): bool throw new InvalidValueException(); } - DB::transaction(function () use ($type, $amount) { + DB::transaction(function () use ($type, $amount, $detail) { $type = WalletEnums::tryFrom($type); $wallet = $this->wallets()->firstOrCreate(['type' => $type]); - $wallet->incrementAndCreateLog($amount); + $wallet->incrementAndCreateLog($amount, $detail); }); return true; @@ -38,6 +44,8 @@ public function deposit(string $type, int|float $amount): bool /** * Get depositable types from WalletEnums. + * + * @return array */ private function getDepositableTypes(): array { @@ -52,7 +60,9 @@ private function getDepositableTypes(): array /** * Check if the given tyep is valid. * - * @param string $type + * @var string $type + * @var array $depositable + * * @return bool */ private function isRequestValid($type, array $depositable) diff --git a/src/Traits/HandlesPayment.php b/src/Traits/HandlesPayment.php index 2e31745..6a632a1 100644 --- a/src/Traits/HandlesPayment.php +++ b/src/Traits/HandlesPayment.php @@ -10,27 +10,37 @@ trait HandlesPayment /** * Pay the order value from the user's wallets. * + * @param int|float $orderValue + * @param array $allowedWallets + * @param ?string $detail * + * @return void * @throws InsufficientBalanceException */ - public function pay(int|float $orderValue): void + public function pay(int|float $orderValue, array $allowedWallets = [], ?string $detail = null): void { if (! $this->hasSufficientBalance($orderValue)) { throw new InsufficientBalanceException('Insufficient balance to cover the order.'); } - DB::transaction(function () use ($orderValue) { + DB::transaction(function () use ($orderValue, $detail, $allowedWallets) { $remainingOrderValue = $orderValue; $walletsInOrder = $this->wallets()->whereIn('type', $this->walletsInOrder())->get(); + /** + * @param string $wallet + * @return bool $useWallet + * */ + $useWallet = fn ($wallet) => count($allowedWallets) < 1 || in_array($wallet, $allowedWallets); + foreach ($walletsInOrder as $wallet) { - if (! $wallet || ! $wallet->hasBalance()) { + if (! $wallet || ! $wallet->hasBalance() || !$useWallet($wallet->type->value)) { continue; } $amountToDeduct = min($wallet->balance, $remainingOrderValue); - $wallet->decrementAndCreateLog($amountToDeduct); + $wallet->decrementAndCreateLog($amountToDeduct, $detail); $remainingOrderValue -= $amountToDeduct; if ($remainingOrderValue <= 0) { diff --git a/src/Traits/HasWallet.php b/src/Traits/HasWallet.php index d30ca89..b9de74d 100644 --- a/src/Traits/HasWallet.php +++ b/src/Traits/HasWallet.php @@ -22,9 +22,11 @@ public function wallets() } /** - * Get User's Wallet Balance + * Get User's Wallet Balance + * + * @return int|float */ - public function getWalletBalanceAttribute() + public function getWalletBalanceAttribute(): int|float { $totalBalance = 0; @@ -39,11 +41,14 @@ public function getWalletBalanceAttribute() } return $totalBalance; - } /** * Check if User's wallet balance is more than given value + * + * @param int|float $value + * + * @return bool */ public function hasSufficientBalance($value): bool { @@ -53,9 +58,12 @@ public function hasSufficientBalance($value): bool /** * Get the balance of a specific wallet type. * + * + * @param string $walletType + * * @return float|int */ - public function getWalletBalanceByType(string $walletType) + public function getWalletBalanceByType(string $walletType): float|int { if (! WalletEnums::isValid($walletType)) { throw new InvalidWalletTypeException("Invalid wallet type '{$walletType}'."); diff --git a/src/Traits/ManagesWallet.php b/src/Traits/ManagesWallet.php index 13fcaa8..b6f5dc6 100644 --- a/src/Traits/ManagesWallet.php +++ b/src/Traits/ManagesWallet.php @@ -4,5 +4,7 @@ trait ManagesWallet { - use HandlesDeposit, HandlesPayment, HasWallet; + use HandlesDeposit; + use HandlesPayment; + use HasWallet; } diff --git a/tests/Models/User.php b/tests/Models/User.php index 7a10991..c9a560a 100644 --- a/tests/Models/User.php +++ b/tests/Models/User.php @@ -11,7 +11,8 @@ class User extends Authenticatable implements WalletOperations { - use HasFactory, Notifiable; + use HasFactory; + use Notifiable; use ManagesWallet; /** diff --git a/tests/OperationsWithFacadeTest.php b/tests/OperationsWithFacadeTest.php index 24a5c5c..5e5fdf9 100644 --- a/tests/OperationsWithFacadeTest.php +++ b/tests/OperationsWithFacadeTest.php @@ -18,7 +18,6 @@ expect(LaravelPayPocket::walletBalanceByType($user, 'wallet_2'))->toBeFloat(234.56); expect(LaravelPayPocket::checkBalance($user))->toBeFloat(234.56); - }); test('user can deposit two times', function () { @@ -34,7 +33,6 @@ expect(LaravelPayPocket::walletBalanceByType($user, 'wallet_2'))->toBeFloat(1023.68); expect(LaravelPayPocket::checkBalance($user))->toBeFloat(1023.68); - }); test('user can pay order', function () { @@ -96,4 +94,4 @@ expect(LaravelPayPocket::walletBalanceByType($user, 'wallet_2'))->toBeFloat(0.12); expect(LaravelPayPocket::checkBalance($user))->toBeFloat(0.12); -}); +}); \ No newline at end of file