From 4c5f7798515e7101f3c2e696c0336ed0d1ba2299 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 9 May 2019 21:32:18 +0300 Subject: [PATCH 1/7] update composer.json --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 612a8ffa1..3eefbf2ff 100644 --- a/composer.json +++ b/composer.json @@ -24,14 +24,14 @@ ], "require": { "php": "^7.1", - "laravel/framework": "~5.5.0|~5.6.0|~5.7.0|~5.8.0", + "illuminate/database": "~5.5.0|~5.6.0|~5.7.0|~5.8.0", "ramsey/uuid": "^3.0" }, "require-dev": { "doctrine/dbal": "^2.8", "mockery/mockery": "^1.2", "orchestra/testbench": "^3.7", - "phpunit/phpunit": "^7.4" + "phpunit/phpunit": "^8.1" }, "autoload": { "psr-4": { From 4232183205f3f3197ad31e2648ce5b81a8a02308 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Thu, 9 May 2019 22:05:39 +0300 Subject: [PATCH 2/7] fix travis ci --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3eefbf2ff..ae89bf47e 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "doctrine/dbal": "^2.8", "mockery/mockery": "^1.2", "orchestra/testbench": "^3.7", - "phpunit/phpunit": "^8.1" + "phpunit/phpunit": "^7.5" }, "autoload": { "psr-4": { From cca3e70bfd0968d686f4ff608e712b69ad39c8b4 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Sun, 12 May 2019 22:23:03 +0300 Subject: [PATCH 3/7] update changelog --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index 23a8b30b7..69a0e8abb 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Add support Themosis Framework ## [2.2.2] - 2019-05-12 ### Fixed From 88ea205f3e9a84ceb7af18a2a31c63ada683128b Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Sun, 12 May 2019 22:28:38 +0300 Subject: [PATCH 4/7] patch changelog )) --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 69a0e8abb..ff4b8ecf4 100644 --- a/changelog.md +++ b/changelog.md @@ -219,3 +219,4 @@ The operation is now executed in the transaction and updates the new `refund` fi [1.1.1]: https://github.com/bavix/laravel-wallet/compare/1.1.0...1.1.1 [1.1.0]: https://github.com/bavix/laravel-wallet/compare/1.0.0...1.1.0 [1.0.0]: https://github.com/bavix/laravel-wallet/compare/0.0.1...1.0.0 +[0.0.1]: https://github.com/bavix/laravel-wallet/compare/d181a99e751c5138694580ca4361d5129baa26b3...0.0.1 From ac683d5976437f9fdb4d700d890790b6a6a040c5 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Mon, 13 May 2019 11:53:46 +0300 Subject: [PATCH 5/7] global upgrade --- changelog.md | 5 + ...11_06_222923_create_transactions_table.php | 24 +- ...18_11_07_192923_create_transfers_table.php | 40 +-- ...18_11_07_202152_update_transfers_table.php | 28 +- ...2018_11_15_124230_create_wallets_table.php | 10 +- ...11_19_164609_update_transactions_table.php | 10 +- ...8_11_20_133759_add_fee_transfers_table.php | 8 +- ...1_22_131953_add_status_transfers_table.php | 8 +- ..._22_133438_drop_refund_transfers_table.php | 8 +- ...3_111553_update_status_transfers_table.php | 113 +++++++ src/Interfaces/Wallet.php | 9 +- src/Interfaces/WalletFloat.php | 9 +- src/Models/Transfer.php | 1 + src/Models/Wallet.php | 22 +- src/Traits/CanPay.php | 113 ++++--- src/Traits/HasGift.php | 36 +-- src/Traits/HasWallet.php | 305 +++++++++--------- src/Traits/HasWalletFloat.php | 31 +- src/Traits/HasWallets.php | 20 +- tests/GiftTest.php | 12 +- tests/Models/User.php | 2 +- tests/TaxTest.php | 2 +- tests/TestCase.php | 2 +- tests/factories/BuyerFactory.php | 4 +- tests/factories/ItemFactory.php | 4 +- tests/factories/ItemTaxFactory.php | 4 +- tests/factories/UserFactory.php | 4 +- tests/factories/UserFloatFactory.php | 4 +- tests/factories/UserMultiFactory.php | 4 +- .../2014_10_12_000000_create_users_table.php | 6 +- .../2018_11_08_214421_create_items_table.php | 6 +- 31 files changed, 500 insertions(+), 354 deletions(-) create mode 100644 database/migrations_v2/2019_05_13_111553_update_status_transfers_table.php diff --git a/changelog.md b/changelog.md index 23a8b30b7..05feb5c5c 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- In all the methods of translations have added the status of the transfer. + +### Fixed +- correction of errors during installation is not correct status. ## [2.2.2] - 2019-05-12 ### Fixed diff --git a/database/migrations_v1/2018_11_06_222923_create_transactions_table.php b/database/migrations_v1/2018_11_06_222923_create_transactions_table.php index d7b4dfa7f..1d5c34f59 100644 --- a/database/migrations_v1/2018_11_06_222923_create_transactions_table.php +++ b/database/migrations_v1/2018_11_06_222923_create_transactions_table.php @@ -1,27 +1,19 @@ getTable(); - } - /** * @return void */ public function up(): void { - Schema::create($this->table(), function(Blueprint $table) { + Schema::create($this->table(), function (Blueprint $table) { $table->increments('id'); $table->morphs('payable'); $table->enum('type', ['deposit', 'withdraw'])->index(); @@ -37,6 +29,14 @@ public function up(): void }); } + /** + * @return string + */ + protected function table(): string + { + return (new Transaction())->getTable(); + } + /** * @return void */ diff --git a/database/migrations_v1/2018_11_07_192923_create_transfers_table.php b/database/migrations_v1/2018_11_07_192923_create_transfers_table.php index bd81d47e0..b88256f18 100644 --- a/database/migrations_v1/2018_11_07_192923_create_transfers_table.php +++ b/database/migrations_v1/2018_11_07_192923_create_transfers_table.php @@ -1,36 +1,20 @@ getTable(); - } - - /** - * @return string - */ - protected function table(): string - { - return (new Transfer())->getTable(); - } - /** * @return void */ public function up(): void { - Schema::create($this->table(), function(Blueprint $table) { + Schema::create($this->table(), function (Blueprint $table) { $table->increments('id'); $table->morphs('from'); $table->morphs('to'); @@ -51,6 +35,22 @@ public function up(): void }); } + /** + * @return string + */ + protected function table(): string + { + return (new Transfer())->getTable(); + } + + /** + * @return string + */ + protected function transactionTable(): string + { + return (new Transaction())->getTable(); + } + /** * @return void */ diff --git a/database/migrations_v1/2018_11_07_202152_update_transfers_table.php b/database/migrations_v1/2018_11_07_202152_update_transfers_table.php index 5a76ec2ac..53605572f 100644 --- a/database/migrations_v1/2018_11_07_202152_update_transfers_table.php +++ b/database/migrations_v1/2018_11_07_202152_update_transfers_table.php @@ -1,29 +1,21 @@ getTable(); - } - /** * @return void */ public function up(): void { - Schema::table($this->table(), function(Blueprint $table) { + Schema::table($this->table(), function (Blueprint $table) { $table->boolean('refund') ->after('withdraw_id') ->default(0); @@ -34,12 +26,20 @@ public function up(): void }); } + /** + * @return string + */ + protected function table(): string + { + return (new Transfer())->getTable(); + } + /** * @return void */ public function down(): void { - Schema::table($this->table(), function(Blueprint $table) { + Schema::table($this->table(), function (Blueprint $table) { if (!(DB::connection() instanceof SQLiteConnection)) { $table->dropIndex('from_to_refund_ind'); $table->dropIndex('from_refund_ind'); diff --git a/database/migrations_v2/2018_11_15_124230_create_wallets_table.php b/database/migrations_v2/2018_11_15_124230_create_wallets_table.php index 2f3b411e8..4d251ee85 100644 --- a/database/migrations_v2/2018_11_15_124230_create_wallets_table.php +++ b/database/migrations_v2/2018_11_15_124230_create_wallets_table.php @@ -1,12 +1,12 @@ table(), function(Blueprint $table) { + Schema::create($this->table(), function (Blueprint $table) { $table->increments('id'); $table->morphs('holder'); $table->string('name'); diff --git a/database/migrations_v2/2018_11_19_164609_update_transactions_table.php b/database/migrations_v2/2018_11_19_164609_update_transactions_table.php index 7a478cdb6..5a4eabc10 100644 --- a/database/migrations_v2/2018_11_19_164609_update_transactions_table.php +++ b/database/migrations_v2/2018_11_19_164609_update_transactions_table.php @@ -1,11 +1,11 @@ table(), function(Blueprint $table) { + Schema::table($this->table(), function (Blueprint $table) { $table->unsignedInteger('wallet_id') ->nullable() ->after('payable_id'); diff --git a/database/migrations_v2/2018_11_20_133759_add_fee_transfers_table.php b/database/migrations_v2/2018_11_20_133759_add_fee_transfers_table.php index af591ed82..f7f42dd86 100644 --- a/database/migrations_v2/2018_11_20_133759_add_fee_transfers_table.php +++ b/database/migrations_v2/2018_11_20_133759_add_fee_transfers_table.php @@ -1,9 +1,9 @@ table(), function(Blueprint $table) { + Schema::table($this->table(), function (Blueprint $table) { $table->bigInteger('fee') ->default(0) ->after('withdraw_id'); diff --git a/database/migrations_v2/2018_11_22_131953_add_status_transfers_table.php b/database/migrations_v2/2018_11_22_131953_add_status_transfers_table.php index da359c9d8..982d6b366 100644 --- a/database/migrations_v2/2018_11_22_131953_add_status_transfers_table.php +++ b/database/migrations_v2/2018_11_22_131953_add_status_transfers_table.php @@ -1,10 +1,10 @@ table(), function(Blueprint $table) { + Schema::table($this->table(), function (Blueprint $table) { $enums = [ Transfer::STATUS_PAID, Transfer::STATUS_REFUND, diff --git a/database/migrations_v2/2018_11_22_133438_drop_refund_transfers_table.php b/database/migrations_v2/2018_11_22_133438_drop_refund_transfers_table.php index 0672fd2e2..52c4b7216 100644 --- a/database/migrations_v2/2018_11_22_133438_drop_refund_transfers_table.php +++ b/database/migrations_v2/2018_11_22_133438_drop_refund_transfers_table.php @@ -1,11 +1,11 @@ table(), function(Blueprint $table) { + Schema::table($this->table(), function (Blueprint $table) { if (!(DB::connection() instanceof SQLiteConnection)) { $table->dropIndex('from_to_refund_ind'); $table->dropIndex('from_refund_ind'); diff --git a/database/migrations_v2/2019_05_13_111553_update_status_transfers_table.php b/database/migrations_v2/2019_05_13_111553_update_status_transfers_table.php new file mode 100644 index 000000000..66fb08ad3 --- /dev/null +++ b/database/migrations_v2/2019_05_13_111553_update_status_transfers_table.php @@ -0,0 +1,113 @@ +getTable(); + } + + /** + * @return void + */ + public function up(): void + { + Schema::table($this->table(), function (Blueprint $table) { + $table->renameColumn('status', 'tmpStatus'); + }); + + Schema::table($this->table(), function (Blueprint $table) { + $table->renameColumn('status_last', 'tmpStatusLast'); + }); + + Schema::table($this->table(), function (Blueprint $table) { + $enums = [ + Transfer::STATUS_TRANSFER, + Transfer::STATUS_PAID, + Transfer::STATUS_REFUND, + Transfer::STATUS_GIFT, + ]; + + $table->enum('status', $enums) + ->default(Transfer::STATUS_TRANSFER); + + $table->enum('status_last', $enums) + ->nullable(); + }); + + DB::table($this->table()) + ->update([ + 'status' => DB::raw('tmpStatus'), + 'status_last' => DB::raw('tmpStatusLast'), + ]); + + Schema::table($this->table(), function (Blueprint $table) { + $table->dropColumn('tmpStatus'); + }); + + Schema::table($this->table(), function (Blueprint $table) { + $table->dropColumn('tmpStatusLast'); + }); + } + + /** + * @return void + */ + public function down(): void + { + Schema::table($this->table(), function (Blueprint $table) { + $table->renameColumn('status', 'tmpStatus'); + }); + + Schema::table($this->table(), function (Blueprint $table) { + $table->renameColumn('status_last', 'tmpStatusLast'); + }); + + Schema::table($this->table(), function (Blueprint $table) { + $enums = [ + Transfer::STATUS_PAID, + Transfer::STATUS_REFUND, + Transfer::STATUS_GIFT, + ]; + + $table->enum('status', $enums) + ->default(Transfer::STATUS_PAID); + + $table->enum('status_last', $enums) + ->nullable(); + }); + + DB::table($this->table()) + ->where('tmpStatus', Transfer::STATUS_TRANSFER) + ->update(['tmpStatus' => Transfer::STATUS_PAID]); + + DB::table($this->table()) + ->where('tmpStatusLast', Transfer::STATUS_TRANSFER) + ->update(['tmpStatusLast' => Transfer::STATUS_PAID]); + + DB::table($this->table()) + ->update([ + 'status' => DB::raw('tmpStatus'), + 'status_last' => DB::raw('tmpStatusLast'), + ]); + + Schema::table($this->table(), function (Blueprint $table) { + $table->dropColumn('tmpStatus'); + }); + + Schema::table($this->table(), function (Blueprint $table) { + $table->dropColumn('tmpStatusLast'); + }); + } + +} diff --git a/src/Interfaces/Wallet.php b/src/Interfaces/Wallet.php index ddb971df1..5c01c6b6d 100644 --- a/src/Interfaces/Wallet.php +++ b/src/Interfaces/Wallet.php @@ -36,25 +36,28 @@ public function forceWithdraw(int $amount, ?array $meta = null, bool $confirmed * @param self $wallet * @param int $amount * @param array|null $meta + * @param string $status * @return Transfer */ - public function transfer(self $wallet, int $amount, ?array $meta = null): Transfer; + public function transfer(self $wallet, int $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer; /** * @param self $wallet * @param int $amount * @param array|null $meta + * @param string $status * @return null|Transfer */ - public function safeTransfer(self $wallet, int $amount, ?array $meta = null): ?Transfer; + public function safeTransfer(self $wallet, int $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): ?Transfer; /** * @param Wallet $wallet * @param int $amount * @param array|null $meta + * @param string $status * @return Transfer */ - public function forceTransfer(Wallet $wallet, int $amount, ?array $meta = null): Transfer; + public function forceTransfer(Wallet $wallet, int $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer; /** * @param int $amount diff --git a/src/Interfaces/WalletFloat.php b/src/Interfaces/WalletFloat.php index 3ca0a2b2c..f54c4bd1a 100644 --- a/src/Interfaces/WalletFloat.php +++ b/src/Interfaces/WalletFloat.php @@ -35,25 +35,28 @@ public function forceWithdrawFloat(float $amount, ?array $meta = null, bool $con * @param Wallet $wallet * @param float $amount * @param array|null $meta + * @param string $status * @return Transfer */ - public function transferFloat(Wallet $wallet, float $amount, ?array $meta = null): Transfer; + public function transferFloat(Wallet $wallet, float $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer; /** * @param Wallet $wallet * @param float $amount * @param array|null $meta + * @param string $status * @return null|Transfer */ - public function safeTransferFloat(Wallet $wallet, float $amount, ?array $meta = null): ?Transfer; + public function safeTransferFloat(Wallet $wallet, float $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): ?Transfer; /** * @param Wallet $wallet * @param float $amount * @param array|null $meta + * @param string $status * @return Transfer */ - public function forceTransferFloat(Wallet $wallet, float $amount, ?array $meta = null): Transfer; + public function forceTransferFloat(Wallet $wallet, float $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer; /** * @param float $amount diff --git a/src/Models/Transfer.php b/src/Models/Transfer.php index d83abb7d6..b6557fa4c 100644 --- a/src/Models/Transfer.php +++ b/src/Models/Transfer.php @@ -26,6 +26,7 @@ class Transfer extends Model { + public const STATUS_TRANSFER = 'transfer'; public const STATUS_PAID = 'paid'; public const STATUS_REFUND = 'refund'; public const STATUS_GIFT = 'gift'; diff --git a/src/Models/Wallet.php b/src/Models/Wallet.php index 17f89aef9..bf551499f 100644 --- a/src/Models/Wallet.php +++ b/src/Models/Wallet.php @@ -72,17 +72,6 @@ public function setNameAttribute(string $name): void } } - /** - * @return int - */ - public function getAvailableBalance(): int - { - return $this->transactions() - ->where('wallet_id', $this->getKey()) - ->where('confirmed', true) - ->sum('amount'); - } - /** * @return bool */ @@ -95,6 +84,17 @@ public function calculateBalance(): bool return $this->save(); } + /** + * @return int + */ + public function getAvailableBalance(): int + { + return $this->transactions() + ->where('wallet_id', $this->getKey()) + ->where('confirmed', true) + ->sum('amount'); + } + /** * @return MorphTo */ diff --git a/src/Traits/CanPay.php b/src/Traits/CanPay.php index 19060e8d8..b4849ff00 100644 --- a/src/Traits/CanPay.php +++ b/src/Traits/CanPay.php @@ -24,7 +24,26 @@ public function payFree(Product $product): Transfer throw new ProductEnded(trans('wallet::errors.product_stock')); } - return $this->transfer($product, 0, $product->getMetaProduct()); + return $this->transfer( + $product, + 0, + $product->getMetaProduct(), + Transfer::STATUS_PAID + ); + } + + /** + * @param Product $product + * @param bool $force + * @return Transfer|null + */ + public function safePay(Product $product, bool $force = false): ?Transfer + { + try { + return $this->pay($product, $force); + } catch (\Throwable $throwable) { + return null; + } } /** @@ -40,24 +59,20 @@ public function pay(Product $product, bool $force = false): Transfer } if ($force) { - return $this->forceTransfer($product, $product->getAmountProduct(), $product->getMetaProduct()); + return $this->forceTransfer( + $product, + $product->getAmountProduct(), + $product->getMetaProduct(), + Transfer::STATUS_PAID + ); } - return $this->transfer($product, $product->getAmountProduct(), $product->getMetaProduct()); - } - - /** - * @param Product $product - * @param bool $force - * @return Transfer|null - */ - public function safePay(Product $product, bool $force = false): ?Transfer - { - try { - return $this->pay($product, $force); - } catch (\Throwable $throwable) { - return null; - } + return $this->transfer( + $product, + $product->getAmountProduct(), + $product->getMetaProduct(), + Transfer::STATUS_PAID + ); } /** @@ -72,27 +87,17 @@ public function forcePay(Product $product): Transfer /** * @param Product $product + * @param bool $force * @param bool $gifts - * @return null|Transfer + * @return bool */ - public function paid(Product $product, bool $gifts = false): ?Transfer + public function safeRefund(Product $product, bool $force = false, bool $gifts = false): bool { - $status = [Transfer::STATUS_PAID]; - if ($gifts) { - $status[] = Transfer::STATUS_GIFT; + try { + return $this->refund($product, $force, $gifts); + } catch (\Throwable $throwable) { + return false; } - - /** - * @var Model $product - * @var Transfer $query - */ - $query = $this->transfers(); - return $query - ->where('to_type', $product->getMorphClass()) - ->where('to_id', $product->getKey()) - ->whereIn('status', $status) - ->orderBy('id', 'desc') - ->first(); } /** @@ -137,17 +142,27 @@ public function refund(Product $product, bool $force = false, bool $gifts = fals /** * @param Product $product - * @param bool $force * @param bool $gifts - * @return bool + * @return null|Transfer */ - public function safeRefund(Product $product, bool $force = false, bool $gifts = false): bool + public function paid(Product $product, bool $gifts = false): ?Transfer { - try { - return $this->refund($product, $force, $gifts); - } catch (\Throwable $throwable) { - return false; + $status = [Transfer::STATUS_PAID]; + if ($gifts) { + $status[] = Transfer::STATUS_GIFT; } + + /** + * @var Model $product + * @var Transfer $query + */ + $query = $this->transfers(); + return $query + ->where('to_type', $product->getMorphClass()) + ->where('to_id', $product->getKey()) + ->whereIn('status', $status) + ->orderBy('id', 'desc') + ->first(); } /** @@ -166,9 +181,13 @@ public function forceRefund(Product $product, bool $gifts = false): bool * @param bool $force * @return bool */ - public function refundGift(Product $product, bool $force = false): bool + public function safeRefundGift(Product $product, bool $force = false): bool { - return $this->refund($product, $force, true); + try { + return $this->refundGift($product, $force); + } catch (\Throwable $throwable) { + return false; + } } /** @@ -176,13 +195,9 @@ public function refundGift(Product $product, bool $force = false): bool * @param bool $force * @return bool */ - public function safeRefundGift(Product $product, bool $force = false): bool + public function refundGift(Product $product, bool $force = false): bool { - try { - return $this->refundGift($product, $force); - } catch (\Throwable $throwable) { - return false; - } + return $this->refund($product, $force, true); } /** diff --git a/src/Traits/HasGift.php b/src/Traits/HasGift.php index dc067d3ed..1de55d8a2 100644 --- a/src/Traits/HasGift.php +++ b/src/Traits/HasGift.php @@ -17,6 +17,23 @@ trait HasGift { + /** + * Give the goods safely. + * + * @param Wallet $to + * @param Product $product + * @param bool $force + * @return Transfer|null + */ + public function safeGift(Wallet $to, Product $product, bool $force = false): ?Transfer + { + try { + return $this->gift($to, $product, $force); + } catch (\Throwable $throwable) { + return null; + } + } + /** * From this moment on, each user (wallet) can give * the goods to another user (wallet). @@ -52,7 +69,7 @@ public function gift(Wallet $to, Product $product, bool $force = false): Transfe } $deposit = $product->deposit($amount, $meta); - return $this->assemble($product, $withdraw, $deposit); + return $this->assemble($product, $withdraw, $deposit, Transfer::STATUS_GIFT); }; /** @@ -65,23 +82,6 @@ public function gift(Wallet $to, Product $product, bool $force = false): Transfe ); } - /** - * Give the goods safely. - * - * @param Wallet $to - * @param Product $product - * @param bool $force - * @return Transfer|null - */ - public function safeGift(Wallet $to, Product $product, bool $force = false): ?Transfer - { - try { - return $this->gift($to, $product, $force); - } catch (\Throwable $throwable) { - return null; - } - } - /** * to give force) * diff --git a/src/Traits/HasWallet.php b/src/Traits/HasWallet.php index 1e72b4275..60db10ee1 100644 --- a/src/Traits/HasWallet.php +++ b/src/Traits/HasWallet.php @@ -30,6 +30,21 @@ trait HasWallet { + /** + * The input means in the system + * + * @param int $amount + * @param array|null $meta + * @param bool $confirmed + * + * @return Transaction + */ + public function deposit(int $amount, ?array $meta = null, bool $confirmed = true): Transaction + { + $this->checkAmount($amount); + return $this->change(Transaction::TYPE_DEPOSIT, $amount, $meta, $confirmed); + } + /** * The amount of checks for errors * @@ -44,66 +59,125 @@ private function checkAmount(int $amount): void } /** - * Forced to withdraw funds from system + * this method adds a new transaction to the translation table * + * @param string $type * @param int $amount * @param array|null $meta * @param bool $confirmed - * * @return Transaction + * @throws */ - public function forceWithdraw(int $amount, ?array $meta = null, bool $confirmed = true): Transaction + protected function change(string $type, int $amount, ?array $meta, bool $confirmed): Transaction { - $this->checkAmount($amount); - return $this->change(Transaction::TYPE_WITHDRAW, -$amount, $meta, $confirmed); + return DB::transaction(function () use ($type, $amount, $meta, $confirmed) { + + $wallet = $this; + if (!($this instanceof WalletModel)) { + $wallet = $this->wallet; + } + + if ($confirmed) { + $this->addBalance($wallet, $amount); + } + + return $this->transactions()->create([ + 'type' => $type, + 'wallet_id' => $wallet->getKey(), + 'uuid' => Uuid::uuid4()->toString(), + 'confirmed' => $confirmed, + 'amount' => $amount, + 'meta' => $meta, + ]); + }); } /** - * The input means in the system + * This method automatically updates the balance in the + * database and the project statics * + * @param WalletModel $wallet * @param int $amount - * @param array|null $meta - * @param bool $confirmed - * - * @return Transaction + * @return bool */ - public function deposit(int $amount, ?array $meta = null, bool $confirmed = true): Transaction + protected function addBalance(WalletModel $wallet, int $amount): bool { - $this->checkAmount($amount); - return $this->change(Transaction::TYPE_DEPOSIT, $amount, $meta, $confirmed); + $newBalance = $this->getBalanceAttribute() + $amount; + $wallet->balance = $newBalance; + + return + // update database wallet + $wallet->save() && + + // update static wallet + WalletProxy::set($wallet->getKey(), $newBalance); } /** - * Withdrawals from the system + * Magic laravel framework method, makes it + * possible to call property balance * - * @param int $amount - * @param array|null $meta - * @param bool $confirmed + * Example: + * $user1 = User::first()->load('wallet'); + * $user2 = User::first()->load('wallet'); * - * @return Transaction + * Without static: + * var_dump($user1->balance, $user2->balance); // 100 100 + * $user1->deposit(100); + * $user2->deposit(100); + * var_dump($user1->balance, $user2->balance); // 200 200 + * + * With static: + * var_dump($user1->balance, $user2->balance); // 100 100 + * $user1->deposit(100); + * var_dump($user1->balance); // 200 + * $user2->deposit(100); + * var_dump($user2->balance); // 300 + * + * @return int + * @throws */ - public function withdraw(int $amount, ?array $meta = null, bool $confirmed = true): Transaction + public function getBalanceAttribute(): int { - if ($amount && !$this->balance) { - throw new BalanceIsEmpty(trans('wallet::errors.wallet_empty')); - } + if ($this instanceof WalletModel) { + $this->exists or $this->save(); + if (!WalletProxy::has($this->getKey())) { + WalletProxy::set($this->getKey(), (int)($this->attributes['balance'] ?? 0)); + } - if (!$this->canWithdraw($amount)) { - throw new InsufficientFunds(trans('wallet::errors.insufficient_funds')); + return WalletProxy::get($this->getKey()); } - return $this->forceWithdraw($amount, $meta, $confirmed); + return $this->wallet->balance; } /** - * Checks if you can withdraw funds + * all user actions on wallets will be in this method + * + * @return MorphMany + */ + public function transactions(): MorphMany + { + return ($this instanceof WalletModel ? $this->holder : $this) + ->morphMany(config('wallet.transaction.model'), 'payable'); + } + + /** + * This method ignores errors that occur when transferring funds * + * @param Wallet $wallet * @param int $amount - * @return bool + * @param array|null $meta + * @param string $status + * @return null|Transfer */ - public function canWithdraw(int $amount): bool + public function safeTransfer(Wallet $wallet, int $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): ?Transfer { - return $this->balance >= $amount; + try { + return $this->transfer($wallet, $amount, $meta, $status); + } catch (\Throwable $throwable) { + return null; + } } /** @@ -112,73 +186,80 @@ public function canWithdraw(int $amount): bool * @param Wallet $wallet * @param int $amount * @param array|null $meta + * @param string $status * @return Transfer * @throws */ - public function transfer(Wallet $wallet, int $amount, ?array $meta = null): Transfer + public function transfer(Wallet $wallet, int $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer { - return DB::transaction(function () use ($amount, $wallet, $meta) { + return DB::transaction(function () use ($amount, $wallet, $meta, $status) { $fee = Tax::fee($wallet, $amount); $withdraw = $this->withdraw($amount + $fee, $meta); $deposit = $wallet->deposit($amount, $meta); - return $this->assemble($wallet, $withdraw, $deposit); + return $this->assemble($wallet, $withdraw, $deposit, $status); }); } /** - * This method ignores errors that occur when transferring funds + * Withdrawals from the system * - * @param Wallet $wallet * @param int $amount * @param array|null $meta - * @return null|Transfer + * @param bool $confirmed + * + * @return Transaction */ - public function safeTransfer(Wallet $wallet, int $amount, ?array $meta = null): ?Transfer + public function withdraw(int $amount, ?array $meta = null, bool $confirmed = true): Transaction { - try { - return $this->transfer($wallet, $amount, $meta); - } catch (\Throwable $throwable) { - return null; + if ($amount && !$this->balance) { + throw new BalanceIsEmpty(trans('wallet::errors.wallet_empty')); } + + if (!$this->canWithdraw($amount)) { + throw new InsufficientFunds(trans('wallet::errors.insufficient_funds')); + } + + return $this->forceWithdraw($amount, $meta, $confirmed); } /** - * the forced transfer is needed when the user does not have the money and we drive it. - * Sometimes you do. Depends on business logic. + * Checks if you can withdraw funds + * + * @param int $amount + * @return bool + */ + public function canWithdraw(int $amount): bool + { + return $this->balance >= $amount; + } + + /** + * Forced to withdraw funds from system * - * @param Wallet $wallet * @param int $amount * @param array|null $meta - * @return Transfer + * @param bool $confirmed + * + * @return Transaction */ - public function forceTransfer(Wallet $wallet, int $amount, ?array $meta = null): Transfer + public function forceWithdraw(int $amount, ?array $meta = null, bool $confirmed = true): Transaction { - return DB::transaction(function () use ($amount, $wallet, $meta) { - $fee = Tax::fee($wallet, $amount); - $withdraw = $this->forceWithdraw($amount + $fee, $meta); - $deposit = $wallet->deposit($amount, $meta); - return $this->assemble($wallet, $withdraw, $deposit); - }); + $this->checkAmount($amount); + return $this->change(Transaction::TYPE_WITHDRAW, -$amount, $meta, $confirmed); } /** * this method adds a new transfer to the transfer table * - * @param string $status * @param Wallet $wallet * @param Transaction $withdraw * @param Transaction $deposit + * @param string $status * @return Transfer * @throws */ - protected function assemble(Wallet $wallet, Transaction $withdraw, Transaction $deposit): Transfer + protected function assemble(Wallet $wallet, Transaction $withdraw, Transaction $deposit, string $status = Transfer::STATUS_PAID): Transfer { - $status = Transfer::STATUS_PAID; - if ($this->getMorphClass() !== $withdraw->payable_type || - $this->getKey() !== $withdraw->payable_id) { - $status = Transfer::STATUS_GIFT; - } - /** * @var Model $wallet */ @@ -196,50 +277,25 @@ protected function assemble(Wallet $wallet, Transaction $withdraw, Transaction $ } /** - * this method adds a new transaction to the translation table + * the forced transfer is needed when the user does not have the money and we drive it. + * Sometimes you do. Depends on business logic. * - * @param string $type + * @param Wallet $wallet * @param int $amount * @param array|null $meta - * @param bool $confirmed - * @return Transaction - * @throws + * @param string $status + * @return Transfer */ - protected function change(string $type, int $amount, ?array $meta, bool $confirmed): Transaction + public function forceTransfer(Wallet $wallet, int $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer { - return DB::transaction(function () use ($type, $amount, $meta, $confirmed) { - - $wallet = $this; - if (!($this instanceof WalletModel)) { - $wallet = $this->wallet; - } - - if ($confirmed) { - $this->addBalance($wallet, $amount); - } - - return $this->transactions()->create([ - 'type' => $type, - 'wallet_id' => $wallet->getKey(), - 'uuid' => Uuid::uuid4()->toString(), - 'confirmed' => $confirmed, - 'amount' => $amount, - 'meta' => $meta, - ]); + return DB::transaction(function () use ($amount, $wallet, $meta, $status) { + $fee = Tax::fee($wallet, $amount); + $withdraw = $this->forceWithdraw($amount + $fee, $meta); + $deposit = $wallet->deposit($amount, $meta); + return $this->assemble($wallet, $withdraw, $deposit, $status); }); } - /** - * all user actions on wallets will be in this method - * - * @return MorphMany - */ - public function transactions(): MorphMany - { - return ($this instanceof WalletModel ? $this->holder : $this) - ->morphMany(config('wallet.transaction.model'), 'payable'); - } - /** * the transfer table is used to confirm the payment * this method receives all transfers @@ -269,63 +325,4 @@ public function wallet(): MorphOne ]); } - /** - * Magic laravel framework method, makes it - * possible to call property balance - * - * Example: - * $user1 = User::first()->load('wallet'); - * $user2 = User::first()->load('wallet'); - * - * Without static: - * var_dump($user1->balance, $user2->balance); // 100 100 - * $user1->deposit(100); - * $user2->deposit(100); - * var_dump($user1->balance, $user2->balance); // 200 200 - * - * With static: - * var_dump($user1->balance, $user2->balance); // 100 100 - * $user1->deposit(100); - * var_dump($user1->balance); // 200 - * $user2->deposit(100); - * var_dump($user2->balance); // 300 - * - * @return int - * @throws - */ - public function getBalanceAttribute(): int - { - if ($this instanceof WalletModel) { - $this->exists or $this->save(); - if (!WalletProxy::has($this->getKey())) { - WalletProxy::set($this->getKey(), (int)($this->attributes['balance'] ?? 0)); - } - - return WalletProxy::get($this->getKey()); - } - - return $this->wallet->balance; - } - - /** - * This method automatically updates the balance in the - * database and the project statics - * - * @param WalletModel $wallet - * @param int $amount - * @return bool - */ - protected function addBalance(WalletModel $wallet, int $amount): bool - { - $newBalance = $this->getBalanceAttribute() + $amount; - $wallet->balance = $newBalance; - - return - // update database wallet - $wallet->save() && - - // update static wallet - WalletProxy::set($wallet->getKey(), $newBalance); - } - } diff --git a/src/Traits/HasWalletFloat.php b/src/Traits/HasWalletFloat.php index 33cbe16e7..b52b9b981 100644 --- a/src/Traits/HasWalletFloat.php +++ b/src/Traits/HasWalletFloat.php @@ -29,6 +29,14 @@ public function forceWithdrawFloat(float $amount, ?array $meta = null, bool $con return $this->forceWithdraw($amount * $this->coefficient(), $meta, $confirmed); } + /** + * @return float + */ + private function coefficient(): float + { + return config('wallet.package.coefficient', 100.); + } + /** * @param float $amount * @param array|null $meta @@ -66,34 +74,37 @@ public function canWithdrawFloat(float $amount): bool * @param Wallet $wallet * @param float $amount * @param array|null $meta + * @param string $status * @return Transfer * @throws */ - public function transferFloat(Wallet $wallet, float $amount, ?array $meta = null): Transfer + public function transferFloat(Wallet $wallet, float $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer { - return $this->transfer($wallet, $amount * $this->coefficient(), $meta); + return $this->transfer($wallet, $amount * $this->coefficient(), $meta, $status); } /** * @param Wallet $wallet * @param float $amount * @param array|null $meta + * @param string $status * @return null|Transfer */ - public function safeTransferFloat(Wallet $wallet, float $amount, ?array $meta = null): ?Transfer + public function safeTransferFloat(Wallet $wallet, float $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): ?Transfer { - return $this->safeTransfer($wallet, $amount * $this->coefficient(), $meta); + return $this->safeTransfer($wallet, $amount * $this->coefficient(), $meta, $status); } /** * @param Wallet $wallet * @param float $amount * @param array|null $meta + * @param string $status * @return Transfer */ - public function forceTransferFloat(Wallet $wallet, float $amount, ?array $meta = null): Transfer + public function forceTransferFloat(Wallet $wallet, float $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer { - return $this->forceTransfer($wallet, $amount * $this->coefficient(), $meta); + return $this->forceTransfer($wallet, $amount * $this->coefficient(), $meta, $status); } /** @@ -104,12 +115,4 @@ public function getBalanceFloatAttribute(): float return $this->balance / $this->coefficient(); } - /** - * @return float - */ - private function coefficient(): float - { - return config('wallet.package.coefficient', 100.); - } - } diff --git a/src/Traits/HasWallets.php b/src/Traits/HasWallets.php index 74dea655e..013228036 100644 --- a/src/Traits/HasWallets.php +++ b/src/Traits/HasWallets.php @@ -26,16 +26,6 @@ trait HasWallets */ private $_wallets = []; - /** - * method of obtaining all wallets - * - * @return MorphMany - */ - public function wallets(): MorphMany - { - return $this->morphMany(config('wallet.wallet.model'), 'holder'); - } - /** * Get wallet by slug * @@ -62,6 +52,16 @@ public function getWallet(string $slug): ?WalletModel return $this->_wallets[$slug]; } + /** + * method of obtaining all wallets + * + * @return MorphMany + */ + public function wallets(): MorphMany + { + return $this->morphMany(config('wallet.wallet.model'), 'holder'); + } + /** * @param array $data * @return WalletModel diff --git a/tests/GiftTest.php b/tests/GiftTest.php index 159a91189..11306f2c5 100644 --- a/tests/GiftTest.php +++ b/tests/GiftTest.php @@ -2,6 +2,7 @@ namespace Bavix\Wallet\Test; +use Bavix\Wallet\Models\Transfer; use Bavix\Wallet\Test\Models\Buyer; use Bavix\Wallet\Test\Models\Item; @@ -29,11 +30,12 @@ public function testGift(): void $first->deposit($product->getAmountProduct()); $this->assertEquals($first->balance, $product->getAmountProduct()); - $first->wallet->gift($second, $product); + $transfer = $first->wallet->gift($second, $product); $this->assertEquals($first->balance, 0); $this->assertEquals($second->balance, 0); $this->assertNull($first->paid($product, true)); $this->assertNotNull($second->paid($product, true)); + $this->assertEquals($transfer->status, Transfer::STATUS_GIFT); } /** @@ -57,9 +59,10 @@ public function testRefund(): void $first->deposit($product->getAmountProduct()); $this->assertEquals($first->balance, $product->getAmountProduct()); - $first->wallet->gift($second, $product); + $transfer = $first->wallet->gift($second, $product); $this->assertEquals($first->balance, 0); $this->assertEquals($second->balance, 0); + $this->assertEquals($transfer->status, Transfer::STATUS_GIFT); $this->assertFalse($second->wallet->safeRefund($product)); $this->assertTrue($second->wallet->refundGift($product)); @@ -68,7 +71,10 @@ public function testRefund(): void $this->assertEquals($second->balance, 0); $this->assertNull($second->wallet->safeGift($first, $product)); - $this->assertNotNull($second->wallet->forceGift($first, $product)); + + $transfer = $second->wallet->forceGift($first, $product); + $this->assertNotNull($transfer); + $this->assertEquals($transfer->status, Transfer::STATUS_GIFT); $this->assertEquals($second->balance, -$product->getAmountProduct()); diff --git a/tests/Models/User.php b/tests/Models/User.php index 037b4bf7b..ae9801d5c 100644 --- a/tests/Models/User.php +++ b/tests/Models/User.php @@ -2,8 +2,8 @@ namespace Bavix\Wallet\Test\Models; -use Bavix\Wallet\Traits\HasWallet; use Bavix\Wallet\Interfaces\Wallet; +use Bavix\Wallet\Traits\HasWallet; use Illuminate\Database\Eloquent\Model; /** diff --git a/tests/TaxTest.php b/tests/TaxTest.php index ae1149213..93cf2eb2b 100644 --- a/tests/TaxTest.php +++ b/tests/TaxTest.php @@ -23,7 +23,7 @@ public function testPay(): void 'quantity' => 1, ]); - $fee = (int) ($product->price * $product->getFeePercent() / 100); + $fee = (int)($product->price * $product->getFeePercent() / 100); $balance = $product->price + $fee; $this->assertEquals($buyer->balance, 0); diff --git a/tests/TestCase.php b/tests/TestCase.php index cac12a16f..0819793cd 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -44,7 +44,7 @@ protected function getPackageProviders($app): array /** * Define environment setup. * - * @param Application $app + * @param Application $app * @return void */ protected function getEnvironmentSetUp($app): void diff --git a/tests/factories/BuyerFactory.php b/tests/factories/BuyerFactory.php index 3a44dc68e..45069dfa2 100644 --- a/tests/factories/BuyerFactory.php +++ b/tests/factories/BuyerFactory.php @@ -1,7 +1,7 @@ define(Buyer::class, function(Faker $faker) { +$factory->define(Buyer::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, diff --git a/tests/factories/ItemFactory.php b/tests/factories/ItemFactory.php index b66654533..a49060303 100644 --- a/tests/factories/ItemFactory.php +++ b/tests/factories/ItemFactory.php @@ -1,7 +1,7 @@ define(Item::class, function(Faker $faker) { +$factory->define(Item::class, function (Faker $faker) { return [ 'name' => $faker->domainName, 'price' => \random_int(1, 100), diff --git a/tests/factories/ItemTaxFactory.php b/tests/factories/ItemTaxFactory.php index 93daf34df..2d2f0cfb2 100644 --- a/tests/factories/ItemTaxFactory.php +++ b/tests/factories/ItemTaxFactory.php @@ -1,7 +1,7 @@ define(ItemTax::class, function(Faker $faker) { +$factory->define(ItemTax::class, function (Faker $faker) { return [ 'name' => $faker->domainName, 'price' => \random_int(1, 100), diff --git a/tests/factories/UserFactory.php b/tests/factories/UserFactory.php index 44d0e56d7..f6e46884c 100644 --- a/tests/factories/UserFactory.php +++ b/tests/factories/UserFactory.php @@ -1,7 +1,7 @@ define(User::class, function(Faker $faker) { +$factory->define(User::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, diff --git a/tests/factories/UserFloatFactory.php b/tests/factories/UserFloatFactory.php index e9fb2dfcf..a07c76c05 100644 --- a/tests/factories/UserFloatFactory.php +++ b/tests/factories/UserFloatFactory.php @@ -1,7 +1,7 @@ define(UserFloat::class, function(Faker $faker) { +$factory->define(UserFloat::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, diff --git a/tests/factories/UserMultiFactory.php b/tests/factories/UserMultiFactory.php index d3c71272e..756f1136c 100644 --- a/tests/factories/UserMultiFactory.php +++ b/tests/factories/UserMultiFactory.php @@ -1,7 +1,7 @@ define(UserMulti::class, function(Faker $faker) { +$factory->define(UserMulti::class, function (Faker $faker) { return [ 'name' => $faker->name, 'email' => $faker->unique()->safeEmail, diff --git a/tests/migrations/2014_10_12_000000_create_users_table.php b/tests/migrations/2014_10_12_000000_create_users_table.php index 2fcc77538..b666083f6 100644 --- a/tests/migrations/2014_10_12_000000_create_users_table.php +++ b/tests/migrations/2014_10_12_000000_create_users_table.php @@ -1,8 +1,8 @@ increments('id'); $table->string('name'); $table->string('email')->unique(); diff --git a/tests/migrations/2018_11_08_214421_create_items_table.php b/tests/migrations/2018_11_08_214421_create_items_table.php index d10c22e30..8ec050a7d 100644 --- a/tests/migrations/2018_11_08_214421_create_items_table.php +++ b/tests/migrations/2018_11_08_214421_create_items_table.php @@ -1,8 +1,8 @@ increments('id'); $table->string('name'); $table->integer('price'); From f6cfb50d242acaaf1d4877c553cfa6e8e0931124 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Mon, 13 May 2019 12:05:37 +0300 Subject: [PATCH 6/7] add test cases --- tests/MultiWalletTest.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/tests/MultiWalletTest.php b/tests/MultiWalletTest.php index 545a3db83..d9ad16d96 100644 --- a/tests/MultiWalletTest.php +++ b/tests/MultiWalletTest.php @@ -2,6 +2,7 @@ namespace Bavix\Wallet\Test; +use Bavix\Wallet\Models\Transfer; use Bavix\Wallet\Test\Models\UserMulti; class MultiWalletTest extends TestCase @@ -136,19 +137,22 @@ public function testTransfer(): void $secondWallet->deposit(100); $this->assertEquals($secondWallet->balance, 100); - $firstWallet->transfer($secondWallet, 100); + $transfer = $firstWallet->transfer($secondWallet, 100); $this->assertEquals($first->balance, 0); $this->assertEquals($firstWallet->balance, 0); $this->assertEquals($second->balance, 0); $this->assertEquals($secondWallet->balance, 200); + $this->assertEquals($transfer->status, Transfer::STATUS_TRANSFER); - $secondWallet->transfer($firstWallet, 100); + $transfer = $secondWallet->transfer($firstWallet, 100); $this->assertEquals($secondWallet->balance, 100); $this->assertEquals($firstWallet->balance, 100); + $this->assertEquals($transfer->status, Transfer::STATUS_TRANSFER); - $secondWallet->transfer($firstWallet, 100); + $transfer = $secondWallet->transfer($firstWallet, 100); $this->assertEquals($secondWallet->balance, 0); $this->assertEquals($firstWallet->balance, 200); + $this->assertEquals($transfer->status, Transfer::STATUS_TRANSFER); $firstWallet->withdraw($firstWallet->balance); $this->assertEquals($firstWallet->balance, 0); @@ -157,13 +161,17 @@ public function testTransfer(): void $this->assertEquals($firstWallet->balance, 0); $this->assertEquals($secondWallet->balance, 0); - $this->assertNotNull($firstWallet->forceTransfer($secondWallet, 100)); + $transfer = $firstWallet->forceTransfer($secondWallet, 100); + $this->assertNotNull($transfer); $this->assertEquals($firstWallet->balance, -100); $this->assertEquals($secondWallet->balance, 100); + $this->assertEquals($transfer->status, Transfer::STATUS_TRANSFER); - $this->assertNotNull($secondWallet->forceTransfer($firstWallet, 100)); + $transfer = $secondWallet->forceTransfer($firstWallet, 100); + $this->assertNotNull($transfer); $this->assertEquals($firstWallet->balance, 0); $this->assertEquals($secondWallet->balance, 0); + $this->assertEquals($transfer->status, Transfer::STATUS_TRANSFER); } /** From bc882b724904e6775460cb202176305461a6cf91 Mon Sep 17 00:00:00 2001 From: Babichev Maxim Date: Mon, 13 May 2019 12:23:47 +0300 Subject: [PATCH 7/7] update changelog --- changelog.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 5cdfad16e..82f2cb863 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [2.3.0] - 2019-05-13 ### Added - Add support Themosis Framework @@ -210,7 +212,8 @@ The operation is now executed in the transaction and updates the new `refund` fi - Exceptions: AmountInvalid, BalanceIsEmpty. - Models: Transfer, Transaction. -[Unreleased]: https://github.com/bavix/laravel-wallet/compare/2.2.2...HEAD +[Unreleased]: https://github.com/bavix/laravel-wallet/compare/2.3.0...HEAD +[2.3.0]: https://github.com/bavix/laravel-wallet/compare/2.2.2...2.3.0 [2.2.2]: https://github.com/bavix/laravel-wallet/compare/2.2.1...2.2.2 [2.2.1]: https://github.com/bavix/laravel-wallet/compare/2.2.0...2.2.1 [2.2.0]: https://github.com/bavix/laravel-wallet/compare/2.1.0...2.2.0