Skip to content

add force method's #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions src/Interfaces/Customer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,26 @@ interface Customer extends Wallet

/**
* @param Product $product
* @param bool $force
* @return Transfer
* @throws
*/
public function pay(Product $product): Transfer;
public function pay(Product $product, bool $force = false): Transfer;

/**
* @param Product $product
* @param bool $force
* @return null|Transfer
* @throws
*/
public function safePay(Product $product): ?Transfer;
public function safePay(Product $product, bool $force = false): ?Transfer;

/**
* @param Product $product
* @return Transfer
* @throws
*/
public function forcePay(Product $product): Transfer;

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

/**
* @param Product $product
* @param bool $force
* @return bool
* @throws
*/
public function refund(Product $product): bool;
public function refund(Product $product, bool $force = false): bool;

/**
* @param Product $product
* @param bool $force
* @return bool
*/
public function safeRefund(Product $product, bool $force = false): bool;

/**
* @param Product $product
* @return bool
*/
public function safeRefund(Product $product): bool;
public function forceRefund(Product $product): bool;

}
3 changes: 2 additions & 1 deletion src/Interfaces/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ interface Product extends Wallet

/**
* @param Customer $customer
* @param bool $force
*
* @return bool
*/
public function canBuy(Customer $customer): bool;
public function canBuy(Customer $customer, bool $force = false): bool;

