Skip to content

Commit 9edf842

Browse files
authored
Merge pull request #13 from bavix/dev
add force method's
2 parents 2a11a16 + e385973 commit 9edf842

File tree

7 files changed

+231
-19
lines changed

7 files changed

+231
-19
lines changed

src/Interfaces/Customer.php

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,26 @@ interface Customer extends Wallet
99

1010
/**
1111
* @param Product $product
12+
* @param bool $force
1213
* @return Transfer
1314
* @throws
1415
*/
15-
public function pay(Product $product): Transfer;
16+
public function pay(Product $product, bool $force = false): Transfer;
1617

1718
/**
1819
* @param Product $product
20+
* @param bool $force
1921
* @return null|Transfer
2022
* @throws
2123
*/
22-
public function safePay(Product $product): ?Transfer;
24+
public function safePay(Product $product, bool $force = false): ?Transfer;
25+
26+
/**
27+
* @param Product $product
28+
* @return Transfer
29+
* @throws
30+
*/
31+
public function forcePay(Product $product): Transfer;
2332

2433
/**
2534
* @param Product $product
@@ -29,15 +38,23 @@ public function paid(Product $product): ?Transfer;
2938

3039
/**
3140
* @param Product $product
41+
* @param bool $force
3242
* @return bool
3343
* @throws
3444
*/
35-
public function refund(Product $product): bool;
45+
public function refund(Product $product, bool $force = false): bool;
46+
47+
/**
48+
* @param Product $product
49+
* @param bool $force
50+
* @return bool
51+
*/
52+
public function safeRefund(Product $product, bool $force = false): bool;
3653

3754
/**
3855
* @param Product $product
3956
* @return bool
4057
*/
41-
public function safeRefund(Product $product): bool;
58+
public function forceRefund(Product $product): bool;
4259

4360
}

src/Interfaces/Product.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ interface Product extends Wallet
77

88
/**
99
* @param Customer $customer
10+
* @param bool $force
1011
*
1112
* @return bool
1213
*/
13-
public function canBuy(Customer $customer): bool;
14+
public function canBuy(Customer $customer, bool $force = false): bool;
1415

