Files
2024-01-25 12:54:01 +01:00

279 lines
12 KiB
PHP

<?php
/*
* This file has been created by developers from BitBag.
* Feel free to contact us once you face any issues or want to start
* You can find more information about us on https://bitbag.io and write us
* an email on hello@bitbag.io.
*/
declare(strict_types=1);
namespace Tests\BitBag\OpenMarketplace\Integration\Cli;
use ApiTestCase\JsonApiTestCase;
use BitBag\OpenMarketplace\Component\Order\Entity\OrderInterface;
use BitBag\OpenMarketplace\Component\Settlement\Entity\SettlementInterface;
use BitBag\OpenMarketplace\Component\Settlement\PeriodStrategy\QuarterlySettlementPeriodResolver;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
final class SettlementGenerateCommandTest extends JsonApiTestCase
{
protected function setUp(): void
{
parent::setUp();
$kernel = self::bootKernel();
$application = new Application($kernel);
$command = $application->find('bitbag:settlement:generate');
$this->commandTester = new CommandTester($command);
$this->settlementRepository = self::getContainer()->get('open_marketplace.repository.settlement');
$this->vendorRepository = self::getContainer()->get('bitbag.open_marketplace.component.vendor.repository.vendor');
$this->channelRepository = self::getContainer()->get('sylius.repository.channel');
$this->orderRepository = self::getContainer()->get('sylius.repository.order');
}
public function test_it_throws_exception_if_period_resolver_for_settlement_frequency_does_not_exist(): void
{
$this->loadFixturesFromFile('SettlementGenerateCommandTest/test_it_throws_exception_if_period_resolver_for_settlement_frequency_does_not_exist.yaml');
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Could not find period resolver for vendor with settlement frequency "daily"');
$this->commandTester->execute([]);
}
public function test_it_generates_settlements_for_all_vendors(): void
{
$this->loadFixturesFromFile('SettlementGenerateCommandTest/test_it_generates_settlements_for_all_vendors.yaml');
$this->assertCount(0, $this->settlementRepository->findAll());
$this->commandTester->execute([]);
$this->commandTester->assertCommandIsSuccessful();
$vendorWeyland = $this->vendorRepository->findOneBySlug('Weyland-Corp');
$vendorWayne = $this->vendorRepository->findOneBySlug('Wayne-Enterprises-Inc');
$vendorTommy = $this->vendorRepository->findOneBySlug('Tommy-Corp');
$channelEu = $this->channelRepository->findOneBy(['code' => 'EU']);
$channelUs = $this->channelRepository->findOneBy(['code' => 'US']);
$settlementsVendorWeyland = $this->settlementRepository->findBy(['vendor' => $vendorWeyland]);
$settlementsVendorWayne = $this->settlementRepository->findBy(['vendor' => $vendorWayne]);
$settlementsVendorTommy = $this->settlementRepository->findBy(['vendor' => $vendorTommy]);
[$weeklyStartDate, $weeklyEndDate] = $this->getStartAndEndDate('weekly');
[$monthlyStartDate, $monthlyEndDate] = $this->getStartAndEndDate('monthly');
[$quarterlyStartDate, $quarterlyEndDate] = $this->getStartAndEndDate('quarterly');
$this->assertCount(2, $settlementsVendorWayne);
$this->assertSettlementSame(
[
'totalAmount' => 540,
'totalCommissionAmount' => 35,
'startDate' => $monthlyStartDate,
'endDate' => $monthlyEndDate,
'channel' => $channelUs,
],
$settlementsVendorWayne[0]
);
$this->assertSettlementSame(
[
'totalAmount' => 1002,
'totalCommissionAmount' => 70,
'startDate' => $monthlyStartDate,
'endDate' => $monthlyEndDate,
'channel' => $channelEu,
],
$settlementsVendorWayne[1]
);
$this->assertCount(2, $settlementsVendorWeyland);
$this->assertSettlementSame(
[
'totalAmount' => 0,
'totalCommissionAmount' => 0,
'startDate' => $weeklyStartDate,
'endDate' => $weeklyEndDate,
'channel' => $channelUs,
],
$settlementsVendorWeyland[0]
);
$this->assertSettlementSame(
[
'totalAmount' => 700,
'totalCommissionAmount' => 100,
'startDate' => $weeklyStartDate,
'endDate' => $weeklyEndDate,
'channel' => $channelEu,
],
$settlementsVendorWeyland[1]
);
$this->assertCount(2, $settlementsVendorTommy);
$this->assertSettlementSame(
[
'totalAmount' => 400,
'totalCommissionAmount' => 10,
'startDate' => $quarterlyStartDate,
'endDate' => $quarterlyEndDate,
'channel' => $channelUs,
],
$settlementsVendorTommy[0]
);
$this->assertSettlementSame(
[
'totalAmount' => 0,
'totalCommissionAmount' => 0,
'startDate' => $quarterlyStartDate,
'endDate' => $quarterlyEndDate,
'channel' => $channelEu,
],
$settlementsVendorTommy[1]
);
}
public function test_it_not_generates_settlements_for_if_settlement_already_exist(): void
{
$this->loadFixturesFromFile('SettlementGenerateCommandTest/test_it_not_generates_settlements_for_if_settlement_already_exist.yaml');
$settlements = $this->settlementRepository->findAll();
$vendorWeyland = $this->vendorRepository->findOneBySlug('Weyland-Corp');
$vendorWayne = $this->vendorRepository->findOneBySlug('Wayne-Enterprises-Inc');
$channelEu = $this->channelRepository->findOneBy(['code' => 'EU']);
$channelUs = $this->channelRepository->findOneBy(['code' => 'US']);
[$startDate, $endDate] = $this->getStartAndEndDate('weekly');
$this->assertCount(1, $settlements);
$this->assertSettlementSame(
[
'totalAmount' => 1002,
'totalCommissionAmount' => 70,
'startDate' => $startDate,
'endDate' => $endDate,
'channel' => $channelEu,
],
$settlements[0]
);
$this->commandTester->execute([]);
$this->commandTester->assertCommandIsSuccessful();
$settlementsVendorWeyland = $this->settlementRepository->findBy(['vendor' => $vendorWeyland]);
$settlementsVendorWayne = $this->settlementRepository->findBy(['vendor' => $vendorWayne]);
$this->assertCount(2, $settlementsVendorWayne);
$this->assertSame($settlements[0], $settlementsVendorWayne[0]);
$this->assertSettlementSame(
[
'totalAmount' => 540,
'totalCommissionAmount' => 35,
'startDate' => $startDate,
'endDate' => $endDate,
'channel' => $channelUs,
],
$settlementsVendorWayne[1]
);
$this->assertCount(2, $settlementsVendorWeyland);
$this->assertSettlementSame(
[
'totalAmount' => 0,
'totalCommissionAmount' => 0,
'startDate' => $startDate,
'endDate' => $endDate,
'channel' => $channelUs,
],
$settlementsVendorWeyland[0]
);
$this->assertSettlementSame(
[
'totalAmount' => 700,
'totalCommissionAmount' => 100,
'startDate' => $startDate,
'endDate' => $endDate,
'channel' => $channelEu,
],
$settlementsVendorWeyland[1]
);
}
public function test_it_generates_settlements_for_incomplete_period(): void
{
$this->loadFixturesFromFile('SettlementGenerateCommandTest/test_it_generates_settlements_for_incomplete_period.yaml');
$settlements = $this->settlementRepository->findAll();
$vendorWayne = $this->vendorRepository->findOneBySlug('Wayne-Enterprises-Inc');
$channelUs = $this->channelRepository->findOneBy(['code' => 'US']);
$channelEu = $this->channelRepository->findOneBy(['code' => 'EU']);
[$startDate, $endDate] = $this->getStartAndEndDate('weekly');
/** @var OrderInterface $lastWayneOrder */
$lastWayneOrder = $this->orderRepository->findOneBy(['vendor' => $vendorWayne], ['paidAt' => 'DESC']);
$to = \DateTime::createFromInterface($lastWayneOrder->getPaidAt())->modify('- 1 hour');
$from = new \DateTime('last week monday');
$settlement = $settlements[0];
$settlement->setStartDate($from);
$settlement->setEndDate($to);
$this->assertSettlementSame(
[
'totalAmount' => 1002,
'totalCommissionAmount' => 70,
'startDate' => $from,
'endDate' => $to,
'channel' => $channelEu,
],
$settlement
);
$this->getEntityManager()->flush();
$this->commandTester->execute([]);
$this->commandTester->assertCommandIsSuccessful();
$settlementsVendorWayne = $this->settlementRepository->findBy(['vendor' => $vendorWayne]);
$this->assertCount(3, $settlementsVendorWayne);
$this->assertSame($settlements[0], $settlementsVendorWayne[0]);
$this->assertSettlementSame(
[
'totalAmount' => 0,
'totalCommissionAmount' => 0,
'startDate' => $startDate,
'endDate' => $endDate,
'channel' => $channelUs,
],
$settlementsVendorWayne[1]
);
$this->assertSettlementSame(
[
'totalAmount' => 540,
'totalCommissionAmount' => 35,
'startDate' => \DateTime::createFromInterface($settlement->getEndDate())->modify('+ 1 second'),
'endDate' => $endDate,
'channel' => $channelEu,
],
$settlementsVendorWayne[2]
);
}
private function getStartAndEndDate(string $frequency): array
{
return match ($frequency) {
'weekly' => [
new \DateTime('last week monday 00:00:00'),
new \DateTime('last week sunday 23:59:59'),
],
'monthly' => [
new \DateTime('first day of last month 00:00:00'),
new \DateTime('last day of last month 23:59:59'),
],
'quarterly' => [
(new \DateTime())->setTimestamp(QuarterlySettlementPeriodResolver::getLastQuarterStartDate()),
(new \DateTime())->setTimestamp(QuarterlySettlementPeriodResolver::getLastQuarterEndDate()),
],
};
}
private function assertSettlementSame(array $expected, SettlementInterface $actual): void
{
$this->assertSame($expected['totalAmount'], $actual->getTotalAmount());
$this->assertSame($expected['totalCommissionAmount'], $actual->getTotalCommissionAmount());
$this->assertSame($expected['startDate']->getTimestamp(), $actual->getStartDate()->getTimestamp());
$this->assertSame($expected['endDate']->getTimestamp(), $actual->getEndDate()->getTimestamp());
$this->assertSame($expected['channel'], $actual->getChannel());
}
}