Files
crowd-fund-api/tests/Gateway/Wallet/WalletServiceTest.php

359 lines
14 KiB
PHP

<?php
namespace App\Tests\Gateway\Wallet;
use App\Entity\Accounting\Transaction;
use App\Entity\EmbeddableMoney;
use App\Entity\Gateway\Charge;
use App\Entity\Tipjar;
use App\Entity\User\User;
use App\Gateway\ChargeStatus;
use App\Gateway\ChargeType;
use App\Gateway\Wallet\StatementDirection;
use App\Gateway\Wallet\WalletService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Foundry\Test\ResetDatabase;
class WalletServiceTest extends KernelTestCase
{
use ResetDatabase;
private EntityManagerInterface $entityManager;
private WalletService $walletService;
public function setUp(): void
{
self::bootKernel();
$this->entityManager = static::getContainer()->get(EntityManagerInterface::class);
$this->walletService = static::getContainer()->get(WalletService::class);
}
private function getUser(): User
{
$user = new User();
$user->setHandle('wallettestuser');
$user->setEmail('testuser@wallet.com');
$user->setPassword('wallettestpassword');
$this->entityManager->persist($user);
$this->entityManager->flush();
return $user;
}
private function getTipjar(): Tipjar
{
$tipjar = new Tipjar();
$tipjar->setName('WALLET_TEST_TIPJAR');
$this->entityManager->persist($tipjar);
$this->entityManager->flush();
return $tipjar;
}
public function testSaveAddFunds()
{
$tipjar = $this->getTipjar()->getAccounting();
$user = $this->getUser()->getAccounting();
$statements = $this->walletService->getStatements($user);
$this->assertCount(0, $statements);
$balance = $this->walletService->getBalance($user);
$this->assertEquals(0, $balance->getAmount());
$this->assertEquals($user->getCurrency(), $balance->getCurrency());
$incoming = new Transaction();
$incoming->setMoney(new EmbeddableMoney(100, 'EUR'));
$incoming->setOrigin($tipjar);
$incoming->setTarget($user);
$income = $this->walletService->save($incoming);
$this->assertEquals(100, $income->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Incoming->value, $income->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(0, $income->getFinancesTo());
$this->assertCount(0, $income->getFinancedBy());
$this->entityManager->persist($income);
$this->entityManager->flush();
$balance = $this->walletService->getBalance($user);
$this->assertEquals(100, $balance->getAmount());
$this->assertEquals('EUR', $balance->getCurrency());
$statements = $this->walletService->getStatements($user);
$this->assertCount(1, $statements);
$statement = $statements[0];
$this->assertEquals(100, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Incoming->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(0, $statement->getFinancesTo());
$this->assertCount(0, $statement->getFinancedBy());
}
public function testChargesListenerAddFunds()
{
$tipjar = $this->getTipjar()->getAccounting();
$user = $this->getUser()->getAccounting();
$statements = $this->walletService->getStatements($user);
$this->assertCount(0, $statements);
$balance = $this->walletService->getBalance($user);
$this->assertEquals(0, $balance->getAmount());
$this->assertEquals($user->getCurrency(), $balance->getCurrency());
$incoming = new Charge();
$incoming->setTitle('Wallet Test Charge');
$incoming->setType(ChargeType::Single);
$incoming->setMoney(new EmbeddableMoney(100, 'EUR'));
$incoming->setTarget($user);
$incoming->setStatus(ChargeStatus::InCharge);
$intrx = new Transaction();
$intrx->setMoney($incoming->getMoney());
$intrx->setOrigin($tipjar);
$intrx->setTarget($incoming->getTarget());
$incoming->addTransaction($intrx);
$this->entityManager->persist($incoming);
$this->entityManager->flush();
$balance = $this->walletService->getBalance($user);
$this->assertEquals(100, $balance->getAmount());
$this->assertEquals('EUR', $balance->getCurrency());
$statements = $this->walletService->getStatements($user);
$this->assertCount(1, $statements);
$statement = $statements[0];
$this->assertEquals(100, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Incoming->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(0, $statement->getFinancesTo());
$this->assertCount(0, $statement->getFinancedBy());
}
public function testSpendFinancesExpenses()
{
$tipjar = $this->getTipjar()->getAccounting();
$user = $this->getUser()->getAccounting();
$incoming = new Charge();
$incoming->setTitle('Wallet Test Charge');
$incoming->setType(ChargeType::Single);
$incoming->setMoney(new EmbeddableMoney(100, 'EUR'));
$incoming->setTarget($user);
$incoming->setStatus(ChargeStatus::InCharge);
$intrx = new Transaction();
$intrx->setMoney($incoming->getMoney());
$intrx->setOrigin($tipjar);
$intrx->setTarget($incoming->getTarget());
$incoming->addTransaction($intrx);
$this->entityManager->persist($incoming);
$this->entityManager->flush();
$outgoing = new Transaction();
$outgoing->setMoney(new EmbeddableMoney(20, 'EUR'));
$outgoing->setOrigin($user);
$outgoing->setTarget($tipjar);
$expenditure = $this->walletService->spend($outgoing);
$this->entityManager->persist($expenditure);
$this->entityManager->flush();
$balance = $this->walletService->getBalance($user);
$this->assertEquals(80, $balance->getAmount());
$this->assertEquals('EUR', $balance->getCurrency());
$statements = $this->walletService->getStatements($user);
$this->assertCount(2, $statements);
$statement = $statements[0];
$this->assertEquals(80, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Incoming->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(1, $statement->getFinancesTo());
$this->assertCount(0, $statement->getFinancedBy());
$statement = $statements[1];
$this->assertEquals(20, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Outgoing->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(0, $statement->getFinancesTo());
$this->assertCount(1, $statement->getFinancedBy());
$outgoing = new Transaction();
$outgoing->setMoney(new EmbeddableMoney(30, 'EUR'));
$outgoing->setOrigin($user);
$outgoing->setTarget($tipjar);
$expenditure = $this->walletService->spend($outgoing);
$this->entityManager->persist($expenditure);
$this->entityManager->flush();
$balance = $this->walletService->getBalance($user);
$this->assertEquals(50, $balance->getAmount());
$this->assertEquals('EUR', $balance->getCurrency());
$statements = $this->walletService->getStatements($user);
$this->assertCount(3, $statements);
$statement = $statements[0];
$this->assertEquals(50, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Incoming->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(2, $statement->getFinancesTo());
$this->assertCount(0, $statement->getFinancedBy());
$statement = $statements[1];
$this->assertEquals(20, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Outgoing->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(0, $statement->getFinancesTo());
$this->assertCount(1, $statement->getFinancedBy());
$financement = $statements[0]->getFinancesTo()[0];
$this->assertEquals(20, $financement->getMoney()->getAmount());
$this->assertEquals('EUR', $financement->getMoney()->getCurrency());
$this->assertSame($financement, $statement->getFinancedBy()[0]);
$this->assertEquals($financement->getId(), $statement->getFinancedBy()[0]->getId());
$statement = $statements[2];
$this->assertEquals(30, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Outgoing->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(0, $statement->getFinancesTo());
$this->assertCount(1, $statement->getFinancedBy());
$financement = $statements[0]->getFinancesTo()[1];
$this->assertEquals(30, $financement->getMoney()->getAmount());
$this->assertEquals('EUR', $financement->getMoney()->getCurrency());
$this->assertSame($financement, $statement->getFinancedBy()[0]);
$this->assertEquals($financement->getId(), $statement->getFinancedBy()[0]->getId());
}
public function testBalanceIsFIFO()
{
$tipjar = $this->getTipjar()->getAccounting();
$user = $this->getUser()->getAccounting();
$incoming = new Charge();
$incoming->setTitle('Wallet Test Charge');
$incoming->setType(ChargeType::Single);
$incoming->setMoney(new EmbeddableMoney(10, 'EUR'));
$incoming->setTarget($user);
$incoming->setStatus(ChargeStatus::InCharge);
$intrx = new Transaction();
$intrx->setMoney($incoming->getMoney());
$intrx->setOrigin($tipjar);
$intrx->setTarget($incoming->getTarget());
$incoming->addTransaction($intrx);
$this->entityManager->persist($incoming);
$this->entityManager->flush();
$incoming = new Charge();
$incoming->setTitle('Wallet Test Charge');
$incoming->setType(ChargeType::Single);
$incoming->setMoney(new EmbeddableMoney(11, 'EUR'));
$incoming->setTarget($user);
$incoming->setStatus(ChargeStatus::InCharge);
$intrx = new Transaction();
$intrx->setMoney($incoming->getMoney());
$intrx->setOrigin($tipjar);
$intrx->setTarget($incoming->getTarget());
$incoming->addTransaction($intrx);
$this->entityManager->persist($incoming);
$this->entityManager->flush();
$outgoing = new Transaction();
$outgoing->setMoney(new EmbeddableMoney(12, 'EUR'));
$outgoing->setOrigin($user);
$outgoing->setTarget($tipjar);
$expenditure = $this->walletService->spend($outgoing);
$this->entityManager->persist($expenditure);
$this->entityManager->flush();
$incoming = new Charge();
$incoming->setTitle('Wallet Test Charge');
$incoming->setType(ChargeType::Single);
$incoming->setMoney(new EmbeddableMoney(13, 'EUR'));
$incoming->setTarget($user);
$incoming->setStatus(ChargeStatus::InCharge);
$intrx = new Transaction();
$intrx->setMoney($incoming->getMoney());
$intrx->setOrigin($tipjar);
$intrx->setTarget($incoming->getTarget());
$incoming->addTransaction($intrx);
$this->entityManager->persist($incoming);
$this->entityManager->flush();
$balance = $this->walletService->getBalance($user);
$this->assertEquals(22, $balance->getAmount());
$this->assertEquals('EUR', $balance->getCurrency());
$statements = $this->walletService->getStatements($user);
$this->assertCount(4, $statements);
$statement = $statements[0];
$this->assertEquals(0, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Incoming->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(1, $statement->getFinancesTo());
$this->assertCount(0, $statement->getFinancedBy());
$statement = $statements[1];
$this->assertEquals(9, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Incoming->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(1, $statement->getFinancesTo());
$this->assertCount(0, $statement->getFinancedBy());
$statement = $statements[2];
$this->assertEquals(12, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Outgoing->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(0, $statement->getFinancesTo());
$this->assertCount(2, $statement->getFinancedBy());
$statement = $statements[3];
$this->assertEquals(13, $statement->getBalance()->getAmount());
$this->assertEquals(StatementDirection::Incoming->value, $statement->getDirection()->value);
$this->assertEquals('EUR', $balance->getCurrency());
$this->assertCount(0, $statement->getFinancesTo());
$this->assertCount(0, $statement->getFinancedBy());
}
}