1516
/**
1617
* @return int

src/Traits/CanBePaid.php

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,47 @@ trait CanBePaid
1616

1717
/**
1818
* @param Product $product
19+
* @param bool $force
1920
* @return Transfer
2021
* @throws
2122
*/
22-
public function pay(Product $product): Transfer
23+
public function pay(Product $product, bool $force = false): Transfer
2324
{
24-
if (!$product->canBuy($this)) {
25+
if (!$product->canBuy($this, $force)) {
2526
throw new ProductEnded('The product is out of stock');
2627
}
2728

29+
if ($force) {
30+
return $this->forceTransfer($product, $product->getAmountProduct(), $product->getMetaProduct());
31+
}
32+
2833
return $this->transfer($product, $product->getAmountProduct(), $product->getMetaProduct());
2934
}
3035

3136
/**
3237
* @param Product $product
38+
* @param bool $force
3339
* @return Transfer|null
3440
*/
35-
public function safePay(Product $product): ?Transfer
41+
public function safePay(Product $product, bool $force = false): ?Transfer
3642
{
3743
try {
38-
return $this->pay($product);
44+
return $this->pay($product, $force);
3945
} catch (\Throwable $throwable) {
4046
return null;
4147
}
4248
}
4349

50+
/**
51+
* @param Product $product
52+
* @return Transfer
53+
* @throws
54+
*/
55+
public function forcePay(Product $product): Transfer
56+
{
57+
return $this->pay($product, true);
58+
}
59+
4460
/**
4561
* @param Product $product
4662
* @return null|Transfer
@@ -60,10 +76,11 @@ public function paid(Product $product): ?Transfer
6076

6177
/**
6278
* @param Product $product
79+
* @param bool $force
6380
* @return bool
6481
* @throws
6582
*/
66-
public function refund(Product $product): bool
83+
public function refund(Product $product, bool $force = false): bool
6784
{
6885
$transfer = $this->paid($product);
6986

@@ -72,23 +89,39 @@ public function refund(Product $product): bool
7289
->setModel($this->transfers()->getMorphClass());
7390
}
7491

75-
return DB::transaction(function() use ($product, $transfer) {
76-
$product->transfer($this, $product->getAmountProduct(), $product->getMetaProduct());
92+
return DB::transaction(function() use ($product, $transfer, $force) {
93+
if ($force) {
94+
$product->forceTransfer($this, $product->getAmountProduct(), $product->getMetaProduct());
95+
} else {
96+
$product->transfer($this, $product->getAmountProduct(), $product->getMetaProduct());
97+
}
98+
7799
return $transfer->update(['refund' => 1]);
78100
});
79101
}
80102

81103
/**
82104
* @param Product $product
105+
* @param bool $force
83106
* @return bool
84107
*/
85-
public function safeRefund(Product $product): bool
108+
public function safeRefund(Product $product, bool $force = false): bool
86109
{
87110
try {
88-
return $this->refund($product);
111+
return $this->refund($product, $force);
89112
} catch (\Throwable $throwable) {
90113
return false;
91114
}
92115
}
93116

117+
/**
118+
* @param Product $product
119+
* @return bool
120+
* @throws
121+
*/
122+
public function forceRefund(Product $product): bool
123+
{
124+
return $this->refund($product, true);
125+
}
126+
94127
}

src/Traits/HasWallet.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,11 @@ protected function assemble(Wallet $wallet, Transaction $withdraw, Transaction $
168168
*/
169169
protected function change(int $amount, ?array $meta, bool $confirmed): Transaction
170170
{
171-
$this->getBalanceAttribute();
172-
static::$cachedBalances[$this->getKey()] += $amount;
171+
if ($confirmed) {
172+
$this->getBalanceAttribute();
173+
static::$cachedBalances[$this->getKey()] += $amount;
174+
}
175+
173176
return $this->transactions()->create([
174177
'type' => $amount > 0 ? 'deposit' : 'withdraw',
175178
'payable_type' => $this->getMorphClass(),

tests/Models/Item.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,19 @@ class Item extends Model implements Product
2727

2828
/**
2929
* @param Customer $customer
30+
* @param bool $force
3031
*
3132
* @return bool
3233
*/
33-
public function canBuy(Customer $customer): bool
34+
public function canBuy(Customer $customer, bool $force = false): bool
3435
{
35-
return $this->quantity > 0 && !$customer->paid($this);
36+
$result = $this->quantity > 0;
37+
38+
if ($force) {
39+
return $result;
40+
}
41+
42+
return $result && !$customer->paid($this);
3643
}
3744

3845
/**

tests/ProductTest.php

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Bavix\Wallet\Test;
44

5+
use Bavix\Wallet\Models\Transaction;
56
use Bavix\Wallet\Test\Models\Buyer;
67
use Bavix\Wallet\Test\Models\Item;
78

@@ -13,6 +14,10 @@ class ProductTest extends TestCase
1314
*/
1415
public function testPay(): void
1516
{
17+
/**
18+
* @var Buyer $buyer
19+
* @var Item $product
20+
*/
1621
$buyer = factory(Buyer::class)->create();
1722
$product = factory(Item::class)->create([
1823
'quantity' => 1,
@@ -22,7 +27,30 @@ public function testPay(): void
2227
$buyer->deposit($product->price);
2328

2429
$this->assertEquals($buyer->balance, $product->price);
25-
$this->assertNotNull($buyer->pay($product));
30+
$transfer = $buyer->pay($product);
31+
$this->assertNotNull($transfer);
32+
33+
/**
34+
* @var Transaction $withdraw
35+
* @var Transaction $deposit
36+
*/
37+
$withdraw = $transfer->withdraw;
38+
$deposit = $transfer->deposit;
39+
40+
$this->assertInstanceOf(Transaction::class, $withdraw);
41+
$this->assertInstanceOf(Transaction::class, $deposit);
42+
43+
$this->assertInstanceOf(Buyer::class, $withdraw->payable);
44+
$this->assertInstanceOf(Item::class, $deposit->payable);
45+
46+
$this->assertEquals($buyer->getKey(), $withdraw->payable->getKey());
47+
$this->assertEquals($product->getKey(), $deposit->payable->getKey());
48+
49+
$this->assertInstanceOf(Buyer::class, $transfer->from);
50+
$this->assertInstanceOf(Item::class, $transfer->to);
51+
52+
$this->assertEquals($buyer->getKey(), $transfer->from->getKey());
53+
$this->assertEquals($product->getKey(), $transfer->to->getKey());
2654

2755
$this->assertEquals($buyer->balance, 0);
2856
$this->assertNull($buyer->safePay($product));
@@ -33,6 +61,10 @@ public function testPay(): void
3361
*/
3462
public function testRefund(): void
3563
{
64+
/**
65+
* @var Buyer $buyer
66+
* @var Item $product
67+
*/
3668
$buyer = factory(Buyer::class)->create();
3769
$product = factory(Item::class)->create([
3870
'quantity' => 1,
@@ -54,4 +86,88 @@ public function testRefund(): void
5486
$this->assertEquals($buyer->balance, 0);
5587
}
5688

89+
/**
90+
* @return void
91+
*/
92+
public function testForceRefund(): void
93+
{
94+
/**
95+
* @var Buyer $buyer
96+
* @var Item $product
97+
*/
98+
$buyer = factory(Buyer::class)->create();
99+
$product = factory(Item::class)->create([
100+
'quantity' => 1,
101+
]);
102+
103+
$this->assertNotEquals($product->balance, 0);
104+
$product->withdraw($product->balance);
105+
106+
$this->assertEquals($buyer->balance, 0);
107+
$buyer->deposit($product->price);
108+
109+
$this->assertEquals($buyer->balance, $product->price);
110+
111+
$buyer->pay($product);
112+
$this->assertEquals($buyer->balance, 0);
113+
$this->assertEquals($product->balance, $product->price);
114+
115+
$product->withdraw($product->balance);
116+
$this->assertEquals($product->balance, 0);
117+
118+
$this->assertFalse($buyer->safeRefund($product));
119+
$this->assertTrue($buyer->forceRefund($product));
120+
121+
$this->assertEquals($product->balance, -$product->price);
122+
$this->assertEquals($buyer->balance, $product->price);
123+
$product->deposit(-$product->balance);
124+
$buyer->withdraw($buyer->balance);
125+
126+
$this->assertEquals($product->balance, 0);
127+
$this->assertEquals($buyer->balance, 0);
128+
}
129+
130+
/**
131+
* @return void
132+
* @expectedException \Bavix\Wallet\Exceptions\ProductEnded
133+
*/
134+
public function testOutOfStock(): void
135+
{
136+
/**
137+
* @var Buyer $buyer
138+
* @var Item $product
139+
*/
140+
$buyer = factory(Buyer::class)->create();
141+
$product = factory(Item::class)->create([
142+
'quantity' => 1,
143+
]);
144+
145+
$buyer->deposit($product->price);
146+
$buyer->pay($product);
147+
$buyer->pay($product);
148+
}
149+
150+
/**
151+
* @return void
152+
*/
153+
public function testForcePay(): void
154+
{
155+
/**
156+
* @var Buyer $buyer
157+
* @var Item $product
158+
*/
159+
$buyer = factory(Buyer::class)->create();
160+
$product = factory(Item::class)->create([
161+
'quantity' => 1,
162+
]);
163+
164+
$this->assertEquals($buyer->balance, 0);
165+
$buyer->forcePay($product);
166+
167+
$this->assertEquals($buyer->balance, -$product->price);
168+
169+
$buyer->deposit(-$buyer->balance);
170+
$this->assertEquals($buyer->balance, 0);
171+
}
172+
57173
}

0 commit comments

Comments
 (0)