Pass WalletGatewayServiceTest

This commit is contained in:
2024-10-25 12:28:01 +02:00
parent 73fc1fafc5
commit 6a4f97bc51
@@ -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;
}
}
}