/**
* @return int
Expand Down
51 changes: 42 additions & 9 deletions src/Traits/CanBePaid.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,47 @@ trait CanBePaid

/**
* @param Product $product
* @param bool $force
* @return Transfer
* @throws
*/
public function pay(Product $product): Transfer
public function pay(Product $product, bool $force = false): Transfer
{
if (!$product->canBuy($this)) {
if (!$product->canBuy($this, $force)) {
throw new ProductEnded('The product is out of stock');
}

if ($force) {
return $this->forceTransfer($product, $product->getAmountProduct(), $product->getMetaProduct());
}

return $this->transfer($product, $product->getAmountProduct(), $product->getMetaProduct());
}

/**
* @param Product $product
* @param bool $force
* @return Transfer|null
*/
public function safePay(Product $product): ?Transfer
public function safePay(Product $product, bool $force = false): ?Transfer
{
try {
return $this->pay($product);
return $this->pay($product, $force);
} catch (\Throwable $throwable) {
return null;
}
}

/**
* @param Product $product
* @return Transfer
* @throws
*/
public function forcePay(Product $product): Transfer
{
return $this->pay($product, true);
}

/**
* @param Product $product
* @return null|Transfer
Expand All @@ -60,10 +76,11 @@ public function paid(Product $product): ?Transfer

/**
* @param Product $product
* @param bool $force
* @return bool
* @throws
*/
public function refund(Product $product): bool
public function refund(Product $product, bool $force = false): bool
{
$transfer = $this->paid($product);

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

return DB::transaction(function() use ($product, $transfer) {
$product->transfer($this, $product->getAmountProduct(), $product->getMetaProduct());
return DB::transaction(function() use ($product, $transfer, $force) {
if ($force) {
$product->forceTransfer($this, $product->getAmountProduct(), $product->getMetaProduct());
} else {
$product->transfer($this, $product->getAmountProduct(), $product->getMetaProduct());
}

return $transfer->update(['refund' => 1]);
});
}

/**
* @param Product $product
* @param bool $force
* @return bool
*/
public function safeRefund(Product $product): bool
public function safeRefund(Product $product, bool $force = false): bool
{
try {
return $this->refund($product);
return $this->refund($product, $force);
} catch (\Throwable $throwable) {
return false;
}
}

/**
* @param Product $product
* @return bool
* @throws
*/
public function forceRefund(Product $product): bool
{
return $this->refund($product, true);
}

}
7 changes: 5 additions & 2 deletions src/Traits/HasWallet.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,11 @@ protected function assemble(Wallet $wallet, Transaction $withdraw, Transaction $
*/
protected function change(int $amount, ?array $meta, bool $confirmed): Transaction
{
$this->getBalanceAttribute();
static::$cachedBalances[$this->getKey()] += $amount;
if ($confirmed) {
$this->getBalanceAttribute();
static::$cachedBalances[$this->getKey()] += $amount;
}

return $this->transactions()->create([
'type' => $amount > 0 ? 'deposit' : 'withdraw',
'payable_type' => $this->getMorphClass(),
Expand Down
11 changes: 9 additions & 2 deletions tests/Models/Item.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,19 @@ class Item extends Model implements Product

/**
* @param Customer $customer
* @param bool $force
*
* @return bool
*/
public function canBuy(Customer $customer): bool
public function canBuy(Customer $customer, bool $force = false): bool
{
return $this->quantity > 0 && !$customer->paid($this);
$result = $this->quantity > 0;

if ($force) {
return $result;
}

return $result && !$customer->paid($this);
}

/**
Expand Down
118 changes: 117 additions & 1 deletion tests/ProductTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Bavix\Wallet\Test;

use Bavix\Wallet\Models\Transaction;
use Bavix\Wallet\Test\Models\Buyer;
use Bavix\Wallet\Test\Models\Item;

Expand All @@ -13,6 +14,10 @@ class ProductTest extends TestCase
*/
public function testPay(): void
{
/**
* @var Buyer $buyer
* @var Item $product
*/
$buyer = factory(Buyer::class)->create();
$product = factory(Item::class)->create([
'quantity' => 1,
Expand All @@ -22,7 +27,30 @@ public function testPay(): void
$buyer->deposit($product->price);

$this->assertEquals($buyer->balance, $product->price);
$this->assertNotNull($buyer->pay($product));
$transfer = $buyer->pay($product);
$this->assertNotNull($transfer);

/**
* @var Transaction $withdraw
* @var Transaction $deposit
*/
$withdraw = $transfer->withdraw;
$deposit = $transfer->deposit;

$this->assertInstanceOf(Transaction::class, $withdraw);
$this->assertInstanceOf(Transaction::class, $deposit);

$this->assertInstanceOf(Buyer::class, $withdraw->payable);
$this->assertInstanceOf(Item::class, $deposit->payable);

$this->assertEquals($buyer->getKey(), $withdraw->payable->getKey());
$this->assertEquals($product->getKey(), $deposit->payable->getKey());

$this->assertInstanceOf(Buyer::class, $transfer->from);
$this->assertInstanceOf(Item::class, $transfer->to);

$this->assertEquals($buyer->getKey(), $transfer->from->getKey());
$this->assertEquals($product->getKey(), $transfer->to->getKey());

$this->assertEquals($buyer->balance, 0);
$this->assertNull($buyer->safePay($product));
Expand All @@ -33,6 +61,10 @@ public function testPay(): void
*/
public function testRefund(): void
{
/**
* @var Buyer $buyer
* @var Item $product
*/
$buyer = factory(Buyer::class)->create();
$product = factory(Item::class)->create([
'quantity' => 1,
Expand All @@ -54,4 +86,88 @@ public function testRefund(): void
$this->assertEquals($buyer->balance, 0);
}

/**
* @return void
*/
public function testForceRefund(): void
{
/**
* @var Buyer $buyer
* @var Item $product
*/
$buyer = factory(Buyer::class)->create();
$product = factory(Item::class)->create([
'quantity' => 1,
]);

$this->assertNotEquals($product->balance, 0);
$product->withdraw($product->balance);

$this->assertEquals($buyer->balance, 0);
$buyer->deposit($product->price);

$this->assertEquals($buyer->balance, $product->price);

$buyer->pay($product);
$this->assertEquals($buyer->balance, 0);
$this->assertEquals($product->balance, $product->price);

$product->withdraw($product->balance);
$this->assertEquals($product->balance, 0);

$this->assertFalse($buyer->safeRefund($product));
$this->assertTrue($buyer->forceRefund($product));

$this->assertEquals($product->balance, -$product->price);
$this->assertEquals($buyer->balance, $product->price);
$product->deposit(-$product->balance);
$buyer->withdraw($buyer->balance);

$this->assertEquals($product->balance, 0);
$this->assertEquals($buyer->balance, 0);
}

/**
* @return void
* @expectedException \Bavix\Wallet\Exceptions\ProductEnded
*/
public function testOutOfStock(): void
{
/**
* @var Buyer $buyer
* @var Item $product
*/
$buyer = factory(Buyer::class)->create();
$product = factory(Item::class)->create([
'quantity' => 1,
]);

$buyer->deposit($product->price);
$buyer->pay($product);
$buyer->pay($product);
}

/**
* @return void
*/
public function testForcePay(): void
{
/**
* @var Buyer $buyer
* @var Item $product
*/
$buyer = factory(Buyer::class)->create();
$product = factory(Item::class)->create([
'quantity' => 1,
]);

$this->assertEquals($buyer->balance, 0);
$buyer->forcePay($product);

$this->assertEquals($buyer->balance, -$product->price);

$buyer->deposit(-$buyer->balance);
$this->assertEquals($buyer->balance, 0);
}

}
Loading