359 lines
14 KiB
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());
|
|
}
|
|
}
|