From 22046a890f1026ed54048657ba5ce7c10e78fdc8 Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 17 Nov 2025 20:44:19 +0300 Subject: [PATCH 1/3] Refactor PHPDoc comments and improve type hints across multiple interfaces and models - Removed redundant PHPDoc comments in the Confirmable and ProductLimitedInterface interfaces. - Updated PHPDoc comments to include type hints for return values in various DTOs and services. - Enhanced type safety by specifying generic types in relationships within the Wallet model and related traits. - Cleaned up unused comments and improved clarity in method signatures across several classes. - Ensured consistency in type declarations and added assertions where necessary for better code quality. --- phpstan.src.baseline.neon | 408 +----------------- src/Interfaces/Confirmable.php | 47 -- src/Interfaces/ProductLimitedInterface.php | 16 - src/Interfaces/Wallet.php | 98 +---- src/Interfaces/WalletFloat.php | 83 +--- .../Assembler/TransactionDtoAssembler.php | 5 +- .../Assembler/TransferDtoAssembler.php | 11 +- .../Decorator/StorageServiceLockDecorator.php | 20 +- src/Internal/Dto/ItemDto.php | 16 +- src/Internal/Dto/TransactionDto.php | 24 +- src/Internal/Dto/TransferDto.php | 16 +- src/Internal/Dto/TransferLazyDto.php | 16 +- src/Internal/Events/BalanceUpdatedEvent.php | 16 +- src/Internal/Events/WalletCreatedEvent.php | 8 +- .../Observers/TransactionObserver.php | 1 - src/Internal/Observers/TransferObserver.php | 1 - src/Internal/Repository/WalletRepository.php | 6 +- src/Internal/Service/ConnectionService.php | 4 +- src/Internal/Service/LockService.php | 4 +- src/Internal/Service/MathServiceInterface.php | 123 ++---- src/Internal/Service/StateService.php | 11 +- src/Internal/Service/StorageService.php | 29 +- .../Service/StorageServiceInterface.php | 2 - src/Models/Transaction.php | 17 +- src/Models/Transfer.php | 32 +- src/Models/Wallet.php | 41 +- src/Objects/Cart.php | 29 +- src/Services/BookkeeperServiceInterface.php | 9 - src/Services/ConsistencyServiceInterface.php | 7 - src/Services/RegulatorServiceInterface.php | 64 +-- src/Traits/CanConfirm.php | 14 - src/Traits/HasWallet.php | 60 ++- src/Traits/HasWalletFloat.php | 131 +++--- src/Traits/HasWallets.php | 13 +- src/Traits/MorphOneWallet.php | 27 +- 35 files changed, 459 insertions(+), 950 deletions(-) diff --git a/phpstan.src.baseline.neon b/phpstan.src.baseline.neon index faf79a45d..96571d719 100644 --- a/phpstan.src.baseline.neon +++ b/phpstan.src.baseline.neon @@ -25,351 +25,45 @@ parameters: path: src/External/Dto/Option.php - - message: '#^Generic type Illuminate\\Database\\Eloquent\\Relations\\HasMany\ in PHPDoc tag @return does not specify all template types of class Illuminate\\Database\\Eloquent\\Relations\\HasMany\: TRelatedModel, TDeclaringModel$#' - identifier: generics.lessTypes + message: '#^Type Bavix\\Wallet\\Interfaces\\Wallet in generic type Illuminate\\Database\\Eloquent\\Relations\\HasMany\ in PHPDoc tag @return is not subtype of template type TDeclaringModel of Illuminate\\Database\\Eloquent\\Model of class Illuminate\\Database\\Eloquent\\Relations\\HasMany\.$#' + identifier: generics.notSubtype count: 1 path: src/Interfaces/Wallet.php - - message: '#^Generic type Illuminate\\Database\\Eloquent\\Relations\\HasMany\ in PHPDoc tag @return does not specify all template types of class Illuminate\\Database\\Eloquent\\Relations\\HasMany\: TRelatedModel, TDeclaringModel$#' - identifier: generics.lessTypes + message: '#^Type Bavix\\Wallet\\Interfaces\\Wallet in generic type Illuminate\\Database\\Eloquent\\Relations\\HasMany\ in PHPDoc tag @return is not subtype of template type TDeclaringModel of Illuminate\\Database\\Eloquent\\Model of class Illuminate\\Database\\Eloquent\\Relations\\HasMany\.$#' + identifier: generics.notSubtype count: 2 path: src/Interfaces/Wallet.php - - - message: '#^Generic type Illuminate\\Database\\Eloquent\\Relations\\MorphMany\ in PHPDoc tag @return does not specify all template types of class Illuminate\\Database\\Eloquent\\Relations\\MorphMany\: TRelatedModel, TDeclaringModel$#' - identifier: generics.lessTypes - count: 1 - path: src/Interfaces/Wallet.php - - - - message: '#^Parameter \#3 \$payableId of class Bavix\\Wallet\\Internal\\Dto\\TransactionDto constructor expects int\|string, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Internal/Assembler/TransactionDtoAssembler.php - - - - message: '#^Parameter \#5 \$fromId of class Bavix\\Wallet\\Internal\\Dto\\TransferDto constructor expects int, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Internal/Assembler/TransferDtoAssembler.php - - - - message: '#^Parameter \#6 \$toId of class Bavix\\Wallet\\Internal\\Dto\\TransferDto constructor expects int, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Internal/Assembler/TransferDtoAssembler.php - - - - message: '#^Call to function assert\(\) with true will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: src/Internal/Decorator/StorageServiceLockDecorator.php - - - - message: '#^Strict comparison using \!\=\= between non\-empty\-array\ and array\{\} will always evaluate to true\.$#' - identifier: notIdentical.alwaysTrue - count: 1 - path: src/Internal/Decorator/StorageServiceLockDecorator.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\ItemDto\:\:count\(\) should return int\<0, max\> but returns int\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/ItemDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\ItemDto\:\:getPricePerItem\(\) should return int\|non\-empty\-string\|null but returns int\|string\|null\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/ItemDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\TransactionDto\:\:getAmount\(\) should return float\|int\|non\-empty\-string but returns float\|int\|string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/TransactionDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\TransactionDto\:\:getPayableType\(\) should return class\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/TransactionDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\TransactionDto\:\:getUuid\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/TransactionDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\TransferDto\:\:getFee\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/TransferDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\TransferDto\:\:getUuid\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/TransferDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\TransferLazyDto\:\:getFee\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/TransferLazyDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Dto\\TransferLazyDto\:\:getUuid\(\) should return non\-empty\-string\|null but returns string\|null\.$#' - identifier: return.type - count: 1 - path: src/Internal/Dto/TransferLazyDto.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Events\\BalanceUpdatedEvent\:\:getBalance\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Events/BalanceUpdatedEvent.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Events\\BalanceUpdatedEvent\:\:getWalletUuid\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Events/BalanceUpdatedEvent.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Events\\WalletCreatedEvent\:\:getWalletUuid\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Events/WalletCreatedEvent.php - - - - message: '#^Call to function assert\(\) with true will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: src/Internal/Repository/WalletRepository.php - - - - message: '#^Instanceof between Bavix\\Wallet\\Models\\Wallet and Bavix\\Wallet\\Models\\Wallet will always evaluate to true\.$#' - identifier: instanceof.alwaysTrue - count: 1 - path: src/Internal/Repository/WalletRepository.php - - - - message: '#^Parameter \#1 \$name of method Illuminate\\Database\\ConnectionResolverInterface\:\:connection\(\) expects string\|UnitEnum\|null, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Internal/Service/ConnectionService.php - - - - message: '#^Parameter \#1 \$name of method Illuminate\\Contracts\\Cache\\Factory\:\:store\(\) expects string\|null, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Internal/Service/LockService.php - - - - message: '#^Binary operation "\." between ''wallet_f\:\:'' and mixed results in an error\.$#' - identifier: binaryOp.invalid - count: 2 - path: src/Internal/Service/StateService.php - - - - message: '#^Binary operation "\." between ''wallet_hm\:\:'' and mixed results in an error\.$#' - identifier: binaryOp.invalid - count: 2 - path: src/Internal/Service/StateService.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Service\\StateService\:\:get\(\) should return non\-empty\-string\|null but returns mixed\.$#' - identifier: return.type - count: 1 - path: src/Internal/Service/StateService.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Service\\StateService\:\:get\(\) should return non\-empty\-string\|null but returns string\|null\.$#' - identifier: return.type - count: 1 - path: src/Internal/Service/StateService.php - - - - message: '#^Call to function assert\(\) with true will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: src/Internal/Service/StorageService.php - - - - message: '#^Method Bavix\\Wallet\\Internal\\Service\\StorageService\:\:increase\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Internal/Service/StorageService.php - - - - message: '#^Parameter \#1 \$number of method Bavix\\Wallet\\Internal\\Service\\MathServiceInterface\:\:round\(\) expects float\|int\|non\-empty\-string, float\|int\|string given\.$#' - identifier: argument.type - count: 1 - path: src/Internal/Service/StorageService.php - - - - message: '#^Parameter \#1 \$uuids of method Bavix\\Wallet\\Internal\\Service\\StorageService\:\:multiGet\(\) expects non\-empty\-array\, non\-empty\-list\ given\.$#' - identifier: argument.type - count: 1 - path: src/Internal/Service/StorageService.php - - - - message: '#^Parameter \#2 \$second of method Bavix\\Wallet\\Internal\\Service\\MathServiceInterface\:\:add\(\) expects float\|int\|non\-empty\-string, float\|int\|string given\.$#' - identifier: argument.type - count: 1 - path: src/Internal/Service/StorageService.php - - - - message: '#^Strict comparison using \!\=\= between non\-empty\-array\ and array\{\} will always evaluate to true\.$#' - identifier: notIdentical.alwaysTrue - count: 1 - path: src/Internal/Service/StorageService.php - - message: '#^Method Bavix\\Wallet\\Models\\Transaction\:\:payable\(\) should return Illuminate\\Database\\Eloquent\\Relations\\MorphTo\ but returns Illuminate\\Database\\Eloquent\\Relations\\MorphTo\\.$#' identifier: return.type count: 1 path: src/Models/Transaction.php - - - message: '#^Method Bavix\\Wallet\\Models\\Transaction\:\:wallet\(\) should return Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\ but returns Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\\.$#' - identifier: return.type - count: 1 - path: src/Models/Transaction.php - - message: '#^PHPDoc type array\ of property Bavix\\Wallet\\Models\\Transaction\:\:\$fillable is not covariant with PHPDoc type list\ of overridden property Illuminate\\Database\\Eloquent\\Model\:\:\$fillable\.$#' identifier: property.phpDocType count: 1 path: src/Models/Transaction.php - - - message: '#^Parameter \#1 \$first of method Bavix\\Wallet\\Internal\\Service\\MathServiceInterface\:\:mul\(\) expects float\|int\|non\-empty\-string, float\|int\|string given\.$#' - identifier: argument.type - count: 1 - path: src/Models/Transaction.php - - - - message: '#^Parameter \#1 \$related of method Illuminate\\Database\\Eloquent\\Model\:\:belongsTo\(\) expects class\-string\, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Models/Transaction.php - - - - message: '#^Property Illuminate\\Database\\Eloquent\\Model\:\:\$table \(string\|null\) does not accept mixed\.$#' - identifier: assign.propertyType - count: 1 - path: src/Models/Transaction.php - - - - message: '#^Unable to resolve the template type TRelatedModel in call to method Illuminate\\Database\\Eloquent\\Model\:\:belongsTo\(\)$#' - identifier: argument.templateType - count: 1 - path: src/Models/Transaction.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Transfer\:\:deposit\(\) should return Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\ but returns Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\\.$#' - identifier: return.type - count: 1 - path: src/Models/Transfer.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Transfer\:\:from\(\) should return Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\ but returns Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\\.$#' - identifier: return.type - count: 1 - path: src/Models/Transfer.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Transfer\:\:to\(\) should return Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\ but returns Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\\.$#' - identifier: return.type - count: 1 - path: src/Models/Transfer.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Transfer\:\:withdraw\(\) should return Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\ but returns Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\\.$#' - identifier: return.type - count: 1 - path: src/Models/Transfer.php - - message: '#^PHPDoc type array\ of property Bavix\\Wallet\\Models\\Transfer\:\:\$fillable is not covariant with PHPDoc type list\ of overridden property Illuminate\\Database\\Eloquent\\Model\:\:\$fillable\.$#' identifier: property.phpDocType count: 1 path: src/Models/Transfer.php - - - message: '#^Parameter \#1 \$related of method Illuminate\\Database\\Eloquent\\Model\:\:belongsTo\(\) expects class\-string\, mixed given\.$#' - identifier: argument.type - count: 4 - path: src/Models/Transfer.php - - - - message: '#^Property Illuminate\\Database\\Eloquent\\Model\:\:\$table \(string\|null\) does not accept mixed\.$#' - identifier: assign.propertyType - count: 1 - path: src/Models/Transfer.php - - - - message: '#^Unable to resolve the template type TRelatedModel in call to method Illuminate\\Database\\Eloquent\\Model\:\:belongsTo\(\)$#' - identifier: argument.templateType - count: 4 - path: src/Models/Transfer.php - - message: '#^Binary operation "\." between literal\-string&non\-falsy\-string and mixed results in an error\.$#' identifier: binaryOp.invalid count: 1 path: src/Models/Wallet.php - - - message: '#^Call to function assert\(\) with true and ''Balance should not…'' will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: src/Models/Wallet.php - - message: '#^Cannot cast mixed to string\.$#' identifier: cast.string - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Generic type Illuminate\\Database\\Eloquent\\Relations\\HasMany\ in PHPDoc tag @return does not specify all template types of class Illuminate\\Database\\Eloquent\\Relations\\HasMany\: TRelatedModel, TDeclaringModel$#' - identifier: generics.lessTypes - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Generic type Illuminate\\Database\\Eloquent\\Relations\\HasMany\ in PHPDoc tag @return does not specify all template types of class Illuminate\\Database\\Eloquent\\Relations\\HasMany\: TRelatedModel, TDeclaringModel$#' - identifier: generics.lessTypes - count: 4 - path: src/Models/Wallet.php - - - - message: '#^Generic type Illuminate\\Database\\Eloquent\\Relations\\MorphMany\ in PHPDoc tag @return does not specify all template types of class Illuminate\\Database\\Eloquent\\Relations\\MorphMany\: TRelatedModel, TDeclaringModel$#' - identifier: generics.lessTypes - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Generic type Illuminate\\Database\\Eloquent\\Relations\\MorphOne\ in PHPDoc tag @return does not specify all template types of class Illuminate\\Database\\Eloquent\\Relations\\MorphOne\: TRelatedModel, TDeclaringModel$#' - identifier: generics.lessTypes - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Wallet\:\:getBalanceFloatAttribute\(\) should return non\-empty\-string but returns string\.$#' - identifier: return.type - count: 1 - path: src/Models/Wallet.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Wallet\:\:getCurrencyAttribute\(\) should return string but returns mixed\.$#' - identifier: return.type - count: 1 + count: 5 path: src/Models/Wallet.php - @@ -378,36 +72,6 @@ parameters: count: 1 path: src/Models/Wallet.php - - - message: '#^Method Bavix\\Wallet\\Models\\Wallet\:\:receivedTransfers\(\) should return Illuminate\\Database\\Eloquent\\Relations\\HasMany\ but returns Illuminate\\Database\\Eloquent\\Relations\\HasMany\\.$#' - identifier: return.type - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Wallet\:\:transactions\(\) should return Illuminate\\Database\\Eloquent\\Relations\\MorphMany\ but returns Illuminate\\Database\\Eloquent\\Relations\\MorphMany\\.$#' - identifier: return.type - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Wallet\:\:transfers\(\) should return Illuminate\\Database\\Eloquent\\Relations\\HasMany\ but returns Illuminate\\Database\\Eloquent\\Relations\\HasMany\\.$#' - identifier: return.type - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Wallet\:\:wallet\(\) should return Illuminate\\Database\\Eloquent\\Relations\\MorphOne\ but returns Illuminate\\Database\\Eloquent\\Relations\\MorphOne\\.$#' - identifier: return.type - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Method Bavix\\Wallet\\Models\\Wallet\:\:walletTransactions\(\) should return Illuminate\\Database\\Eloquent\\Relations\\HasMany\ but returns Illuminate\\Database\\Eloquent\\Relations\\HasMany\\.$#' - identifier: return.type - count: 2 - path: src/Models/Wallet.php - - message: '#^PHPDoc tag @var with type Bavix\\Wallet\\Interfaces\\Wallet is not subtype of native type \$this\(Bavix\\Wallet\\Models\\Wallet\)\.$#' identifier: varTag.nativeType @@ -426,12 +90,6 @@ parameters: count: 2 path: src/Models/Wallet.php - - - message: '#^Parameter \#1 \$attributes of method Illuminate\\Database\\Eloquent\\Model\:\:forceFill\(\) expects array\, array\ given\.$#' - identifier: argument.type - count: 2 - path: src/Models/Wallet.php - - message: '#^Parameter \#1 \$first of method Bavix\\Wallet\\Internal\\Service\\MathServiceInterface\:\:add\(\) expects float\|int\|non\-empty\-string, int\|string given\.$#' identifier: argument.type @@ -441,7 +99,7 @@ parameters: - message: '#^Parameter \#1 \$first of method Bavix\\Wallet\\Internal\\Service\\MathServiceInterface\:\:mul\(\) expects float\|int\|non\-empty\-string, float\|int\|string given\.$#' identifier: argument.type - count: 7 + count: 1 path: src/Models/Wallet.php - @@ -450,24 +108,6 @@ parameters: count: 1 path: src/Models/Wallet.php - - - message: '#^Parameter \#1 \$related of method Illuminate\\Database\\Eloquent\\Model\:\:hasMany\(\) expects class\-string\, mixed given\.$#' - identifier: argument.type - count: 6 - path: src/Models/Wallet.php - - - - message: '#^Parameter \#1 \$related of method Illuminate\\Database\\Eloquent\\Model\:\:morphMany\(\) expects class\-string\, mixed given\.$#' - identifier: argument.type - count: 2 - path: src/Models/Wallet.php - - - - message: '#^Parameter \#1 \.\.\.\$arrays of function array_merge expects array, mixed given\.$#' - identifier: argument.type - count: 2 - path: src/Models/Wallet.php - - message: '#^Parameter \#2 \$amount of method Bavix\\Wallet\\Interfaces\\Wallet\:\:forceTransfer\(\) expects int\|non\-empty\-string, int\|string given\.$#' identifier: argument.type @@ -480,12 +120,6 @@ parameters: count: 5 path: src/Models/Wallet.php - - - message: '#^Parameter \#2 \$second of method Bavix\\Wallet\\Internal\\Service\\MathServiceInterface\:\:compare\(\) expects float\|int\|non\-empty\-string, float\|int\|string given\.$#' - identifier: argument.type - count: 1 - path: src/Models/Wallet.php - - message: '#^Parameter \#2 \$second of method Bavix\\Wallet\\Internal\\Service\\MathServiceInterface\:\:mul\(\) expects float\|int\|non\-empty\-string, string given\.$#' identifier: argument.type @@ -493,33 +127,21 @@ parameters: path: src/Models/Wallet.php - - message: '#^Parameter \#2 \$value of method Bavix\\Wallet\\Services\\RegulatorServiceInterface\:\:sync\(\) expects float\|int\|non\-empty\-string, float\|int\|string given\.$#' - identifier: argument.type - count: 1 - path: src/Models/Wallet.php - - - - message: '#^Property Illuminate\\Database\\Eloquent\\Model\:\:\$table \(string\|null\) does not accept mixed\.$#' - identifier: assign.propertyType - count: 1 - path: src/Models/Wallet.php - - - - message: '#^Strict comparison using \!\=\= between float\|int\|numeric\-string and '''' will always evaluate to true\.$#' - identifier: notIdentical.alwaysTrue - count: 1 + message: '#^Return type \(Illuminate\\Database\\Eloquent\\Relations\\HasMany\\) of method Bavix\\Wallet\\Models\\Wallet\:\:walletTransactions\(\) should be compatible with return type \(Illuminate\\Database\\Eloquent\\Relations\\HasMany\\) of method Bavix\\Wallet\\Interfaces\\Wallet\:\:walletTransactions\(\)$#' + identifier: method.childReturnType + count: 4 path: src/Models/Wallet.php - - message: '#^Unable to resolve the template type TRelatedModel in call to method Illuminate\\Database\\Eloquent\\Model\:\:hasMany\(\)$#' - identifier: argument.templateType - count: 6 + message: '#^Return type \(Illuminate\\Database\\Eloquent\\Relations\\HasMany\\) of method Bavix\\Wallet\\Models\\Wallet\:\:receivedTransfers\(\) should be compatible with return type \(Illuminate\\Database\\Eloquent\\Relations\\HasMany\\) of method Bavix\\Wallet\\Interfaces\\Wallet\:\:receivedTransfers\(\)$#' + identifier: method.childReturnType + count: 4 path: src/Models/Wallet.php - - message: '#^Unable to resolve the template type TRelatedModel in call to method Illuminate\\Database\\Eloquent\\Model\:\:morphMany\(\)$#' - identifier: argument.templateType - count: 2 + message: '#^Return type \(Illuminate\\Database\\Eloquent\\Relations\\HasMany\\) of method Bavix\\Wallet\\Models\\Wallet\:\:transfers\(\) should be compatible with return type \(Illuminate\\Database\\Eloquent\\Relations\\HasMany\\) of method Bavix\\Wallet\\Interfaces\\Wallet\:\:transfers\(\)$#' + identifier: method.childReturnType + count: 4 path: src/Models/Wallet.php - diff --git a/src/Interfaces/Confirmable.php b/src/Interfaces/Confirmable.php index 6196aef43..72b489448 100644 --- a/src/Interfaces/Confirmable.php +++ b/src/Interfaces/Confirmable.php @@ -18,13 +18,6 @@ interface Confirmable { /** - * Confirm the transaction. - * - * This method confirms the given transaction if it is not already confirmed. - * - * @param Transaction $transaction The transaction to confirm. - * @return bool Returns true if the transaction was confirmed, false otherwise. - * * @throws BalanceIsEmpty If the balance is empty. * @throws InsufficientFunds If there are insufficient funds. * @throws ConfirmedInvalid If the transaction is already confirmed. @@ -37,15 +30,6 @@ interface Confirmable public function confirm(Transaction $transaction): bool; /** - * Safely confirms the transaction. - * - * This method attempts to confirm the given transaction. If an exception occurs during the confirmation process, - * it will be caught and handled. If the confirmation is successful, true will be returned. If an exception occurs, - * false will be returned. - * - * @param Transaction $transaction The transaction to confirm. - * @return bool Returns true if the transaction was confirmed, false otherwise. - * * @throws BalanceIsEmpty If the balance is empty. * @throws InsufficientFunds If there are insufficient funds. * @throws ConfirmedInvalid If the transaction is already confirmed. @@ -58,16 +42,6 @@ public function confirm(Transaction $transaction): bool; public function safeConfirm(Transaction $transaction): bool; /** - * Reset the confirmation of the transaction. - * - * This method is used to remove the confirmation from a transaction. - * If the transaction is already confirmed, a `ConfirmedInvalid` exception will be thrown. - * If the transaction does not belong to the wallet, a `WalletOwnerInvalid` exception will be thrown. - * If the transaction was not found, a `RecordNotFoundException` will be thrown. - * - * @param Transaction $transaction The transaction to reset. - * @return bool Returns true if the confirmation was reset, false otherwise. - * * @throws UnconfirmedInvalid If the transaction is not confirmed. * @throws WalletOwnerInvalid If the transaction does not belong to the wallet. * @throws RecordNotFoundException If the transaction was not found. @@ -77,30 +51,9 @@ public function safeConfirm(Transaction $transaction): bool; */ public function resetConfirm(Transaction $transaction): bool; - /** - * Safely reset the confirmation of the transaction. - * - * This method is used to remove the confirmation from a transaction. - * If the transaction is already confirmed, the confirmation will be reset. - * If the transaction does not belong to the wallet, a `WalletOwnerInvalid` exception will be thrown. - * If the transaction was not found, a `RecordNotFoundException` will be thrown. - * - * @param Transaction $transaction The transaction to reset. - * @return bool Returns true if the confirmation was reset, false otherwise. - */ public function safeResetConfirm(Transaction $transaction): bool; /** - * Force confirm the transaction. - * - * This method forces the confirmation of the given transaction even if it is already confirmed. - * If the transaction is already confirmed, a `ConfirmedInvalid` exception will be thrown. - * If the transaction does not belong to the wallet, a `WalletOwnerInvalid` exception will be thrown. - * If the transaction was not found, a `RecordNotFoundException` will be thrown. - * - * @param Transaction $transaction The transaction to confirm. - * @return bool Returns true if the transaction was confirmed, false otherwise. - * * @throws ConfirmedInvalid If the transaction is already confirmed. * @throws WalletOwnerInvalid If the transaction does not belong to the wallet. * @throws RecordNotFoundException If the transaction was not found. diff --git a/src/Interfaces/ProductLimitedInterface.php b/src/Interfaces/ProductLimitedInterface.php index 05250b9d7..ce0e723fe 100644 --- a/src/Interfaces/ProductLimitedInterface.php +++ b/src/Interfaces/ProductLimitedInterface.php @@ -6,21 +6,5 @@ interface ProductLimitedInterface extends ProductInterface { - /** - * Check if the customer can buy the product. - * - * @param Customer $customer The customer entity - * @param int $quantity The quantity of the product to buy. Default is 1. - * @param bool $force Flag to force the purchase. Default is false. - * @return bool Returns true if the customer can buy the product, false otherwise. - * - * The method checks if the customer can buy the product based on the quantity and the force flag. - * If the force flag is set to true, the method returns true regardless of the quantity. - * If the force flag is set to false, the method returns true if the quantity of the product is - * greater than or equal to the quantity to buy. - * - * The method does not check if the customer has already bought the product. It is the responsibility - * of the caller to check if the customer has already bought the product. - */ public function canBuy(Customer $customer, int $quantity = 1, bool $force = false): bool; } diff --git a/src/Interfaces/Wallet.php b/src/Interfaces/Wallet.php index 60170afcf..f75f32c08 100644 --- a/src/Interfaces/Wallet.php +++ b/src/Interfaces/Wallet.php @@ -12,6 +12,7 @@ use Bavix\Wallet\Internal\Exceptions\TransactionFailedException; use Bavix\Wallet\Models\Transaction; use Bavix\Wallet\Models\Transfer; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\RecordsNotFoundException; @@ -19,12 +20,8 @@ interface Wallet { /** - * Deposit the specified amount of money into the wallet. - * - * @param int|non-empty-string $amount The amount to deposit. - * @param array|null $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param int|non-empty-string $amount + * @param array|null $meta * * @throws AmountInvalid If the amount is invalid. * @throws RecordsNotFoundException If the wallet is not found. @@ -34,12 +31,8 @@ interface Wallet public function deposit(int|string $amount, ?array $meta = null, bool $confirmed = true): Transaction; /** - * Withdraw the specified amount of money from the wallet. - * - * @param int|non-empty-string $amount The amount to withdraw. - * @param array|null $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param int|non-empty-string $amount + * @param array|null $meta * * @throws AmountInvalid If the amount is invalid. * @throws BalanceIsEmpty If the balance is empty. @@ -51,12 +44,8 @@ public function deposit(int|string $amount, ?array $meta = null, bool $confirmed public function withdraw(int|string $amount, ?array $meta = null, bool $confirmed = true): Transaction; /** - * Forced to withdraw funds from the wallet. - * - * @param int|non-empty-string $amount The amount to withdraw. - * @param array|null $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param int|non-empty-string $amount + * @param array|null $meta * * @throws AmountInvalid If the amount is invalid. * @throws RecordsNotFoundException If the wallet is not found. @@ -66,12 +55,8 @@ public function withdraw(int|string $amount, ?array $meta = null, bool $confirme public function forceWithdraw(int|string $amount, ?array $meta = null, bool $confirmed = true): Transaction; /** - * Transfer funds from this wallet to another. - * - * @param self $wallet The wallet to transfer funds to. - * @param int|non-empty-string $amount The amount to transfer. - * @param ExtraDtoInterface|array|null $meta Additional information for the transaction. - * @return Transfer The created transaction. + * @param int|non-empty-string $amount + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount is invalid. * @throws BalanceIsEmpty If the balance is empty. @@ -83,17 +68,8 @@ public function forceWithdraw(int|string $amount, ?array $meta = null, bool $con public function transfer(self $wallet, int|string $amount, ExtraDtoInterface|array|null $meta = null): Transfer; /** - * Safely transfers funds from this wallet to another. - * - * This method attempts to transfer funds from this wallet to another wallet. - * If an error occurs during the process, null is returned. - * - * @param self $wallet The wallet to transfer funds to. - * @param int|non-empty-string $amount The amount to transfer. - * @param ExtraDtoInterface|array|null $meta Additional information for the transaction. - * This can be an instance of an ExtraDtoInterface - * or an array of arbitrary data. - * @return null|Transfer The created transaction, or null if an error occurred. + * @param int|non-empty-string $amount + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount is invalid. * @throws BalanceIsEmpty If the balance is empty. @@ -109,18 +85,8 @@ public function safeTransfer( ): ?Transfer; /** - * Forces a transfer of funds from this wallet to another, bypassing certain safety checks. - * - * This method is intended for use in scenarios where a transfer must be completed regardless of - * the usual validation checks (e.g., sufficient funds, wallet status). It is critical to use this - * method with caution as it can result in negative balances or other unintended consequences. - * - * @param self $wallet The wallet instance to which funds will be transferred. - * @param int|non-empty-string $amount The amount of funds to transfer. Can be specified as an integer or a string. - * @param ExtraDtoInterface|array|null $meta Additional metadata associated with the transfer. This - * can be used to store extra information about the transaction, such as reasons for the transfer or - * identifiers linking to other systems. - * @return Transfer Returns a Transfer object representing the completed transaction. + * @param int|non-empty-string $amount + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount specified is invalid (e.g., negative values). * @throws RecordsNotFoundException If the target wallet cannot be found. @@ -136,60 +102,34 @@ public function forceTransfer( ): Transfer; /** - * Checks if the wallet can safely withdraw the specified amount. - * - * @param int|non-empty-string $amount The amount to withdraw. - * @param bool $allowZero Whether to allow withdrawing when the balance is zero. - * @return bool Returns true if the wallet can withdraw the specified amount, false otherwise. + * @param int|non-empty-string $amount */ public function canWithdraw(int|string $amount, bool $allowZero = false): bool; /** - * Returns the balance of the wallet as a string. - * - * The balance is the total amount of funds held by the wallet. - * - * @return non-empty-string The balance of the wallet. + * @return non-empty-string */ public function getBalanceAttribute(): string; - /** - * Returns the balance of the wallet as an integer. - * - * @return int The balance of the wallet. This value is the result of - * {@see getBalanceAttribute()} converted to an integer. - */ public function getBalanceIntAttribute(): int; /** - * Represents a relationship where a wallet has many transactions. - * - * @return HasMany A collection of transactions associated with this wallet. + * @return HasMany */ public function walletTransactions(): HasMany; /** - * Returns all the transactions associated with this wallet. - * - * This method returns a morph many relationship that represents all the transactions - * associated with this wallet. The transactions may be of different types, such as - * deposits, withdrawals, or transfers. - * - * @return MorphMany A collection of transactions associated with this wallet. + * @return MorphMany */ public function transactions(): MorphMany; /** - * Returns all the transfers sent by this wallet. - * - * @return HasMany A collection of transfers sent by this wallet. + * @return HasMany */ public function transfers(): HasMany; /** - * Returns all the transfers received by this wallet. - * - * @return HasMany A collection of transfers received by this wallet. + * @return HasMany */ public function receivedTransfers(): HasMany; } diff --git a/src/Interfaces/WalletFloat.php b/src/Interfaces/WalletFloat.php index 3ac1f5f0a..ebb40f17b 100644 --- a/src/Interfaces/WalletFloat.php +++ b/src/Interfaces/WalletFloat.php @@ -17,12 +17,8 @@ interface WalletFloat { /** - * Deposit a float amount of money into the wallet. - * - * @param float|int|non-empty-string $amount The amount to deposit. - * @param null|array $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param float|int|non-empty-string $amount + * @param null|array $meta * * @throws AmountInvalid If the amount is invalid. * @throws RecordsNotFoundException If the wallet is not found. @@ -36,12 +32,8 @@ public function depositFloat( ): Transaction; /** - * Withdraw the specified float amount of money from the wallet. - * - * @param float|int|non-empty-string $amount The amount to withdraw. - * @param array|null $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param float|int|non-empty-string $amount + * @param array|null $meta * * @throws AmountInvalid If the amount is invalid. * @throws BalanceIsEmpty If the balance is empty. @@ -57,12 +49,8 @@ public function withdrawFloat( ): Transaction; /** - * Forced to withdraw funds from the wallet. - * - * @param float|int|non-empty-string $amount The amount to withdraw. - * @param null|array $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param float|int|non-empty-string $amount + * @param null|array $meta * * @throws AmountInvalid If the amount is invalid. * @throws RecordsNotFoundException If the wallet is not found. @@ -76,14 +64,8 @@ public function forceWithdrawFloat( ): Transaction; /** - * Transfer funds from this wallet to another. - * - * @param Wallet $wallet The wallet to transfer funds to. - * @param float|int|non-empty-string $amount The amount to transfer. - * @param ExtraDtoInterface|array|null $meta Additional information for the transaction. - * This can be an instance of an ExtraDtoInterface - * or an array of arbitrary data. - * @return Transfer The created transaction. + * @param float|int|non-empty-string $amount + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount is invalid. * @throws BalanceIsEmpty If the balance is empty. @@ -99,16 +81,8 @@ public function transferFloat( ): Transfer; /** - * Safely transfers funds from this wallet to another. - * - * This method will not throw an exception if the transfer fails. Instead, it will return null. - * - * @param Wallet $wallet The wallet to transfer funds to. - * @param float|int|non-empty-string $amount The amount to transfer. - * @param ExtraDtoInterface|array|null $meta Additional information for the transaction. - * This can be an instance of an ExtraDtoInterface - * or an array of arbitrary data. - * @return Transfer|null The created transaction, or null if the transfer fails. + * @param float|int|non-empty-string $amount + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount is invalid. */ @@ -119,18 +93,8 @@ public function safeTransferFloat( ): ?Transfer; /** - * Forces a transfer of funds from this wallet to another, bypassing certain safety checks. - * - * This method is intended for use in scenarios where a transfer must be completed regardless of - * the usual validation checks (e.g., sufficient funds, wallet status). It is critical to use this - * method with caution as it can result in negative balances or other unintended consequences. - * - * @param Wallet $wallet The wallet instance to which funds will be transferred. - * @param float|int|non-empty-string $amount The amount of funds to transfer. Can be specified as a float, int, or string. - * @param ExtraDtoInterface|array|null $meta Additional metadata associated with the transfer. This - * can be used to store extra information about the transaction, such as reasons for the transfer or - * identifiers linking to other systems. - * @return Transfer Returns a Transfer object representing the completed transaction. + * @param float|int|non-empty-string $amount + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount specified is invalid (e.g., negative values). * @throws RecordsNotFoundException If the target wallet cannot be found. @@ -146,33 +110,16 @@ public function forceTransferFloat( ): Transfer; /** - * Checks if the user can withdraw the specified amount of funds. + * @param float|int|non-empty-string $amount * - * @param float|int|non-empty-string $amount The amount of funds to withdraw. Can be specified as a float, int, or string. - * @return bool Returns TRUE if the withdrawal is possible, FALSE otherwise. - * - * @throws AmountInvalid If the amount is invalid (e.g., negative values). + * @throws AmountInvalid */ public function canWithdrawFloat(float|int|string $amount): bool; /** - * Returns the user's current balance as a string value. - * - * This method returns the balance of the wallet as a string. The balance is the total amount of funds - * held by the wallet. - * - * @return non-empty-string The user's current balance as a string (e.g. "1.23"). + * @return non-empty-string */ public function getBalanceFloatAttribute(): string; - /** - * Returns the user's current balance as a float value. - * - * The float value is the actual value of the balance, which may not be - * the same as the value stored in the database. This method is useful - * when you need to perform calculations or formatting on the balance. - * - * @return float The user's current balance as a float (e.g. 1.23). - */ public function getBalanceFloatNumAttribute(): float; } diff --git a/src/Internal/Assembler/TransactionDtoAssembler.php b/src/Internal/Assembler/TransactionDtoAssembler.php index 5c19e9874..d44d1675f 100644 --- a/src/Internal/Assembler/TransactionDtoAssembler.php +++ b/src/Internal/Assembler/TransactionDtoAssembler.php @@ -27,10 +27,13 @@ public function create( ?array $meta, ?string $uuid ): TransactionDtoInterface { + /** @var int|string $payableId */ + $payableId = $payable->getKey(); + return new TransactionDto( $uuid ?? $this->identifierFactoryService->generate(), $payable->getMorphClass(), - $payable->getKey(), + $payableId, $walletId, $type, $amount, diff --git a/src/Internal/Assembler/TransferDtoAssembler.php b/src/Internal/Assembler/TransferDtoAssembler.php index 0bbb3b3e5..6dc31defd 100644 --- a/src/Internal/Assembler/TransferDtoAssembler.php +++ b/src/Internal/Assembler/TransferDtoAssembler.php @@ -32,13 +32,20 @@ public function create( ?string $uuid, ?array $extra, ): TransferDtoInterface { + // Wallet models always have int keys + /** @var int $fromId */ + $fromId = $fromModel->getKey(); + + /** @var int $toId */ + $toId = $toModel->getKey(); + return new TransferDto( $uuid ?? $this->identifierFactoryService->generate(), $depositId, $withdrawId, $status, - $fromModel->getKey(), - $toModel->getKey(), + $fromId, + $toId, $discount, $fee, $extra, diff --git a/src/Internal/Decorator/StorageServiceLockDecorator.php b/src/Internal/Decorator/StorageServiceLockDecorator.php index 8c97eddd7..eadc77166 100644 --- a/src/Internal/Decorator/StorageServiceLockDecorator.php +++ b/src/Internal/Decorator/StorageServiceLockDecorator.php @@ -52,6 +52,12 @@ public function increase(string $uuid, float|int|string $value): string ])); } + /** + * @param non-empty-array $uuids + * @return non-empty-array + * + * @throws RecordNotFoundException + */ public function multiGet(array $uuids): array { $missingKeys = []; @@ -74,8 +80,7 @@ public function multiGet(array $uuids): array } } - assert($results !== []); - + /** @var non-empty-array $results */ return $results; } @@ -90,14 +95,17 @@ public function multiIncrease(array $inputs): array $multiGet = $this->multiGet(array_keys($inputs)); $results = []; foreach ($multiGet as $uuid => $item) { - $value = $this->mathService->add($item, $inputs[$uuid]); - $results[$uuid] = $this->mathService->round($value); + /** @var non-empty-string $itemValue */ + $itemValue = $item; + /** @var float|int|non-empty-string $inputValue */ + $inputValue = $inputs[$uuid]; + $added = $this->mathService->add($itemValue, $inputValue); + $rounded = $this->mathService->round($added); + $results[$uuid] = $rounded; } $this->multiSync($results); - assert($results !== []); - return $results; }); } diff --git a/src/Internal/Dto/ItemDto.php b/src/Internal/Dto/ItemDto.php index 4af3c87f0..0cd98ccb0 100644 --- a/src/Internal/Dto/ItemDto.php +++ b/src/Internal/Dto/ItemDto.php @@ -26,9 +26,15 @@ public function getItems(): array return array_fill(0, $this->quantity, $this->product); } + /** + * @return int|non-empty-string|null + */ public function getPricePerItem(): int|string|null { - return $this->pricePerItem; + /** @var int|non-empty-string|null $pricePerItem */ + $pricePerItem = $this->pricePerItem; + + return $pricePerItem; } public function getProduct(): ProductInterface @@ -36,9 +42,15 @@ public function getProduct(): ProductInterface return $this->product; } + /** + * @return int<0, max> + */ public function count(): int { - return $this->quantity; + /** @var int<0, max> $quantity */ + $quantity = $this->quantity; + + return $quantity; } public function getReceiving(): ?Wallet diff --git a/src/Internal/Dto/TransactionDto.php b/src/Internal/Dto/TransactionDto.php index 4261cfe1a..44eaaf5ab 100644 --- a/src/Internal/Dto/TransactionDto.php +++ b/src/Internal/Dto/TransactionDto.php @@ -26,14 +26,26 @@ public function __construct( ) { } + /** + * @return non-empty-string + */ public function getUuid(): string { - return $this->uuid; + /** @var non-empty-string $uuid */ + $uuid = $this->uuid; + + return $uuid; } + /** + * @return class-string + */ public function getPayableType(): string { - return $this->payableType; + /** @var class-string $payableType */ + $payableType = $this->payableType; + + return $payableType; } public function getPayableId(): int|string @@ -51,9 +63,15 @@ public function getType(): string return $this->type; } + /** + * @return float|int|non-empty-string + */ public function getAmount(): float|int|string { - return $this->amount; + /** @var float|int|non-empty-string $amount */ + $amount = $this->amount; + + return $amount; } public function isConfirmed(): bool diff --git a/src/Internal/Dto/TransferDto.php b/src/Internal/Dto/TransferDto.php index a73a30a50..4e408bcbe 100644 --- a/src/Internal/Dto/TransferDto.php +++ b/src/Internal/Dto/TransferDto.php @@ -27,9 +27,15 @@ public function __construct( ) { } + /** + * @return non-empty-string + */ public function getUuid(): string { - return $this->uuid; + /** @var non-empty-string $uuid */ + $uuid = $this->uuid; + + return $uuid; } public function getDepositId(): int @@ -62,9 +68,15 @@ public function getDiscount(): int return $this->discount; } + /** + * @return non-empty-string + */ public function getFee(): string { - return $this->fee; + /** @var non-empty-string $fee */ + $fee = $this->fee; + + return $fee; } /** diff --git a/src/Internal/Dto/TransferLazyDto.php b/src/Internal/Dto/TransferLazyDto.php index 8fb66cc75..ed2d1315b 100644 --- a/src/Internal/Dto/TransferLazyDto.php +++ b/src/Internal/Dto/TransferLazyDto.php @@ -40,9 +40,15 @@ public function getDiscount(): int return $this->discount; } + /** + * @return non-empty-string + */ public function getFee(): string { - return $this->fee; + /** @var non-empty-string $fee */ + $fee = $this->fee; + + return $fee; } public function getWithdrawDto(): TransactionDtoInterface @@ -60,9 +66,15 @@ public function getStatus(): string return $this->status; } + /** + * @return non-empty-string|null + */ public function getUuid(): ?string { - return $this->uuid; + /** @var non-empty-string|null $uuid */ + $uuid = $this->uuid; + + return $uuid; } /** diff --git a/src/Internal/Events/BalanceUpdatedEvent.php b/src/Internal/Events/BalanceUpdatedEvent.php index 622f5905e..4bdb1ef9a 100644 --- a/src/Internal/Events/BalanceUpdatedEvent.php +++ b/src/Internal/Events/BalanceUpdatedEvent.php @@ -21,14 +21,26 @@ public function getWalletId(): int return $this->walletId; } + /** + * @return non-empty-string + */ public function getWalletUuid(): string { - return $this->walletUuid; + /** @var non-empty-string $walletUuid */ + $walletUuid = $this->walletUuid; + + return $walletUuid; } + /** + * @return non-empty-string + */ public function getBalance(): string { - return $this->balance; + /** @var non-empty-string $balance */ + $balance = $this->balance; + + return $balance; } public function getUpdatedAt(): DateTimeImmutable diff --git a/src/Internal/Events/WalletCreatedEvent.php b/src/Internal/Events/WalletCreatedEvent.php index 30c1910e5..2b8b74f5e 100644 --- a/src/Internal/Events/WalletCreatedEvent.php +++ b/src/Internal/Events/WalletCreatedEvent.php @@ -27,9 +27,15 @@ public function getHolderId(): int|string return $this->holderId; } + /** + * @return non-empty-string + */ public function getWalletUuid(): string { - return $this->walletUuid; + /** @var non-empty-string $walletUuid */ + $walletUuid = $this->walletUuid; + + return $walletUuid; } public function getWalletId(): int diff --git a/src/Internal/Observers/TransactionObserver.php b/src/Internal/Observers/TransactionObserver.php index cef4bed9d..825dd2182 100644 --- a/src/Internal/Observers/TransactionObserver.php +++ b/src/Internal/Observers/TransactionObserver.php @@ -21,7 +21,6 @@ final class TransactionObserver * It safely resets the confirmation of the transaction. * * @param Transaction $model The transaction model being deleted. - * @return bool Returns true if the confirmation was reset, false otherwise. * * @throws UnconfirmedInvalid If the transaction is not confirmed. * @throws WalletOwnerInvalid If the transaction does not belong to the wallet. diff --git a/src/Internal/Observers/TransferObserver.php b/src/Internal/Observers/TransferObserver.php index 0f0e24715..b2065d181 100644 --- a/src/Internal/Observers/TransferObserver.php +++ b/src/Internal/Observers/TransferObserver.php @@ -27,7 +27,6 @@ public function __construct( * It safely resets the confirmation of the transfer. * * @param Transfer $model The transfer model being deleted. - * @return bool Returns true if the confirmation was reset, false otherwise. * * @throws UnconfirmedInvalid If the transfer is not confirmed. * @throws WalletOwnerInvalid If the transfer does not belong to the wallet. diff --git a/src/Internal/Repository/WalletRepository.php b/src/Internal/Repository/WalletRepository.php index bc512df13..826c76aa5 100644 --- a/src/Internal/Repository/WalletRepository.php +++ b/src/Internal/Repository/WalletRepository.php @@ -127,17 +127,15 @@ public function findDefaultAll(string $holderType, array $holderIds): array } /** - * @param array $attributes + * @param non-empty-array $attributes */ private function getBy(array $attributes): Wallet { - assert($attributes !== []); - try { + /** @var Wallet $wallet */ $wallet = $this->wallet->newQuery() ->where($attributes) ->firstOrFail(); - assert($wallet instanceof Wallet); return $wallet; } catch (EloquentModelNotFoundException $exception) { diff --git a/src/Internal/Service/ConnectionService.php b/src/Internal/Service/ConnectionService.php index c3ef8c939..553621fd8 100644 --- a/src/Internal/Service/ConnectionService.php +++ b/src/Internal/Service/ConnectionService.php @@ -16,7 +16,9 @@ public function __construct(ConnectionResolverInterface $connectionResolver) { - $this->connection = $connectionResolver->connection(config('wallet.database.connection')); + /** @var string|null $connectionName */ + $connectionName = config('wallet.database.connection'); + $this->connection = $connectionResolver->connection($connectionName); } public function get(): ConnectionInterface diff --git a/src/Internal/Service/LockService.php b/src/Internal/Service/LockService.php index 18280581b..3aabb1c76 100644 --- a/src/Internal/Service/LockService.php +++ b/src/Internal/Service/LockService.php @@ -25,7 +25,9 @@ public function __construct( CacheFactory $cacheFactory, private readonly int $seconds ) { - $this->cache = $cacheFactory->store(config('wallet.lock.driver', 'array')); + /** @var string|null $lockDriver */ + $lockDriver = config('wallet.lock.driver', 'array'); + $this->cache = $cacheFactory->store($lockDriver); $this->lockedKeys = $cacheFactory->store('array'); } diff --git a/src/Internal/Service/MathServiceInterface.php b/src/Internal/Service/MathServiceInterface.php index 73ba914f4..95a2830cd 100644 --- a/src/Internal/Service/MathServiceInterface.php +++ b/src/Internal/Service/MathServiceInterface.php @@ -9,144 +9,81 @@ interface MathServiceInterface { /** - * Add two numbers. - * - * This method adds two numbers and returns the result as a string. - * - * @param float|int|non-empty-string $first The first number to add. - * @param float|int|non-empty-string $second The second number to add. - * @param int|null $scale The scale to use for rounding. Defaults to null, which means the scale will be determined automatically. - * @return non-empty-string The sum of the two numbers. + * @param float|int|non-empty-string $first + * @param float|int|non-empty-string $second + * @return non-empty-string */ public function add(float|int|string $first, float|int|string $second, ?int $scale = null): string; /** - * Subtract two numbers. - * - * This method subtracts the second number from the first number and returns the result as a string. - * - * @param float|int|non-empty-string $first The first number to subtract from. - * @param float|int|non-empty-string $second The number to subtract. - * @param int|null $scale The scale to use for rounding. Defaults to null, which means the scale will be determined automatically. - * @return non-empty-string The difference between the two numbers. + * @param float|int|non-empty-string $first + * @param float|int|non-empty-string $second + * @return non-empty-string */ public function sub(float|int|string $first, float|int|string $second, ?int $scale = null): string; /** - * Divide two numbers. - * - * This method divides the first number by the second number and returns the result as a string. - * - * @param float|int|non-empty-string $first The first number to divide. - * @param float|int|non-empty-string $second The number to divide by. - * @param int|null $scale The scale to use for rounding. Defaults to null, which means the scale will be determined automatically. - * @return non-empty-string The result of the division. + * @param float|int|non-empty-string $first + * @param float|int|non-empty-string $second + * @return non-empty-string * - * @throws DivisionByZeroException If the second number is zero. + * @throws DivisionByZeroException */ public function div(float|int|string $first, float|int|string $second, ?int $scale = null): string; /** - * Multiply two numbers. - * - * This method multiplies the first number by the second number and returns the result as a string. - * The result can be scaled to a specific number of decimal places as specified by the $scale parameter. - * If $scale is not provided, a default scale (defined elsewhere in the implementation) will be used. - * - * @param float|int|non-empty-string $first The first number to multiply. This can be a float, int, or a numeric string. - * @param float|int|non-empty-string $second The second number to multiply. Similar to $first, it accepts float, int, or numeric string. - * @param int|null $scale Optional. The scale to use for rounding the result. Defaults to null, indicating automatic scale determination. - * @return non-empty-string The product of the two numbers, represented as a string. + * @param float|int|non-empty-string $first + * @param float|int|non-empty-string $second + * @return non-empty-string */ public function mul(float|int|string $first, float|int|string $second, ?int $scale = null): string; /** - * Raise a number to the power of another number. - * - * This method calculates the result of raising the first number to the power of the second number and returns the result as a string. - * The result can be scaled to a specific number of decimal places as specified by the $scale parameter. - * If $scale is not provided, a default scale (defined elsewhere in the implementation) will be used. - * - * @param float|int|non-empty-string $first The base number to raise. - * @param float|int|non-empty-string $second The exponent to raise the base number to. - * @param int|null $scale Optional. The scale to use for rounding the result. Defaults to null, indicating automatic scale determination. - * @return non-empty-string The result of the exponentiation, represented as a string. + * @param float|int|non-empty-string $first + * @param float|int|non-empty-string $second + * @return non-empty-string */ public function pow(float|int|string $first, float|int|string $second, ?int $scale = null): string; /** - * Raise the number 10 to the power of another number. - * - * This method calculates the result of raising the number 10 to the power of the given number and returns - * the result as a string. - * - * @param float|int|non-empty-string $number The exponent to raise the number 10 to. - * @return non-empty-string The result of the exponentiation, represented as a string. + * @param float|int|non-empty-string $number + * @return non-empty-string */ public function powTen(float|int|string $number): string; /** - * Round a number to a specified precision. - * - * This method provides a way to round numerical values (whether they are floats, integers, or numeric strings) - * to a specified level of precision. The precision is defined by the number of decimal places to round to. - * The rounding follows the standard mathematical rules for rounding. - * - * @param float|int|non-empty-string $number The number to be rounded. Can be of type float, int, or a numeric string. - * @param int $precision The number of decimal places to round to. Defaults to 0, meaning rounding to the nearest whole number. - * @return non-empty-string The rounded number, represented as a string. This ensures consistent precision and format, especially useful in financial calculations. + * @param float|int|non-empty-string $number + * @return non-empty-string */ public function round(float|int|string $number, int $precision = 0): string; /** - * Get the floor value of a number. - * - * This method returns the largest integer less than or equal to the specified number. - * - * @param float|int|non-empty-string $number The number to get the floor value for. - * @return non-empty-string The floor value of the number represented as a string. + * @param float|int|non-empty-string $number + * @return non-empty-string */ public function floor(float|int|string $number): string; /** - * Get the ceiling value of a number. - * - * This method returns the smallest integer greater than or equal to the specified number. - * - * @param float|int|non-empty-string $number The number to get the ceiling value for. - * @return non-empty-string The ceiling value of the number represented as a string. + * @param float|int|non-empty-string $number + * @return non-empty-string */ public function ceil(float|int|string $number): string; /** - * Get the absolute value of a number. - * - * The absolute value of a number is the value without considering whether it is positive or negative. - * - * @param float|int|non-empty-string $number The number for which to get the absolute value. - * @return non-empty-string The absolute value of the number represented as a string. + * @param float|int|non-empty-string $number + * @return non-empty-string */ public function abs(float|int|string $number): string; /** - * Get the negative value of a number. - * - * The negative value of a number is the same as the number multiplied by -1. - * - * @param float|int|non-empty-string $number The number for which to get the negative value. - * @return non-empty-string The negative value of the number represented as a string. + * @param float|int|non-empty-string $number + * @return non-empty-string */ public function negative(float|int|string $number): string; /** - * Compare two numbers. - * - * This method compares two numbers and returns an integer value indicating their relationship. - * - * @param float|int|non-empty-string $first The first number to compare. - * @param float|int|non-empty-string $second The second number to compare. - * @return int Returns an integer less than, equal to, or greater than zero if the first number is considered - * to be respectively less than, equal to, or greater than the second. + * @param float|int|non-empty-string $first + * @param float|int|non-empty-string $second */ public function compare(float|int|string $first, float|int|string $second): int; } diff --git a/src/Internal/Service/StateService.php b/src/Internal/Service/StateService.php index d03613b66..6f23e3b5c 100644 --- a/src/Internal/Service/StateService.php +++ b/src/Internal/Service/StateService.php @@ -59,13 +59,18 @@ public function multiFork(array $uuids, callable $value): void $this->store->setMultiple($values); } + /** + * @return non-empty-string|null + */ public function get(string $uuid): ?string { + /** @var non-empty-string|null $value */ $value = $this->store->get(self::PREFIX_STATE.$uuid); if ($value !== null) { return $value; } + /** @var string|null $forkId */ $forkId = $this->store->pull(self::PREFIX_FORK_ID.$uuid); if ($forkId === null) { return null; @@ -93,13 +98,17 @@ public function get(string $uuid): ?string // delete callables by uuids $this->store->deleteMultiple($deleteKeys); - return $results[$uuid] ?? null; + /** @var non-empty-string|null $result */ + $result = $results[$uuid] ?? null; + + return $result; } public function drop(string $uuid): void { $deleteKeys = [self::PREFIX_STATE.$uuid]; + /** @var string|null $forkId */ $forkId = $this->store->pull(self::PREFIX_FORK_ID.$uuid); if ($forkId !== null) { $deleteKeys[] = self::PREFIX_FORK_REF.$forkId; diff --git a/src/Internal/Service/StorageService.php b/src/Internal/Service/StorageService.php index 1c7db5be6..aa20fc3a0 100644 --- a/src/Internal/Service/StorageService.php +++ b/src/Internal/Service/StorageService.php @@ -45,13 +45,18 @@ public function sync(string $uuid, float|int|string $value): bool } /** + * @return non-empty-string + * * @throws RecordNotFoundException */ public function increase(string $uuid, float|int|string $value): string { - return current($this->multiIncrease([ + /** @var non-empty-string $result */ + $result = current($this->multiIncrease([ $uuid => $value, ])); + + return $result; } /** @@ -89,7 +94,10 @@ public function multiGet(array $uuids): array continue; } - $results[$uuid] = $this->mathService->round($value); + /** @var float|int|non-empty-string $valueToRound */ + $valueToRound = $value; + $rounded = $this->mathService->round($valueToRound); + $results[$uuid] = $rounded; } if ($missingKeys !== []) { @@ -112,7 +120,10 @@ public function multiSync(array $inputs): bool { $values = []; foreach ($inputs as $uuid => $value) { - $values[self::PREFIX.$uuid] = $this->mathService->round($value); + /** @var float|int|non-empty-string $valueToRound */ + $valueToRound = $value; + $rounded = $this->mathService->round($valueToRound); + $values[self::PREFIX.$uuid] = $rounded; } if (count($values) === 1) { @@ -133,16 +144,22 @@ public function multiSync(array $inputs): bool public function multiIncrease(array $inputs): array { $newInputs = []; + /** @var non-empty-array $uuids */ $uuids = array_keys($inputs); $multiGet = $this->multiGet($uuids); foreach ($uuids as $uuid) { - $newInputs[$uuid] = $this->mathService->round($this->mathService->add($multiGet[$uuid], $inputs[$uuid])); + /** @var non-empty-string $multiGetValue */ + $multiGetValue = $multiGet[$uuid]; + /** @var float|int|non-empty-string $inputValue */ + $inputValue = $inputs[$uuid]; + $added = $this->mathService->add($multiGetValue, $inputValue); + $rounded = $this->mathService->round($added); + $newInputs[$uuid] = $rounded; } $this->multiSync($newInputs); - assert($newInputs !== []); - + /** @var non-empty-array, non-empty-string> $newInputs */ return $newInputs; } } diff --git a/src/Internal/Service/StorageServiceInterface.php b/src/Internal/Service/StorageServiceInterface.php index 5cc295240..a8dfe0f7a 100644 --- a/src/Internal/Service/StorageServiceInterface.php +++ b/src/Internal/Service/StorageServiceInterface.php @@ -50,7 +50,6 @@ public function get(string $uuid): string; * * @param non-empty-string $uuid The UUID of the stored value. * @param float|int|non-empty-string $value The value to synchronize. - * @return bool Returns `true` if the synchronization was successful, `false` otherwise. */ public function sync(string $uuid, float|int|string $value): bool; @@ -91,7 +90,6 @@ public function multiGet(array $uuids): array; * @param non-empty-array $inputs An associative array * where the keys are UUIDs and the values are the corresponding * stored values. - * @return bool Returns `true` if the synchronization was successful, `false` otherwise. * * @throws RecordNotFoundException If any of the values with the given UUIDs are not found. */ diff --git a/src/Models/Transaction.php b/src/Models/Transaction.php index 430632105..27abe2048 100644 --- a/src/Models/Transaction.php +++ b/src/Models/Transaction.php @@ -77,7 +77,9 @@ public function casts(): array public function getTable(): string { if ((string) $this->table === '') { - $this->table = config('wallet.transaction.table', 'transactions'); + /** @var string $table */ + $table = config('wallet.transaction.table', 'transactions'); + $this->table = $table; } return parent::getTable(); @@ -96,7 +98,12 @@ public function payable(): MorphTo */ public function wallet(): BelongsTo { - return $this->belongsTo(config('wallet.wallet.model', WalletModel::class)); + /** @var class-string $model */ + $model = config('wallet.wallet.model', WalletModel::class); + /** @var BelongsTo $belongsTo */ + $belongsTo = $this->belongsTo($model); + + return $belongsTo; } public function getAmountIntAttribute(): int @@ -122,8 +129,12 @@ public function setAmountFloatAttribute(float|int|string $amount): void ->getWallet($this->wallet) ->decimal_places; $decimalPlaces = $math->powTen($decimalPlacesValue); + /** @var float|int|non-empty-string $amountValue */ + $amountValue = $amount; + $multiplied = $math->mul($amountValue, $decimalPlaces, $decimalPlacesValue); + $rounded = $math->round($multiplied); - $this->amount = $math->round($math->mul($amount, $decimalPlaces)); + $this->amount = $rounded; } #[\Override] diff --git a/src/Models/Transfer.php b/src/Models/Transfer.php index 7e331f73b..3b690a715 100644 --- a/src/Models/Transfer.php +++ b/src/Models/Transfer.php @@ -81,7 +81,9 @@ public function casts(): array public function getTable(): string { if ((string) $this->table === '') { - $this->table = config('wallet.transfer.table', 'transfers'); + /** @var string $table */ + $table = config('wallet.transfer.table', 'transfers'); + $this->table = $table; } return parent::getTable(); @@ -92,7 +94,12 @@ public function getTable(): string */ public function from(): BelongsTo { - return $this->belongsTo(config('wallet.wallet.model', Wallet::class), 'from_id'); + /** @var class-string $model */ + $model = config('wallet.wallet.model', Wallet::class); + /** @var BelongsTo $belongsTo */ + $belongsTo = $this->belongsTo($model, 'from_id'); + + return $belongsTo; } /** @@ -100,7 +107,12 @@ public function from(): BelongsTo */ public function to(): BelongsTo { - return $this->belongsTo(config('wallet.wallet.model', Wallet::class), 'to_id'); + /** @var class-string $model */ + $model = config('wallet.wallet.model', Wallet::class); + /** @var BelongsTo $belongsTo */ + $belongsTo = $this->belongsTo($model, 'to_id'); + + return $belongsTo; } /** @@ -108,7 +120,12 @@ public function to(): BelongsTo */ public function deposit(): BelongsTo { - return $this->belongsTo(config('wallet.transaction.model', Transaction::class), 'deposit_id'); + /** @var class-string $model */ + $model = config('wallet.transaction.model', Transaction::class); + /** @var BelongsTo $belongsTo */ + $belongsTo = $this->belongsTo($model, 'deposit_id'); + + return $belongsTo; } /** @@ -116,7 +133,12 @@ public function deposit(): BelongsTo */ public function withdraw(): BelongsTo { - return $this->belongsTo(config('wallet.transaction.model', Transaction::class), 'withdraw_id'); + /** @var class-string $model */ + $model = config('wallet.transaction.model', Transaction::class); + /** @var BelongsTo $belongsTo */ + $belongsTo = $this->belongsTo($model, 'withdraw_id'); + + return $belongsTo; } #[\Override] diff --git a/src/Models/Wallet.php b/src/Models/Wallet.php index 2da75e13d..a39ae6af5 100644 --- a/src/Models/Wallet.php +++ b/src/Models/Wallet.php @@ -45,8 +45,16 @@ * @property DateTimeInterface $created_at * @property DateTimeInterface $updated_at * @property DateTimeInterface $deleted_at + * @property \Illuminate\Database\Eloquent\Relations\HasMany $walletTransactions + * @property \Illuminate\Database\Eloquent\Relations\MorphMany $transactions + * @property \Illuminate\Database\Eloquent\Relations\HasMany $transfers + * @property \Illuminate\Database\Eloquent\Relations\HasMany $receivedTransfers * * @method int getKey() + * @method \Illuminate\Database\Eloquent\Relations\HasMany walletTransactions() + * @method \Illuminate\Database\Eloquent\Relations\MorphMany transactions() + * @method \Illuminate\Database\Eloquent\Relations\HasMany transfers() + * @method \Illuminate\Database\Eloquent\Relations\HasMany receivedTransfers() */ class Wallet extends Model implements Customer, WalletFloat, Confirmable, Exchangeable { @@ -96,7 +104,9 @@ public function casts(): array public function getTable(): string { if ((string) $this->table === '') { - $this->table = config('wallet.wallet.table', 'wallets'); + /** @var string $table */ + $table = config('wallet.wallet.table', 'wallets'); + $this->table = $table; } return parent::getTable(); @@ -114,7 +124,9 @@ public function setNameAttribute(string $name): void if (array_key_exists('slug', $this->attributes)) { return; } - $this->attributes['slug'] = Str::slug($name); + /** @var string $slug */ + $slug = Str::slug($name); + $this->attributes['slug'] = $slug; } /** @@ -127,8 +139,12 @@ public function setNameAttribute(string $name): void public function refreshBalance(): bool { return app(AtomicServiceInterface::class)->block($this, function () { + /** @var non-empty-string $whatIs */ $whatIs = $this->getBalanceAttribute(); - $balance = $this->getAvailableBalanceAttribute(); + /** @var float|int|non-empty-string $balanceRaw */ + $balanceRaw = $this->getAvailableBalanceAttribute(); + /** @var non-empty-string $balance */ + $balance = is_string($balanceRaw) ? $balanceRaw : (string) $balanceRaw; if (app(MathServiceInterface::class)->compare($whatIs, $balance) === 0) { return true; } @@ -139,7 +155,9 @@ public function refreshBalance(): bool public function getOriginalBalanceAttribute(): string { - $balance = (string) $this->getRawOriginal('balance', 0); + /** @var int|string|null $rawBalance */ + $rawBalance = $this->getRawOriginal('balance', 0); + $balance = (string) $rawBalance; // Perform assertion to check if balance is not an empty string assert($balance !== '', 'Balance should not be an empty string'); @@ -149,11 +167,15 @@ public function getOriginalBalanceAttribute(): string public function getAvailableBalanceAttribute(): float|int|string { + /** @var float|int|string|null $balance */ $balance = $this->walletTransactions() ->where('confirmed', true) ->sum('amount'); // Perform assertion to check if balance is not an empty string + if ($balance === null) { + $balance = '0'; + } assert($balance !== '', 'Balance should not be an empty string'); return $balance; @@ -189,7 +211,16 @@ public function getCreditAttribute(): string public function getCurrencyAttribute(): string { - return $this->meta['currency'] ?? Str::upper($this->slug); + /** @var string|null $currency */ + $currency = $this->meta['currency'] ?? null; + if ($currency !== null) { + return $currency; + } + + /** @var string $slug */ + $slug = $this->slug; + + return Str::upper($slug); } protected function initializeMorphOneWallet(): void diff --git a/src/Objects/Cart.php b/src/Objects/Cart.php index 3e44d04c8..51a19fb08 100644 --- a/src/Objects/Cart.php +++ b/src/Objects/Cart.php @@ -120,32 +120,44 @@ public function getItems(): array $items = []; foreach ($this->items as $item) { foreach ($item as $datum) { - $items[] = $datum->getItems(); + /** @var ProductInterface[] $datumItems */ + $datumItems = $datum->getItems(); + $items[] = $datumItems; } } + /** @var array $items */ return array_merge(...$items); } public function getTotal(Customer $customer): string { - $result = 0; + /** @var non-empty-string $result */ + $result = '0'; $prices = []; foreach ($this->items as $productId => $_items) { foreach ($_items as $item) { $product = $item->getProduct(); $pricePerItem = $item->getPricePerItem(); if ($pricePerItem === null) { - $prices[$productId] ??= $product->getAmountProduct($customer); + /** @var non-empty-string $productPrice */ + $productPrice = $product->getAmountProduct($customer); + $prices[$productId] ??= $productPrice; + /** @var int|non-empty-string $pricePerItem */ $pricePerItem = $prices[$productId]; } - $price = $this->math->mul(count($item), $pricePerItem); - $result = $this->math->add($result, $price); + /** @var int<0, max> $itemCount */ + $itemCount = count($item); + /** @var int|non-empty-string $pricePerItemValue */ + $pricePerItemValue = $pricePerItem; + $price = $this->math->mul($itemCount, $pricePerItemValue); + $newResult = $this->math->add($result, $price); + $result = $newResult; } } - return (string) $result; + return $result; } public function count(): int @@ -169,7 +181,10 @@ public function getQuantity(ProductInterface $product): int */ public function getBasketDto(): BasketDtoInterface { - $items = array_merge(...array_values($this->items)); + /** @var array $itemsValues */ + $itemsValues = array_values($this->items); + /** @var array $items */ + $items = array_merge(...$itemsValues); if ($items === []) { throw new CartEmptyException('Cart is empty', ExceptionInterface::CART_EMPTY); diff --git a/src/Services/BookkeeperServiceInterface.php b/src/Services/BookkeeperServiceInterface.php index e76bc6515..3062ccb6e 100644 --- a/src/Services/BookkeeperServiceInterface.php +++ b/src/Services/BookkeeperServiceInterface.php @@ -26,14 +26,6 @@ interface BookkeeperServiceInterface public function forget(Wallet $wallet): bool; /** - * Retrieves the current balance of the specified wallet. - * - * This method returns the current balance of the specified wallet as a string. - * The balance is always returned as a string to preserve the accuracy of the decimal value. - * - * @param Wallet $wallet The wallet to retrieve the balance from. - * @return string The current balance of the wallet as a string. - * * @throws RecordNotFoundException If the wallet does not exist in the database. */ public function amount(Wallet $wallet): string; @@ -48,7 +40,6 @@ public function amount(Wallet $wallet): string; * * @param Wallet $wallet The wallet whose balance needs to be synchronized. * @param float|int|string $value The new balance value for the wallet. - * @return bool Returns `true` on successful synchronization, `false` otherwise. * * @throws RecordNotFoundException If the wallet does not exist. */ diff --git a/src/Services/ConsistencyServiceInterface.php b/src/Services/ConsistencyServiceInterface.php index 87ec5a81f..7e2b1579b 100644 --- a/src/Services/ConsistencyServiceInterface.php +++ b/src/Services/ConsistencyServiceInterface.php @@ -44,13 +44,6 @@ public function checkPotential(Wallet $object, float|int|string $amount, bool $a /** * Checks if the given balance can be safely withdrawn by the specified amount. * - * This method returns true if the balance can be withdrawn, and false otherwise. - * - * @param float|int|string $balance The balance to check. - * @param float|int|string $amount The amount to withdraw. - * @param bool $allowZero Whether to allow zero amounts. Defaults to false. - * @return bool Returns true if the balance can be withdrawn, false otherwise. - * * @throws AmountInvalid If the given balance or amount is not positive. */ public function canWithdraw(float|int|string $balance, float|int|string $amount, bool $allowZero = false): bool; diff --git a/src/Services/RegulatorServiceInterface.php b/src/Services/RegulatorServiceInterface.php index 7014c28b8..fb5cc7638 100644 --- a/src/Services/RegulatorServiceInterface.php +++ b/src/Services/RegulatorServiceInterface.php @@ -11,88 +11,34 @@ */ interface RegulatorServiceInterface { - /** - * Forget the stored value for the given wallet. - * - * This method removes the stored value associated with the provided wallet from the storage. - * - * @param Wallet $wallet The wallet to forget. - * @return bool True if the value was successfully forgotten, false otherwise. - */ public function forget(Wallet $wallet): bool; /** - * Calculate the difference between the current balance and the given value. - * - * This method subtracts the given value from the current balance and returns the result. - * - * @param Wallet $wallet The wallet to calculate the difference for. - * @return non-empty-string The difference, formatted as a string with the same decimal places as the wallet. + * @return non-empty-string */ public function diff(Wallet $wallet): string; /** - * Get the current balance of the wallet. - * - * This method retrieves the current balance of the wallet from the storage. - * - * @param Wallet $wallet The wallet to get the balance for. - * @return non-empty-string The current balance, formatted as a string with the same decimal places as the wallet. + * @return non-empty-string */ public function amount(Wallet $wallet): string; /** - * Synchronize the stored value for the given wallet with the given value. - * - * This method updates the stored value associated with the provided wallet with the given value. - * If the value does not exist, it will be created. If the value already exists, it will be updated. - * - * @param Wallet $wallet The wallet to synchronize. - * @param float|int|non-empty-string $value The value to synchronize. - * @return non-empty-string True if the synchronization was successful, false otherwise. + * @param float|int|non-empty-string $value */ public function sync(Wallet $wallet, float|int|string $value): bool; /** - * Increase the stored value for the given wallet by the given amount. - * - * This method increases the stored value associated with the provided wallet by the given amount. - * - * @param Wallet $wallet The wallet to increase. - * @param float|int|non-empty-string $value The amount to increase the stored value by. - * @return non-empty-string The updated stored value, formatted as a string with the same decimal places as the wallet. + * @param float|int|non-empty-string $value + * @return non-empty-string */ public function increase(Wallet $wallet, float|int|string $value): string; - /** - * Decrease the stored value for the given wallet by the given amount. - * - * This method decreases the stored value associated with the provided wallet by the given amount. - * - * @param Wallet $wallet The wallet to decrease. - * @param float|int|string $value The amount to decrease the stored value by. - * @return string The updated stored value, formatted as a string with the same decimal places as the wallet. - */ public function decrease(Wallet $wallet, float|int|string $value): string; - /** - * Start committing a transaction. - * - * This method starts a transaction and locks the wallet for the duration of the transaction. - */ public function committing(): void; - /** - * Commit the transaction. - * - * This method commits the transaction and unlocks the wallet. - */ public function committed(): void; - /** - * Purge the stored values for all wallets. - * - * This method removes all stored values from the storage. - */ public function purge(): void; } diff --git a/src/Traits/CanConfirm.php b/src/Traits/CanConfirm.php index 0946239a0..73946aa8c 100644 --- a/src/Traits/CanConfirm.php +++ b/src/Traits/CanConfirm.php @@ -32,7 +32,6 @@ trait CanConfirm * This method confirms the given transaction if it is not already confirmed. * * @param Transaction $transaction The transaction to confirm. - * @return bool Returns true if the transaction was confirmed, false otherwise. * * @throws BalanceIsEmpty If the balance is empty. * @throws InsufficientFunds If there are insufficient funds. @@ -85,7 +84,6 @@ public function confirm(Transaction $transaction): bool * If the transaction was not found, a `RecordNotFoundException` will be thrown. * * @param Transaction $transaction The transaction to confirm. - * @return bool Returns true if the transaction was confirmed, false otherwise. * * @throws ConfirmedInvalid If the transaction is already confirmed. * @throws WalletOwnerInvalid If the transaction does not belong to the wallet. @@ -118,7 +116,6 @@ public function safeConfirm(Transaction $transaction): bool * If an exception occurred, a `TransactionFailedException` or `ExceptionInterface` will be thrown. * * @param Transaction $transaction The transaction to reset. - * @return bool Returns true if the confirmation was reset, false otherwise. * * @throws UnconfirmedInvalid If the transaction is not confirmed. * @throws WalletOwnerInvalid If the transaction does not belong to the wallet. @@ -162,16 +159,6 @@ public function resetConfirm(Transaction $transaction): bool }); } - /** - * Safely reset the confirmation of the transaction. - * - * This method attempts to reset the confirmation of the given transaction. If an exception occurs during the - * confirmation process, it will be caught and handled. If the confirmation is successfully reset, true will be - * returned. If an exception occurs, false will be returned. - * - * @param Transaction $transaction The transaction to reset. - * @return bool Returns true if the confirmation was reset, false otherwise. - */ public function safeResetConfirm(Transaction $transaction): bool { try { @@ -195,7 +182,6 @@ public function safeResetConfirm(Transaction $transaction): bool * returned. * * @param Transaction $transaction The transaction to confirm. - * @return bool Returns true if the confirmation was reset, false otherwise. * * @throws ConfirmedInvalid If the transaction is already confirmed. * @throws WalletOwnerInvalid If the transaction does not belong to the wallet. diff --git a/src/Traits/HasWallet.php b/src/Traits/HasWallet.php index e03858654..e2246baf3 100644 --- a/src/Traits/HasWallet.php +++ b/src/Traits/HasWallet.php @@ -24,6 +24,7 @@ use Bavix\Wallet\Services\TransactionServiceInterface; use Bavix\Wallet\Services\TransferServiceInterface; use function config; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Database\RecordsNotFoundException; @@ -141,7 +142,7 @@ public function getBalanceIntAttribute(): int * The transaction model class is retrieved from the configuration using `config('wallet.transaction.model', Transaction::class)`. * The relationship is defined using the `wallet_id` foreign key. * - * @return HasMany Returns a `HasMany` relationship of transactions related to the wallet. + * @return HasMany Returns a `HasMany` relationship of transactions related to the wallet. */ public function walletTransactions(): HasMany { @@ -152,7 +153,10 @@ public function walletTransactions(): HasMany // Retrieve all transactions related to the wallet using the `hasMany` method on the wallet instance. // The transaction model class is retrieved from the configuration using `config('wallet.transaction.model', Transaction::class)`. // The relationship is defined using the `wallet_id` foreign key. - $transactions = $wallet->hasMany(config('wallet.transaction.model', Transaction::class), 'wallet_id'); + /** @var class-string $model */ + $model = config('wallet.transaction.model', Transaction::class); + /** @var HasMany $transactions */ + $transactions = $wallet->hasMany($model, 'wallet_id'); return $transactions; } @@ -166,7 +170,7 @@ public function walletTransactions(): HasMany * The transaction model class is retrieved from the configuration using `config('wallet.transaction.model', Transaction::class)`. * The relationship is defined using the `payable` foreign key. * - * @return MorphMany The `MorphMany` relationship object representing all user actions on the wallet. + * @return MorphMany The `MorphMany` relationship object representing all user actions on the wallet. */ public function transactions(): MorphMany { @@ -180,10 +184,15 @@ public function transactions(): MorphMany // The transaction model class is retrieved from the configuration using `config('wallet.transaction.model', Transaction::class)`. // The relationship is defined using the `payable` foreign key. // The `payable` foreign key is used to associate the transactions with the wallet. - return $wallet->morphMany( - config('wallet.transaction.model', Transaction::class), + /** @var class-string $model */ + $model = config('wallet.transaction.model', Transaction::class); + /** @var MorphMany $morphMany */ + $morphMany = $wallet->morphMany( + $model, 'payable' // The name of the polymorphic relation column. ); + + return $morphMany; } /** @@ -315,7 +324,6 @@ public function withdraw(int|string $amount, ?array $meta = null, bool $confirme * * @param int|string $amount The amount to be withdrawn. * @param bool $allowZero Flag to allow zero balance for withdrawal. Defaults to false. - * @return bool Returns true if the withdrawal is possible; otherwise, false. */ public function canWithdraw(int|string $amount, bool $allowZero = false): bool { @@ -352,10 +360,13 @@ public function forceWithdraw(int|string $amount, ?array $meta = null, bool $con // Wrap the transaction creation in an atomic block to ensure atomicity and consistency. // The atomic block ensures that the creation of the transaction is atomic, // meaning that either the entire transaction is created or none of it is. + /** @var int|non-empty-string $amountValue */ + $amountValue = $amount; + return app(AtomicServiceInterface::class)->block( // The wallet instance $this, - function () use ($amount, $meta, $confirmed): Transaction { + function () use ($amountValue, $meta, $confirmed): Transaction { // Create a new withdrawal transaction. return app(TransactionServiceInterface::class)->makeOne( // The wallet instance @@ -363,7 +374,7 @@ function () use ($amount, $meta, $confirmed): Transaction { // The transaction type Transaction::TYPE_WITHDRAW, // The amount to withdraw - $amount, + $amountValue, // Additional information for the transaction $meta, // Whether the transaction is confirmed @@ -400,14 +411,21 @@ public function forceTransfer( // Wrap the transfer creation in an atomic block to ensure atomicity and consistency. // The atomic block ensures that the creation of the transfer is atomic, // meaning that either the entire transfer is created or none of it is. - return app(AtomicServiceInterface::class)->block($this, function () use ($wallet, $amount, $meta): Transfer { + /** @var int|non-empty-string $amountValue */ + $amountValue = $amount; + + return app(AtomicServiceInterface::class)->block($this, function () use ( + $wallet, + $amountValue, + $meta + ): Transfer { // Create a new transfer transaction. // The transfer transaction is created using the PrepareServiceInterface. // The transfer status is set to Transfer::STATUS_TRANSFER. // The additional information for the transaction is passed as an argument. // The created transfer transaction is stored in the $transferLazyDto variable. $transferLazyDto = app(PrepareServiceInterface::class) - ->transferLazy($this, $wallet, Transfer::STATUS_TRANSFER, $amount, $meta); + ->transferLazy($this, $wallet, Transfer::STATUS_TRANSFER, $amountValue, $meta); // Apply the transfer transaction. // The transfer transaction is applied using the TransferServiceInterface. @@ -432,7 +450,7 @@ public function forceTransfer( * The transfer model class is retrieved from the configuration using `config('wallet.transfer.model', Transfer::class)`. * The relationship is defined using the `from_id` foreign key. * - * @return HasMany The `HasMany` relationship object representing all transfers related to the wallet. + * @return HasMany The `HasMany` relationship object representing all transfers related to the wallet. */ public function transfers(): HasMany { @@ -446,15 +464,20 @@ public function transfers(): HasMany // The `hasMany` method is used on the wallet instance to retrieve all transfers related to the wallet. // The transfer model class is retrieved from the configuration using `config('wallet.transfer.model', Transfer::class)`. // The relationship is defined using the `from_id` foreign key. - return $wallet + /** @var class-string $model */ + $model = config('wallet.transfer.model', Transfer::class); + /** @var HasMany $hasMany */ + $hasMany = $wallet ->hasMany( // Retrieve the transfer model class from the configuration. // The default value is `Transfer::class`. - config('wallet.transfer.model', Transfer::class), + $model, // Define the foreign key for the relationship. // The foreign key is `from_id`. 'from_id' ); + + return $hasMany; } /** @@ -467,7 +490,7 @@ public function transfers(): HasMany * The transfer model class is retrieved from the configuration using `config('wallet.transfer.model', Transfer::class)`. * The relationship is defined using the `to_id` foreign key. * - * @return HasMany The `HasMany` relationship object representing all receiving transfers related to the wallet. + * @return HasMany The `HasMany` relationship object representing all receiving transfers related to the wallet. */ public function receivedTransfers(): HasMany { @@ -481,14 +504,19 @@ public function receivedTransfers(): HasMany // The `hasMany` method is used on the wallet instance to retrieve all receiving transfers related to the wallet. // The transfer model class is retrieved from the configuration using `config('wallet.transfer.model', Transfer::class)`. // The relationship is defined using the `to_id` foreign key. - return $wallet + /** @var class-string $model */ + $model = config('wallet.transfer.model', Transfer::class); + /** @var HasMany $hasMany */ + $hasMany = $wallet ->hasMany( // Retrieve the transfer model class from the configuration. // The default value is `Transfer::class`. - config('wallet.transfer.model', Transfer::class), + $model, // Define the foreign key for the relationship. // The foreign key is `to_id`. 'to_id' ); + + return $hasMany; } } diff --git a/src/Traits/HasWalletFloat.php b/src/Traits/HasWalletFloat.php index a624363d8..4bb78feba 100644 --- a/src/Traits/HasWalletFloat.php +++ b/src/Traits/HasWalletFloat.php @@ -33,12 +33,7 @@ trait HasWalletFloat use HasWallet; /** - * Withdraw funds from the wallet without checking the balance. - * - * @param float|int|string $amount The amount to withdraw. - * @param null|array $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param null|array $meta * * @throws AmountInvalid If the amount is invalid. * @throws RecordsNotFoundException If the wallet is not found. @@ -62,23 +57,17 @@ public function forceWithdrawFloat( $decimalPlaces = $math->powTen($decimalPlacesValue); // Convert the amount to the decimal format. - $result = $math->round($math->mul($amount, $decimalPlaces, $decimalPlacesValue)); + /** @var float|int|non-empty-string $amountValue */ + $amountValue = $amount; + $multiplied = $math->mul($amountValue, $decimalPlaces, $decimalPlacesValue); + $result = $math->round($multiplied); // Perform the withdrawal. return $this->forceWithdraw($result, $meta, $confirmed); } /** - * Deposit funds into the wallet. - * - * This method takes a float or int amount and deposits it into the wallet. - * It uses the math service to convert the amount to the wallet's decimal format, - * and then performs the deposit. - * - * @param float|int|string $amount The amount to deposit. - * @param null|array $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param null|array $meta * * @throws AmountInvalid If the amount is invalid. * @throws RecordsNotFoundException If the wallet is not found. @@ -96,27 +85,24 @@ public function depositFloat(float|int|string $amount, ?array $meta = null, bool ->decimal_places; // Get the decimal places. + /** @var non-empty-string $decimalPlaces */ $decimalPlaces = $math->powTen($decimalPlacesValue); // Convert the amount to the decimal format. // Rounding is needed to avoid issues with floats. - $result = $math->round($math->mul($amount, $decimalPlaces, $decimalPlacesValue)); + /** @var float|int|non-empty-string $amountValue */ + $amountValue = $amount; + /** @var non-empty-string $multiplied */ + $multiplied = $math->mul($amountValue, $decimalPlaces, $decimalPlacesValue); + /** @var non-empty-string $result */ + $result = $math->round($multiplied); // Perform the deposit. return $this->deposit($result, $meta, $confirmed); } /** - * Withdraw the specified float amount of money from the wallet. - * - * This method takes a float or int amount and withdraws it from the wallet. - * It uses the math service to convert the amount to the wallet's decimal format, - * and then performs the withdrawal. - * - * @param float|int|string $amount The amount to withdraw. - * @param null|array $meta Additional information for the transaction. - * @param bool $confirmed Whether the transaction is confirmed or not. - * @return Transaction The created transaction. + * @param null|array $meta * * @throws AmountInvalid If the amount is invalid. * @throws BalanceIsEmpty If the balance is empty. @@ -136,23 +122,24 @@ public function withdrawFloat(float|int|string $amount, ?array $meta = null, boo ->decimal_places; // Get the decimal places. + /** @var non-empty-string $decimalPlaces */ $decimalPlaces = $math->powTen($decimalPlacesValue); // Convert the amount to the decimal format. // Rounding is needed to avoid issues with floats. - $result = $math->round($math->mul($amount, $decimalPlaces, $decimalPlacesValue)); + /** @var float|int|non-empty-string $amountValue */ + $amountValue = $amount; + /** @var non-empty-string $multiplied */ + $multiplied = $math->mul($amountValue, $decimalPlaces, $decimalPlacesValue); + /** @var non-empty-string $result */ + $result = $math->round($multiplied); // Perform the withdrawal. return $this->withdraw($result, $meta, $confirmed); } /** - * Checks if the user can safely withdraw the specified amount of funds. - * - * @param float|int|string $amount The amount to withdraw. Can be specified as a float, int, or string. - * @return bool Returns TRUE if the withdrawal is possible, FALSE otherwise. - * - * @throws AmountInvalid If the amount is invalid (e.g., negative values). + * @throws AmountInvalid */ public function canWithdrawFloat(float|int|string $amount): bool { @@ -165,29 +152,24 @@ public function canWithdrawFloat(float|int|string $amount): bool ->decimal_places; // Get the decimal places. + /** @var non-empty-string $decimalPlaces */ $decimalPlaces = $math->powTen($decimalPlacesValue); // Convert the amount to the decimal format. // Rounding is needed to avoid issues with floats. - $result = $math->round($math->mul($amount, $decimalPlaces, $decimalPlacesValue)); + /** @var float|int|non-empty-string $amountValue */ + $amountValue = $amount; + /** @var non-empty-string $multiplied */ + $multiplied = $math->mul($amountValue, $decimalPlaces, $decimalPlacesValue); + /** @var non-empty-string $result */ + $result = $math->round($multiplied); // Check if the user can withdraw the specified amount. return $this->canWithdraw($result); } /** - * Transfers a specific amount of funds from this wallet to another. - * - * This method transfers the specified amount of funds from this wallet to another wallet. The amount can be - * specified as a float, int, or string. The transferred amount is rounded to the decimal places specified in the - * wallet's configuration. - * - * @param Wallet $wallet The wallet instance to which funds will be transferred. - * @param float|int|string $amount The amount of funds to transfer. Can be specified as a float, int, or string. - * @param ExtraDtoInterface|array|null $meta Additional metadata associated with the transfer. This can be - * used to store extra information about the transaction, such as - * reasons for the transfer or identifiers linking to other systems. - * @return Transfer Returns a Transfer object representing the completed transaction. + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount specified is invalid (e.g., negative values). * @throws BalanceIsEmpty If the balance of this wallet is empty. @@ -210,27 +192,24 @@ public function transferFloat( $decimalPlacesValue = app(CastServiceInterface::class)->getWallet($this)->decimal_places; // Get the decimal places. + /** @var non-empty-string $decimalPlaces */ $decimalPlaces = $math->powTen($decimalPlacesValue); // Convert the amount to the decimal format. // Rounding is needed to avoid issues with floats. - $result = $math->round($math->mul($amount, $decimalPlaces, $decimalPlacesValue)); + /** @var float|int|non-empty-string $amountValue */ + $amountValue = $amount; + /** @var non-empty-string $multiplied */ + $multiplied = $math->mul($amountValue, $decimalPlaces, $decimalPlacesValue); + /** @var non-empty-string $result */ + $result = $math->round($multiplied); // Perform the transfer. return $this->transfer($wallet, $result, $meta); } /** - * Safely transfers funds from this wallet to another. - * - * This method will not throw an exception if the transfer fails. Instead, it will return null. - * - * @param Wallet $wallet The wallet to transfer funds to. - * @param float|int|string $amount The amount to transfer. - * @param ExtraDtoInterface|array|null $meta Additional information for the transaction. - * This can be an instance of an ExtraDtoInterface - * or an array of arbitrary data. - * @return Transfer|null The created transaction, or null if the transfer fails. + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount is invalid. */ @@ -260,18 +239,7 @@ public function safeTransferFloat( } /** - * Forces a transfer of funds from this wallet to another, bypassing certain safety checks. - * - * This method is intended for use in scenarios where a transfer must be completed regardless of - * the usual validation checks (e.g., sufficient funds, wallet status). It is critical to use this - * method with caution as it can result in negative balances or other unintended consequences. - * - * @param Wallet $wallet The wallet instance to which funds will be transferred. - * @param float|int|string $amount The amount of funds to transfer. Can be specified as a float, int, or string. - * @param ExtraDtoInterface|array|null $meta Additional metadata associated with the transfer. This - * can be used to store extra information about the transaction, such as reasons for the transfer or - * identifiers linking to other systems. - * @return Transfer Returns a Transfer object representing the completed transaction. + * @param ExtraDtoInterface|array|null $meta * * @throws AmountInvalid If the amount specified is invalid (e.g., negative values). * @throws RecordsNotFoundException If the target wallet cannot be found. @@ -293,12 +261,18 @@ public function forceTransferFloat( $decimalPlacesValue = app(CastServiceInterface::class)->getWallet($this)->decimal_places; // Calculate the decimal places value as a power of ten. + /** @var non-empty-string $decimalPlaces */ $decimalPlaces = $math->powTen($decimalPlacesValue); // Convert the amount to the decimal format. // Rounding is needed to avoid issues with floats. // The result is the amount in the correct decimal format. - $result = $math->round($math->mul($amount, $decimalPlaces, $decimalPlacesValue)); + /** @var float|int|non-empty-string $amountValue */ + $amountValue = $amount; + /** @var non-empty-string $multiplied */ + $multiplied = $math->mul($amountValue, $decimalPlaces, $decimalPlacesValue); + /** @var non-empty-string $result */ + $result = $math->round($multiplied); // Perform the transfer. // This method will not throw an exception if the transfer fails. Instead, it will return null. @@ -306,13 +280,7 @@ public function forceTransferFloat( } /** - * Get the balance of the wallet as a float. - * - * This method returns the balance of the wallet as a string, and then formats it as a float with the - * correct number of decimal places. The number of decimal places is obtained from the wallet's - * `decimal_places` attribute. - * - * @return non-empty-string The balance of the wallet as a string, formatted as a float. + * @return non-empty-string */ public function getBalanceFloatAttribute(): string { @@ -327,13 +295,16 @@ public function getBalanceFloatAttribute(): string $decimalPlacesValue = $wallet->decimal_places; // Use the formatter service to format the balance as a float. - return app(FormatterServiceInterface::class)->floatValue( + /** @var non-empty-string $result */ + $result = app(FormatterServiceInterface::class)->floatValue( // The balance of the wallet. $balance, // The number of decimal places for the wallet. $decimalPlacesValue, ); + + return $result; } /** diff --git a/src/Traits/HasWallets.php b/src/Traits/HasWallets.php index 0c094e8e4..d20eed14d 100644 --- a/src/Traits/HasWallets.php +++ b/src/Traits/HasWallets.php @@ -9,6 +9,7 @@ use Bavix\Wallet\Models\Wallet as WalletModel; use Bavix\Wallet\Services\WalletServiceInterface; use function config; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Support\Collection; @@ -99,19 +100,24 @@ public function getWalletOrFail(string $slug): WalletModel * 'wallet.model' key. If the key is not found, the default wallet model is * used. * - * @return MorphMany The MorphMany relationship object. + * @return MorphMany The MorphMany relationship object. */ public function wallets(): MorphMany { // Define a MorphMany relationship between the current model (the "holder") // and the wallet model. - return $this + /** @var class-string $model */ + $model = config('wallet.wallet.model', WalletModel::class); + /** @var MorphMany $morphMany */ + $morphMany = $this ->morphMany( // Get the wallet model from the configuration. - config('wallet.wallet.model', WalletModel::class), + $model, // Specify the name of the polymorphic relation. 'holder' ); + + return $morphMany; } /** @@ -161,7 +167,6 @@ public function createWallet(array $data): WalletModel * This method checks if a wallet with the given slug exists for the current model. * * @param string $slug The slug of the wallet. - * @return bool Returns true if the wallet exists, false otherwise. */ public function hasWallet(string $slug): bool { diff --git a/src/Traits/MorphOneWallet.php b/src/Traits/MorphOneWallet.php index ae245eafe..b756b9f89 100644 --- a/src/Traits/MorphOneWallet.php +++ b/src/Traits/MorphOneWallet.php @@ -6,6 +6,7 @@ use Bavix\Wallet\Models\Wallet as WalletModel; use Bavix\Wallet\Services\CastServiceInterface; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphOne; /** @@ -20,7 +21,7 @@ trait MorphOneWallet /** * Get default Wallet. This method is used for Eager Loading. * - * @return MorphOne + * @return MorphOne */ public function wallet(): MorphOne { @@ -36,11 +37,15 @@ public function wallet(): MorphOne $related = config('wallet.wallet.model', WalletModel::class); // Eager load the wallet for the related model. - return $castService + /** @var MorphOne $morphOne */ + $morphOne = $castService ->getHolder($this) // Get the related holder model. ->morphOne($related, 'holder') // Define the Eloquent relationship. ->withTrashed() // Include soft deleted wallets. - ->where('slug', config('wallet.wallet.default.slug', 'default')) // Filter by the default wallet slug. + ->where( + 'slug', + (string) config('wallet.wallet.default.slug', 'default') + ) // Filter by the default wallet slug. ->withDefault(static function (WalletModel $wallet, object $holder) use ( $castService ) { // Define the default wallet values. @@ -55,18 +60,26 @@ public function wallet(): MorphOne : config('wallet.wallet.default.slug', 'default'); // Fill the default wallet attributes. - $wallet->forceFill(array_merge(config('wallet.wallet.creating', []), [ - 'name' => config('wallet.wallet.default.name', 'Default Wallet'), // Default wallet name. + /** @var array $creating */ + $creating = config('wallet.wallet.creating', []); + /** @var array $defaultMeta */ + $defaultMeta = config('wallet.wallet.default.meta', []); + /** @var array $attributes */ + $attributes = array_merge($creating, [ + 'name' => (string) config('wallet.wallet.default.name', 'Default Wallet'), // Default wallet name. 'slug' => $slug, // Default wallet slug. - 'meta' => config('wallet.wallet.default.meta', []), // Default wallet metadata. + 'meta' => $defaultMeta, // Default wallet metadata. 'balance' => 0, // Default wallet balance. - ])); + ]); + $wallet->forceFill($attributes); if ($model->exists) { // Set the related model on the wallet. $wallet->setRelation('holder', $model->withoutRelations()); } }); + + return $morphOne; } /** From c75e568b1077c5a1ef1264e540b5a1715546d2ad Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 17 Nov 2025 20:49:21 +0300 Subject: [PATCH 2/3] Refactor balance handling in Wallet model - Simplified the conversion of the available balance to a string by removing the conditional check for string type. - Ensured consistent type casting for better clarity and maintainability. --- src/Models/Wallet.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Models/Wallet.php b/src/Models/Wallet.php index a39ae6af5..6406915b1 100644 --- a/src/Models/Wallet.php +++ b/src/Models/Wallet.php @@ -144,7 +144,7 @@ public function refreshBalance(): bool /** @var float|int|non-empty-string $balanceRaw */ $balanceRaw = $this->getAvailableBalanceAttribute(); /** @var non-empty-string $balance */ - $balance = is_string($balanceRaw) ? $balanceRaw : (string) $balanceRaw; + $balance = (string) $balanceRaw; if (app(MathServiceInterface::class)->compare($whatIs, $balance) === 0) { return true; } From f4a7c87ba5cb5f8a0332ad722624074cca44e75f Mon Sep 17 00:00:00 2001 From: Maxim Babichev Date: Mon, 17 Nov 2025 20:56:53 +0300 Subject: [PATCH 3/3] Add deptrac for dependency analysis and update configuration - Added "deptrac/deptrac" as a development dependency in composer.json. - Updated deptrac.yaml to use "classLike" collectors instead of "className" for better compatibility with the latest deptrac standards. - Modified GitHub Actions workflow to remove the installation step for deptrac, as it is now included in composer dependencies. --- .github/workflows/deptrac.yaml | 4 - composer.json | 4 +- deptrac.yaml | 145 +++++++++++++++++---------------- 3 files changed, 76 insertions(+), 77 deletions(-) diff --git a/.github/workflows/deptrac.yaml b/.github/workflows/deptrac.yaml index 68c6e3e81..cdecd98d3 100644 --- a/.github/workflows/deptrac.yaml +++ b/.github/workflows/deptrac.yaml @@ -64,9 +64,5 @@ jobs: - name: Install dependencies run: composer install --prefer-dist --no-progress - - name: Install deptrac - run: composer req --dev qossmic/deptrac-shim - if: hashFiles('vendor/bin/deptrac') == '' - - name: Run deptrac run: php vendor/bin/deptrac analyse diff --git a/composer.json b/composer.json index 933f906bb..5efa57638 100644 --- a/composer.json +++ b/composer.json @@ -31,6 +31,7 @@ "ramsey/uuid": "^4.0" }, "require-dev": { + "deptrac/deptrac": "^4.2", "driftingly/rector-laravel": "^2.0", "ergebnis/phpstan-rules": "^2.1", "infection/infection": "~0.27", @@ -77,7 +78,8 @@ "ecs-fix": "@php vendor/bin/ecs check --fix", "ecs-cc": "@php vendor/bin/ecs --clear-cache", "rector": "@php vendor/bin/rector process --dry-run", - "rector-fix": "@php vendor/bin/rector process" + "rector-fix": "@php vendor/bin/rector process", + "deptrac": "@php vendor/bin/deptrac analyse" }, "extra": { "laravel": { diff --git a/deptrac.yaml b/deptrac.yaml index adb477e50..458650789 100644 --- a/deptrac.yaml +++ b/deptrac.yaml @@ -1,167 +1,166 @@ -parameters: +deptrac: paths: - ./src - layers: - name: Legacy collectors: - - type: className - regex: ^Bavix\\.*\\Objects\\Cart$ + - type: classLike + value: ^Bavix\\.*\\Objects\\Cart$ - name: Contract collectors: - - type: className - regex: ^Bavix\\Wallet\\Interfaces\\.* - - type: className - regex: ^Bavix\\Wallet\\External\\Contracts\\.* - - type: className - regex: ^Bavix\\Wallet\\External\\Dto\\.* + - type: classLike + value: ^Bavix\\Wallet\\Interfaces\\.* + - type: classLike + value: ^Bavix\\Wallet\\External\\Contracts\\.* + - type: classLike + value: ^Bavix\\Wallet\\External\\Dto\\.* - name: Api collectors: - - type: className - regex: ^Bavix\\Wallet\\External\\Api\\.*Interface$ + - type: classLike + value: ^Bavix\\Wallet\\External\\Api\\.*Interface$ - name: ApiQuery collectors: - - type: className - regex: ^Bavix\\Wallet\\External\\Api\\.*Query$ + - type: classLike + value: ^Bavix\\Wallet\\External\\Api\\.*Query$ - name: ApiHandler collectors: - - type: className - regex: ^Bavix\\Wallet\\External\\Api\\.*Handler$ + - type: classLike + value: ^Bavix\\Wallet\\External\\Api\\.*Handler$ - name: UI collectors: - - type: className - regex: ^Bavix\\.*\\Traits\\.* + - type: classLike + value: ^Bavix\\.*\\Traits\\.* - name: UIException collectors: - - type: className - regex: ^Illuminate\\Database\\Eloquent\\ModelNotFoundException$ - - type: className - regex: ^Bavix\\Wallet\\Exceptions\\.* + - type: classLike + value: ^Illuminate\\Database\\Eloquent\\ModelNotFoundException$ + - type: classLike + value: ^Bavix\\Wallet\\Exceptions\\.* # internal - name: InternalException collectors: - - type: className - regex: ^Bavix\\.*\\Internal\\Exceptions\\.* + - type: classLike + value: ^Bavix\\.*\\Internal\\Exceptions\\.* - name: InternalListener collectors: - - type: className - regex: ^Bavix\\.*\\Internal\\Listeners\\.* + - type: classLike + value: ^Bavix\\.*\\Internal\\Listeners\\.* - name: Event collectors: - - type: className - regex: ^Bavix\\.*\\Internal\\Events\\.*Event$ + - type: classLike + value: ^Bavix\\.*\\Internal\\Events\\.*Event$ - name: EventInterface collectors: - - type: className - regex: ^Bavix\\.*\\Internal\\Events\\.*EventInterface$ + - type: classLike + value: ^Bavix\\.*\\Internal\\Events\\.*EventInterface$ - name: Dto collectors: - - type: className - regex: ^Bavix\\.*\\Internal\\Dto\\.*Dto$ + - type: classLike + value: ^Bavix\\.*\\Internal\\Dto\\.*Dto$ - name: DtoInterface collectors: - - type: className - regex: ^Bavix\\.*\\Internal\\Dto\\.*DtoInterface$ + - type: classLike + value: ^Bavix\\.*\\Internal\\Dto\\.*DtoInterface$ - name: AssemblerDto collectors: - - type: className - regex: ^Bavix\\.*\\Internal\\Assembler\\.*DtoAssembler$ + - type: classLike + value: ^Bavix\\.*\\Internal\\Assembler\\.*DtoAssembler$ - name: AssemblerDtoInterface collectors: - - type: className - regex: ^Bavix\\.*\\Internal\\Assembler\\.*DtoAssemblerInterface$ + - type: classLike + value: ^Bavix\\.*\\Internal\\Assembler\\.*DtoAssemblerInterface$ - name: QueryInterface collectors: - - type: className - regex: ^Bavix\\.*Internal\\Query\\.*QueryInterface$ + - type: classLike + value: ^Bavix\\.*Internal\\Query\\.*QueryInterface$ - name: Query collectors: - - type: className - regex: ^Bavix\\.*Internal\\Query\\.*Query$ + - type: classLike + value: ^Bavix\\.*Internal\\Query\\.*Query$ - name: RepositoryInterface collectors: - - type: className - regex: ^Bavix\\.*Internal\\Repository\\.*RepositoryInterface$ + - type: classLike + value: ^Bavix\\.*Internal\\Repository\\.*RepositoryInterface$ - name: Repository collectors: - - type: className - regex: ^Bavix\\.*Internal\\Repository\\.*Repository$ + - type: classLike + value: ^Bavix\\.*Internal\\Repository\\.*Repository$ - name: Transform collectors: - - type: className - regex: ^Bavix\\.*Internal\\Transform\\.*DtoTransformer$ + - type: classLike + value: ^Bavix\\.*Internal\\Transform\\.*DtoTransformer$ - name: TransformInterface collectors: - - type: className - regex: ^Bavix\\.*Internal\\Transform\\.*DtoTransformerInterface$ + - type: classLike + value: ^Bavix\\.*Internal\\Transform\\.*DtoTransformerInterface$ - name: Infra collectors: - - type: className - regex: ^Bavix\\.*Internal\\Service\\.*Service$ + - type: classLike + value: ^Bavix\\.*Internal\\Service\\.*Service$ - name: ServiceDecorator collectors: - - type: className - regex: ^Bavix\\.*Decorator\\.*Decorator + - type: classLike + value: ^Bavix\\.*Decorator\\.*Decorator # contracts - name: Model collectors: - - type: className - regex: ^Bavix\\.*Models\\Transaction$ - - type: className - regex: ^Bavix\\.*Models\\Transfer$ - - type: className - regex: ^Bavix\\.*Models\\Wallet$ + - type: classLike + value: ^Bavix\\.*Models\\Transaction$ + - type: classLike + value: ^Bavix\\.*Models\\Transfer$ + - type: classLike + value: ^Bavix\\.*Models\\Wallet$ - name: Service collectors: - - type: className - regex: ^Bavix\\.*Services\\.*Service$ + - type: classLike + value: ^Bavix\\.*Services\\.*Service$ - name: ServiceInterface collectors: - - type: className - regex: ^Bavix\\.*Service\\.*ServiceInterface$ - - type: className - regex: ^Bavix\\.*Services\\.*ServiceInterface$ + - type: classLike + value: ^Bavix\\.*Service\\.*ServiceInterface$ + - type: classLike + value: ^Bavix\\.*Services\\.*ServiceInterface$ # framework - name: EloquentModel collectors: - - type: className - regex: ^Illuminate\\Database\\Eloquent\\Model$ + - type: classLike + value: ^Illuminate\\Database\\Eloquent\\Model$ - name: Config collectors: - - type: className - regex: ^Illuminate\\Config\\Repository$ + - type: classLike + value: ^Illuminate\\Config\\Repository$ - name: Cache collectors: - - type: className - regex: ^Illuminate\\Contracts\\Cache\\Repository$ + - type: classLike + value: ^Illuminate\\Contracts\\Cache\\Repository$ ruleset: Contract: @@ -169,6 +168,7 @@ parameters: - DtoInterface - UIException - Model + - EloquentModel ApiQuery: - Api @@ -196,6 +196,7 @@ parameters: - UIException - Contract - Model + - EloquentModel - Legacy # delete as soon as possible UIException: