Skip to content

Commit 7480cab

Browse files
author
Babichev Maxim
committed
fix bug's
1 parent a3e8014 commit 7480cab

File tree

5 files changed

+308
-6
lines changed

5 files changed

+308
-6
lines changed

src/Services/CommonService.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ class CommonService
3030
public function transfer(Wallet $from, Wallet $to, int $amount, ?array $meta = null, string $status = Transfer::STATUS_TRANSFER): Transfer
3131
{
3232
return app(LockService::class)->lock($this, __FUNCTION__, function () use ($from, $to, $amount, $meta, $status) {
33-
$this->verifyWithdraw($from, $amount);
33+
$discount = app(WalletService::class)->discount($from, $to);
34+
$newAmount = max(0, $amount - $discount);
35+
$fee = app(WalletService::class)->fee($to, $newAmount);
36+
$this->verifyWithdraw($from, $newAmount + $fee);
3437
return $this->forceTransfer($from, $to, $amount, $meta, $status);
3538
});
3639
}
@@ -146,7 +149,8 @@ public function verifyWithdraw(Wallet $wallet, int $amount, bool $allowZero = nu
146149
}
147150

148151
if (!$wallet->canWithdraw($amount, $allowZero)) {
149-
throw new InsufficientFunds(trans('wallet::errors.insufficient_funds'));
152+
// throw new InsufficientFunds(trans('wallet::errors.insufficient_funds'));
153+
throw new InsufficientFunds("{$wallet->balance}, $amount");
150154
}
151155
}
152156

src/Services/WalletService.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use Bavix\Wallet\Interfaces\Customer;
77
use Bavix\Wallet\Interfaces\Discount;
88
use Bavix\Wallet\Interfaces\MinimalTaxable;
9-
use Bavix\Wallet\Interfaces\Product;
109
use Bavix\Wallet\Interfaces\Storable;
1110
use Bavix\Wallet\Interfaces\Taxable;
1211
use Bavix\Wallet\Interfaces\Wallet;

tests/DiscountTaxTest.php

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
<?php
2+
3+
namespace Bavix\Wallet\Test;
4+
5+
use Bavix\Wallet\Exceptions\ProductEnded;
6+
use Bavix\Wallet\Models\Transaction;
7+
use Bavix\Wallet\Models\Transfer;
8+
use Bavix\Wallet\Models\Wallet;
9+
use Bavix\Wallet\Services\WalletService;
10+
use Bavix\Wallet\Test\Models\Buyer;
11+
use Bavix\Wallet\Test\Models\Item;
12+
use Bavix\Wallet\Test\Models\ItemDiscountTax;
13+
14+
class DiscountTaxTest extends TestCase
15+
{
16+
17+
/**
18+
* @return void
19+
*/
20+
public function testPay(): void
21+
{
22+
/**
23+
* @var Buyer $buyer
24+
* @var ItemDiscountTax $product
25+
*/
26+
$buyer = factory(Buyer::class)->create();
27+
$product = factory(ItemDiscountTax::class)->create();
28+
29+
$this->assertEquals($buyer->balance, 0);
30+
$fee = app(WalletService::class)->fee($product, $product->getAmountProduct($buyer));
31+
$buyer->deposit($product->getAmountProduct($buyer) + $fee);
32+
33+
$this->assertEquals($buyer->balance, $product->getAmountProduct($buyer) + $fee);
34+
$transfer = $buyer->pay($product);
35+
$this->assertNotNull($transfer);
36+
$this->assertEquals($transfer->status, Transfer::STATUS_PAID);
37+
38+
$this->assertEquals(
39+
$buyer->balance,
40+
$product->getPersonalDiscount($buyer)
41+
);
42+
43+
/**
44+
* @var Transaction $withdraw
45+
* @var Transaction $deposit
46+
*/
47+
$withdraw = $transfer->withdraw;
48+
$deposit = $transfer->deposit;
49+
50+
$this->assertInstanceOf(Transaction::class, $withdraw);
51+
$this->assertInstanceOf(Transaction::class, $deposit);
52+
53+
$this->assertInstanceOf(Buyer::class, $withdraw->payable);
54+
$this->assertInstanceOf(Item::class, $deposit->payable);
55+
56+
$this->assertEquals($buyer->getKey(), $withdraw->payable->getKey());
57+
$this->assertEquals($product->getKey(), $deposit->payable->getKey());
58+
59+
$this->assertInstanceOf(Buyer::class, $transfer->from->holder);
60+
$this->assertInstanceOf(Wallet::class, $transfer->from);
61+
$this->assertInstanceOf(Item::class, $transfer->to);
62+
$this->assertInstanceOf(Wallet::class, $transfer->to->wallet);
63+
64+
$this->assertEquals($buyer->wallet->getKey(), $transfer->from->getKey());
65+
$this->assertEquals($buyer->getKey(), $transfer->from->holder->getKey());
66+
$this->assertEquals($product->getKey(), $transfer->to->getKey());
67+
}
68+
69+
/**
70+
* @return void
71+
*/
72+
public function testRefund(): void
73+
{
74+
/**
75+
* @var Buyer $buyer
76+
* @var ItemDiscountTax $product
77+
*/
78+
$buyer = factory(Buyer::class)->create();
79+
$product = factory(ItemDiscountTax::class)->create();
80+
81+
$this->assertEquals($buyer->balance, 0);
82+
$discount = app(WalletService::class)->discount($buyer, $product);
83+
$fee = app(WalletService::class)->fee($product, ($product->getAmountProduct($buyer) - $discount));
84+
$buyer->deposit(($product->getAmountProduct($buyer) - $discount) + $fee);
85+
86+
$this->assertEquals($buyer->balance, ($product->getAmountProduct($buyer) - $discount) + $fee);
87+
$transfer = $buyer->pay($product);
88+
$this->assertNotNull($transfer);
89+
$this->assertEquals($transfer->status, Transfer::STATUS_PAID);
90+
91+
$this->assertTrue($buyer->refund($product));
92+
$this->assertEquals(
93+
$buyer->balance,
94+
$product->getAmountProduct($buyer) - $product->getPersonalDiscount($buyer)
95+
);
96+
97+
$this->assertEquals($product->balance, 0);
98+
99+
$transfer->refresh();
100+
$this->assertEquals($transfer->status, Transfer::STATUS_REFUND);
101+
102+
$this->assertFalse($buyer->safeRefund($product));
103+
$this->assertEquals(
104+
$buyer->balance,
105+
$product->getAmountProduct($buyer) - $product->getPersonalDiscount($buyer)
106+
);
107+
108+
$this->assertNull($buyer->safePay($product));
109+
$buyer->deposit($fee);
110+
$transfer = $buyer->pay($product);
111+
$this->assertNotNull($transfer);
112+
$this->assertEquals(0, $buyer->balance);
113+
$this->assertEquals(
114+
$product->balance,
115+
$product->getAmountProduct($buyer) - $product->getPersonalDiscount($buyer)
116+
);
117+
118+
$this->assertEquals($transfer->status, Transfer::STATUS_PAID);
119+
120+
$this->assertTrue($buyer->refund($product));
121+
$this->assertEquals(
122+
$buyer->balance,
123+
$product->getAmountProduct($buyer) - $product->getPersonalDiscount($buyer)
124+
);
125+
126+
$this->assertEquals($product->balance, 0);
127+
128+
$transfer->refresh();
129+
$this->assertEquals($transfer->status, Transfer::STATUS_REFUND);
130+
}
131+
132+
/**
133+
* @return void
134+
*/
135+
public function testForceRefund(): void
136+
{
137+
/**
138+
* @var Buyer $buyer
139+
* @var ItemDiscountTax $product
140+
*/
141+
$buyer = factory(Buyer::class)->create();
142+
$product = factory(ItemDiscountTax::class)->create();
143+
144+
$this->assertEquals($buyer->balance, 0);
145+
$discount = app(WalletService::class)->discount($buyer, $product);
146+
$fee = app(WalletService::class)->fee($product, ($product->getAmountProduct($buyer) - $discount));
147+
$buyer->deposit($product->getAmountProduct($buyer) + $fee);
148+
149+
$this->assertEquals($buyer->balance, $product->getAmountProduct($buyer) + $fee);
150+
151+
$buyer->pay($product);
152+
$this->assertEquals($buyer->balance, $product->getPersonalDiscount($buyer));
153+
154+
$this->assertEquals(
155+
$product->balance,
156+
$product->getAmountProduct($buyer) - $product->getPersonalDiscount($buyer)
157+
);
158+
159+
$product->withdraw($product->balance);
160+
$this->assertEquals($product->balance, 0);
161+
162+
$this->assertFalse($buyer->safeRefund($product));
163+
$this->assertTrue($buyer->forceRefund($product));
164+
165+
$this->assertEquals(
166+
$product->balance, -($product->getAmountProduct($buyer) - $product->getPersonalDiscount($buyer))
167+
);
168+
169+
$this->assertEquals($buyer->balance, $product->getAmountProduct($buyer));
170+
$product->deposit(-$product->balance);
171+
$buyer->withdraw($buyer->balance);
172+
173+
$this->assertEquals($product->balance, 0);
174+
$this->assertEquals($buyer->balance, 0);
175+
}
176+
177+
/**
178+
* @return void
179+
*/
180+
public function testOutOfStock(): void
181+
{
182+
$this->expectException(ProductEnded::class);
183+
184+
/**
185+
* @var Buyer $buyer
186+
* @var ItemDiscountTax $product
187+
*/
188+
$buyer = factory(Buyer::class)->create();
189+
$product = factory(ItemDiscountTax::class)->create([
190+
'quantity' => 1,
191+
]);
192+
193+
$fee = app(WalletService::class)->fee($product, $product->getAmountProduct($buyer));
194+
$buyer->deposit($product->getAmountProduct($buyer) + $fee);
195+
$buyer->pay($product);
196+
$buyer->pay($product);
197+
}
198+
199+
/**
200+
* @return void
201+
*/
202+
public function testForcePay(): void
203+
{
204+
/**
205+
* @var Buyer $buyer
206+
* @var ItemDiscountTax $product
207+
*/
208+
$buyer = factory(Buyer::class)->create();
209+
$product = factory(ItemDiscountTax::class)->create([
210+
'quantity' => 1,
211+
]);
212+
213+
$this->assertEquals($buyer->balance, 0);
214+
$buyer->forcePay($product);
215+
216+
$fee = app(WalletService::class)->fee($product, $product->getAmountProduct($buyer));
217+
$this->assertEquals(
218+
$buyer->balance,
219+
-($product->getAmountProduct($buyer) - $product->getPersonalDiscount($buyer)) - $fee
220+
);
221+
222+
$buyer->deposit(-$buyer->balance);
223+
$this->assertEquals($buyer->balance, 0);
224+
}
225+
226+
/**
227+
* @return void
228+
*/
229+
public function testPayFree(): void
230+
{
231+
/**
232+
* @var Buyer $buyer
233+
* @var ItemDiscountTax $product
234+
*/
235+
$buyer = factory(Buyer::class)->create();
236+
$product = factory(ItemDiscountTax::class)->create([
237+
'quantity' => 1,
238+
]);
239+
240+
$this->assertEquals($buyer->balance, 0);
241+
242+
$transfer = $buyer->payFree($product);
243+
$this->assertEquals($transfer->deposit->type, Transaction::TYPE_DEPOSIT);
244+
$this->assertEquals($transfer->withdraw->type, Transaction::TYPE_WITHDRAW);
245+
246+
$this->assertEquals($buyer->balance, 0);
247+
$this->assertEquals($product->balance, 0);
248+
249+
$buyer->refund($product);
250+
$this->assertEquals($buyer->balance, 0);
251+
$this->assertEquals($product->balance, 0);
252+
}
253+
254+
public function testFreePay(): void
255+
{
256+
/**
257+
* @var Buyer $buyer
258+
* @var ItemDiscountTax $product
259+
*/
260+
$buyer = factory(Buyer::class)->create();
261+
$product = factory(ItemDiscountTax::class)->create([
262+
'quantity' => 1,
263+
]);
264+
265+
$buyer->forceWithdraw(1000);
266+
$this->assertEquals($buyer->balance, -1000);
267+
268+
$transfer = $buyer->payFree($product);
269+
$this->assertEquals($transfer->deposit->type, Transaction::TYPE_DEPOSIT);
270+
$this->assertEquals($transfer->withdraw->type, Transaction::TYPE_WITHDRAW);
271+
272+
$this->assertEquals($buyer->balance, -1000);
273+
$this->assertEquals($product->balance, 0);
274+
275+
$buyer->refund($product);
276+
$this->assertEquals($buyer->balance, -1000);
277+
$this->assertEquals($product->balance, 0);
278+
}
279+
280+
/**
281+
* @return void
282+
*/
283+
public function testPayFreeOutOfStock(): void
284+
{
285+
$this->expectException(ProductEnded::class);
286+
287+
/**
288+
* @var Buyer $buyer
289+
* @var ItemDiscountTax $product
290+
*/
291+
$buyer = factory(Buyer::class)->create();
292+
$product = factory(ItemDiscountTax::class)->create([
293+
'quantity' => 1,
294+
]);
295+
296+
$this->assertNotNull($buyer->payFree($product));
297+
$buyer->payFree($product);
298+
}
299+
300+
}

tests/Models/ItemDiscount.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use Bavix\Wallet\Interfaces\Customer;
66
use Bavix\Wallet\Interfaces\Discount;
77
use Bavix\Wallet\Services\WalletService;
8-
use Bavix\Wallet\Test\Common\Models\Wallet;
98

109
class ItemDiscount extends Item implements Discount
1110
{

tests/factories/ItemDiscountTaxFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
$factory->define(ItemDiscountTax::class, function (Faker $faker) {
1818
return [
1919
'name' => $faker->domainName,
20-
'price' => random_int(200, 700),
21-
'quantity' => random_int(10, 100),
20+
'price' => 250,
21+
'quantity' => 90,
2222
];
2323
});

0 commit comments

Comments
 (0)