TASK-37: Add ability to accept new clients from CRM

This commit is contained in:
Kacper Donat 2024-04-14 18:23:14 +02:00
parent 8a3068419e
commit d6fdec2a8b
7 changed files with 211 additions and 23 deletions

View File

@ -0,0 +1,34 @@
Feature:
The CRM system is able to send information about new Clients to the service
Background:
Given there exist following clients:
| clientId | name | initialBalance | currentBalance |
| 018edd2e-894a-78d7-b10c-16e05ca933a3 | Kacper | 10000 | 5000 |
Scenario: CRM is able to create new clients
Given the request has the following body:
"""
{
"clientId": "018edd37-c145-7143-ba91-c191084e4fba",
"name": "Jan",
"balance": 100000
}
"""
When I send a POST request to "/clients"
Then the response status should be 201
And client with id "018edd37-c145-7143-ba91-c191084e4fba" should exist
And client with id "018edd37-c145-7143-ba91-c191084e4fba" should have balance of 100000
Scenario: CRM should not be able to override existing user
Given the request has the following body:
"""
{
"clientId": "018edd2e-894a-78d7-b10c-16e05ca933a3",
"name": "Kacper",
"balance": 100000
}
"""
When I send a POST request to "/clients"
Then the response status should be 409
And client with id "018edd2e-894a-78d7-b10c-16e05ca933a3" should exist

View File

@ -0,0 +1,40 @@
<?php
namespace App\Controller;
use App\Contract\ClientDto;
use App\Entity\Client;
use App\Exception\ClientAlreadyExistsException;
use App\Service\ClientService;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;
#[Route(path: '/clients', name: 'clients_')]
#[AsController]
readonly class ClientController
{
public function __construct(
private ClientService $clientService,
) {
}
#[Route(name: 'create', methods: ['POST'])]
public function create(#[MapRequestPayload] ClientDto $clientDto): Response
{
$client = new Client(
clientId: $clientDto->getClientId(),
name: $clientDto->getName(),
initialBalance: $clientDto->getBalance(),
);
try {
$this->clientService->createNewClient($client);
} catch (ClientAlreadyExistsException) {
return new Response(status: Response::HTTP_CONFLICT);
}
return new Response(status: Response::HTTP_CREATED);
}
}

View File

@ -18,9 +18,13 @@ class Client
#[ORM\Column]
private ?string $name = null,
#[ORM\Column]
private ?int $initialBalance = null,
#[ORM\Column]
private ?int $currentBalance = null,
) {
$this->currentBalance ??= $this->initialBalance;
}
public function getClientId(): ?Uuid
@ -38,6 +42,16 @@ class Client
$this->name = $name;
}
public function getInitialBalance(): ?int
{
return $this->initialBalance;
}
public function setInitialBalance(?int $initialBalance): void
{
$this->initialBalance = $initialBalance;
}
public function getBalance(): ?int
{
return $this->currentBalance;

View File

@ -0,0 +1,7 @@
<?php
namespace App\Exception;
class ClientAlreadyExistsException extends \LogicException
{
}

View File

@ -21,28 +21,11 @@ class ClientRepository extends ServiceEntityRepository
parent::__construct($registry, Client::class);
}
// /**
// * @return Client[] Returns an array of Client objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('c.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
public function save(Client $client): Client
{
$this->getEntityManager()->persist($client);
$this->getEntityManager()->flush();
// public function findOneBySomeField($value): ?Client
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
return $client;
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Service;
use App\Entity\Client;
use App\Exception\ClientAlreadyExistsException;
use App\Repository\ClientRepository;
class ClientService
{
public function __construct(
public readonly ClientRepository $clientRepository
) {
}
public function createNewClient(Client $client): Client
{
$existing = $this->clientRepository->find($client->getClientId());
if ($existing !== null) {
throw new ClientAlreadyExistsException(
message: sprintf('Client with id "%s" already exists.', $client->getClientId()->toRfc4122())
);
}
return $this->clientRepository->save($client);
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace App\Tests\Behat;
use App\Entity\Client;
use App\Repository\ClientRepository;
use Behat\Behat\Context\Context;
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Gherkin\Node\TableNode;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\Assert;
use Symfony\Component\Uid\Uuid;
class ClientsContext implements Context
{
private array $clients;
public function __construct(
protected readonly ClientRepository $clientRepository,
) {}
/**
* @BeforeScenario
*/
public function clean()
{
$this->clientRepository
->createQueryBuilder('c')
->delete()
->getQuery()
->execute();
$this->clients = [];
}
/**
* @Given /^there exist following clients:$/
*/
public function thereExistFollowingClients(TableNode $table)
{
foreach ($table as $row) {
$client = $this->getClient($row['clientId']);
if (!$client) {
$client = new Client(
clientId: Uuid::fromRfc4122($row['clientId']),
name: $row['name'],
initialBalance: intval($row['initialBalance']),
currentBalance: intval($row['currentBalance']),
);
$this->clientRepository->save($client);
}
$this->clients[$client->getClientId()->toRfc4122()] = $client;
}
}
public function getClient(string $id): ?Client
{
return $this->clients[$id] ??= $this->clientRepository->find(Uuid::fromRfc4122($id));
}
/**
* @Given /^client with id "([^"]+)" should exist$/
*/
public function clientWithIdShouldExist(string $clientId)
{
Assert::assertNotNull($this->getClient($clientId));
}
/**
* @Given /^client with id "([^"]+)" should have balance of (\d+)$/
*/
public function clientWithIdShouldHaveBalanceOf(string $clientId, int $balance)
{
$client = $this->getClient($clientId);
Assert::assertEquals($client->getBalance(), $balance);
}
}