Skip to content

Commit

Permalink
Pass WalletGatewayServiceTest
Browse files Browse the repository at this point in the history
  • Loading branch information
subiabre committed Oct 25, 2024
1 parent 73fc1fa commit 6a4f97b
Showing 1 changed file with 85 additions and 14 deletions.
99 changes: 85 additions & 14 deletions src/Library/Economy/Payment/WalletGatewayService.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,113 @@
namespace App\Library\Economy\Payment;

use App\Entity\Accounting;
use App\Entity\AccountingTransaction;
use App\Entity\Money;
use App\Entity\WalletStatement;
use App\Entity\WalletStatementDirection;
use App\Library\Economy\MoneyService;
use App\Repository\WalletStatementRepository;
use Brick\Money as Brick;
use Doctrine\ORM\EntityManagerInterface;

class WalletGatewayService
{
public function __construct(
private MoneyService $money,
private WalletStatementRepository $walletStatementRepository,
private EntityManagerInterface $entityManager,
) {}

public function getAccountingBalance(Accounting $accounting): Money
/**
* @return \App\Entity\WalletStatement[]
*/
public function getStatements(Accounting $accounting): array
{
$available = Brick\Money::ofMinor(0, $accounting->getCurrency());
$statements = $this->walletStatementRepository->findByAccounting($accounting);
return $this->walletStatementRepository->findByAccounting($accounting);
}

public function getBalance(Accounting $accounting): Money
{
$total = Brick\Money::ofMinor(0, $accounting->getCurrency());
$statements = $this->getStatements($accounting);

foreach ($statements as $statement) {
$transaction = $statement->getTransaction();
$money = Brick\Money::ofMinor(
$transaction->getMoney()->amount,
$transaction->getMoney()->currency
);
$transacted = $this->money->toBrick($statement->getTransaction()->getMoney());

switch ($statement->getDirection()) {
case WalletStatementDirection::Incoming:
$available = $available->plus($money);
$total = $total->plus($transacted);
break;
case WalletStatementDirection::Outgoing:
$available = $available->minus($money);
$total = $total->minus($transacted);
break;
}
}

return new Money(
$available->getMinorAmount()->toInt(),
$available->getCurrency()->getCurrencyCode()
);
return $this->money->toMoney($total);
}

/**
* Puts the money of a Transaction into the target wallet.
*
* @param AccountingTransaction $transaction The Transaction targetting a wallet
* @return \App\Entity\WalletStatement An incoming statement for the target wallet
*/
public function save(AccountingTransaction $transaction): WalletStatement
{
$statement = new WalletStatement();
$statement->setTransaction($transaction);
$statement->setDirection(WalletStatementDirection::Incoming);
$statement->setBalance($transaction->getMoney());

$this->entityManager->persist($statement);
$this->entityManager->flush();

return $statement;
}

/**
* Takes the money of a Transaction from the origin wallet.
*
* @param AccountingTransaction $transaction The Transaction originating from a wallet
* @return \App\Entity\WalletStatement An outgoing statement financed by previous incoming statements
*/
public function spend(AccountingTransaction $transaction): WalletStatement
{
$origin = $transaction->getOrigin();
$toSpend = $transaction->getMoney();

$outgoing = new WalletStatement();
$outgoing->setTransaction($transaction);
$outgoing->setDirection(WalletStatementDirection::Outgoing);

$incomings = $this->getStatements($origin);
foreach ($incomings as $incoming) {
$spent = new Money(0, $toSpend->currency);
$balance = $incoming->getBalance();

if ($balance->amount === 0) {
continue;
}

if ($this->money->isMoreOrSame($balance, $spent)) {
$spent = $toSpend;
} else {
$spent = $this->money->add($balance, $spent);
}

$balance = $this->money->substract($spent, $balance);

$incoming->setBalance($balance);

$outgoing->setBalance($spent);
$outgoing->addFinancedBy($incoming);

$this->entityManager->persist($incoming);
$this->entityManager->persist($outgoing);
$this->entityManager->flush();

return $outgoing;
}
}
}

0 comments on commit 6a4f97b

Please sign in to comment.