Skip to content

Commit

Permalink
feat: backend savings
Browse files Browse the repository at this point in the history
  • Loading branch information
dcorroyer authored and dcorroyer committed Oct 26, 2024
1 parent 1377759 commit d1296e8
Show file tree
Hide file tree
Showing 49 changed files with 2,618 additions and 93 deletions.
44 changes: 44 additions & 0 deletions app/migrations/Version20241026154742.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20241026154742 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SEQUENCE "account_id_seq" INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE "transaction_id_seq" INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE "account" (id INT NOT NULL, user_id INT NOT NULL, name VARCHAR(255) NOT NULL, amount DOUBLE PRECISION NOT NULL, type VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_7D3656A4A76ED395 ON "account" (user_id)');
$this->addSql('CREATE TABLE "transaction" (id INT NOT NULL, account_id INT NOT NULL, description VARCHAR(255) NOT NULL, amount DOUBLE PRECISION NOT NULL, type VARCHAR(255) NOT NULL, date DATE NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE INDEX IDX_723705D19B6B5FBA ON "transaction" (account_id)');
$this->addSql('ALTER TABLE "account" ADD CONSTRAINT FK_7D3656A4A76ED395 FOREIGN KEY (user_id) REFERENCES "user" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE "transaction" ADD CONSTRAINT FK_723705D19B6B5FBA FOREIGN KEY (account_id) REFERENCES "account" (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SCHEMA public');
$this->addSql('DROP SEQUENCE "account_id_seq" CASCADE');
$this->addSql('DROP SEQUENCE "transaction_id_seq" CASCADE');
$this->addSql('ALTER TABLE "account" DROP CONSTRAINT FK_7D3656A4A76ED395');
$this->addSql('ALTER TABLE "transaction" DROP CONSTRAINT FK_723705D19B6B5FBA');
$this->addSql('DROP TABLE "account"');
$this->addSql('DROP TABLE "transaction"');
}
}
1 change: 1 addition & 0 deletions app/phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<directory suffix=".php">src/Serializable</directory>
<directory suffix=".php">src/DataFixtures</directory>
<directory suffix=".php">src/Entity</directory>
<directory suffix=".php">src/Enum</directory>
<file>src/Kernel.php</file>
</exclude>

Expand Down
50 changes: 50 additions & 0 deletions app/src/Controller/Account/CreateAccountController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace App\Controller\Account;

use App\Dto\Account\Payload\AccountPayload;
use App\Entity\Account;
use App\Serializable\SerializationGroups;
use App\Service\AccountService;
use My\RestBundle\Attribute\MyOpenApi\MyOpenApi;
use My\RestBundle\Attribute\MyOpenApi\Response\SuccessResponse;
use My\RestBundle\Controller\BaseRestController;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/accounts')]
#[OA\Tag(name: 'Accounts')]
class CreateAccountController extends BaseRestController
{
#[MyOpenApi(
httpMethod: Request::METHOD_POST,
operationId: 'post_account',
summary: 'post account',
responses: [
new SuccessResponse(
responseClassFqcn: Account::class,
groups: [SerializationGroups::ACCOUNT_CREATE],
responseCode: Response::HTTP_CREATED,
description: 'Account creation',
),
],
requestBodyClassFqcn: AccountPayload::class
)]
#[Route('', name: 'api_accounts_create', methods: Request::METHOD_POST)]
public function __invoke(
AccountService $accountService,
#[MapRequestPayload] AccountPayload $accountPayload
): JsonResponse {
return $this->successResponse(
data: $accountService->create($accountPayload),
groups: [SerializationGroups::ACCOUNT_CREATE],
status: Response::HTTP_CREATED,
);
}
}
43 changes: 43 additions & 0 deletions app/src/Controller/Account/DeleteAccountController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace App\Controller\Account;

use App\Entity\Account;
use App\Service\AccountService;
use My\RestBundle\Attribute\MyOpenApi\MyOpenApi;
use My\RestBundle\Attribute\MyOpenApi\Response\NotFoundResponse;
use My\RestBundle\Attribute\MyOpenApi\Response\SuccessResponse;
use My\RestBundle\Controller\BaseRestController;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/accounts')]
#[OA\Tag(name: 'Accounts')]
class DeleteAccountController extends BaseRestController
{
#[MyOpenApi(
httpMethod: Request::METHOD_DELETE,
operationId: 'delete_account',
summary: 'delete account',
responses: [
new SuccessResponse(
responseClassFqcn: Account::class,
responseCode: Response::HTTP_NO_CONTENT,
description: 'Account deleted'
),
new NotFoundResponse(description: 'Account not found'),
],
)]
#[Route('/{id}', name: 'api_accounts_delete', methods: Request::METHOD_DELETE)]
public function __invoke(AccountService $accountService, Account $account): JsonResponse
{
$accountService->delete($account);

return $this->successResponse(data: [], status: Response::HTTP_NO_CONTENT);
}
}
41 changes: 41 additions & 0 deletions app/src/Controller/Account/GetAccountController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace App\Controller\Account;

use App\Entity\Account;
use App\Serializable\SerializationGroups;
use App\Service\AccountService;
use My\RestBundle\Attribute\MyOpenApi\MyOpenApi;
use My\RestBundle\Attribute\MyOpenApi\Response\NotFoundResponse;
use My\RestBundle\Attribute\MyOpenApi\Response\SuccessResponse;
use My\RestBundle\Controller\BaseRestController;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/accounts')]
#[OA\Tag(name: 'Accounts')]
class GetAccountController extends BaseRestController
{
#[MyOpenApi(
httpMethod: Request::METHOD_GET,
operationId: 'get_account',
summary: 'get account',
responses: [
new SuccessResponse(
responseClassFqcn: Account::class,
groups: [SerializationGroups::ACCOUNT_GET],
description: 'Account get',
),
new NotFoundResponse(description: 'Account not found'),
],
)]
#[Route('/{id}', name: 'api_accounts_get', methods: Request::METHOD_GET)]
public function __invoke(int $id, AccountService $accountService): JsonResponse
{
return $this->successResponse(data: $accountService->get($id), groups: [SerializationGroups::ACCOUNT_GET]);
}
}
41 changes: 41 additions & 0 deletions app/src/Controller/Account/ListAccountController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace App\Controller\Account;

use App\Entity\Account;
use App\Serializable\SerializationGroups;
use App\Service\AccountService;
use My\RestBundle\Attribute\MyOpenApi\MyOpenApi;
use My\RestBundle\Attribute\MyOpenApi\Response\SuccessResponse;
use My\RestBundle\Controller\BaseRestController;
use My\RestBundle\Dto\PaginationQueryParams;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/accounts')]
#[OA\Tag(name: 'Accounts')]
class ListAccountController extends BaseRestController
{
#[MyOpenApi(
httpMethod: Request::METHOD_GET,
operationId: 'list_account',
summary: 'list account',
responses: [
new SuccessResponse(
responseClassFqcn: Account::class,
groups: [SerializationGroups::ACCOUNT_LIST],
description: 'Return the list of accounts'
),
],
queryParamsClassFqcn: [PaginationQueryParams::class],
)]
#[Route('', name: 'api_accounts_list', methods: Request::METHOD_GET)]
public function __invoke(AccountService $accountService): JsonResponse
{
return $this->successResponse($accountService->list(), [SerializationGroups::ACCOUNT_LIST]);
}
}
50 changes: 50 additions & 0 deletions app/src/Controller/Account/UpdateAccountController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace App\Controller\Account;

use App\Dto\Account\Payload\AccountPayload;
use App\Entity\Account;
use App\Serializable\SerializationGroups;
use App\Service\AccountService;
use My\RestBundle\Attribute\MyOpenApi\MyOpenApi;
use My\RestBundle\Attribute\MyOpenApi\Response\NotFoundResponse;
use My\RestBundle\Attribute\MyOpenApi\Response\SuccessResponse;
use My\RestBundle\Controller\BaseRestController;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/accounts')]
#[OA\Tag(name: 'Accounts')]
class UpdateAccountController extends BaseRestController
{
#[MyOpenApi(
httpMethod: Request::METHOD_PATCH,
operationId: 'put_account',
summary: 'put account',
responses: [
new SuccessResponse(
responseClassFqcn: Account::class,
groups: [SerializationGroups::ACCOUNT_UPDATE],
description: 'Account updated',
),
new NotFoundResponse(description: 'Account not found'),
],
requestBodyClassFqcn: AccountPayload::class
)]
#[Route('/{id}', name: 'api_account_update', methods: Request::METHOD_PATCH)]
public function __invoke(
AccountService $accountService,
Account $account,
#[MapRequestPayload] AccountPayload $accountPayload
): JsonResponse {
return $this->successResponse(
data: $accountService->update($accountPayload, $account),
groups: [SerializationGroups::ACCOUNT_UPDATE]
);
}
}
4 changes: 3 additions & 1 deletion app/src/Controller/Budget/DeleteBudgetController.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class DeleteBudgetController extends BaseRestController
#[Route('/{id}', name: 'api_budgets_delete', methods: Request::METHOD_DELETE)]
public function __invoke(BudgetService $budgetService, Budget $budget): JsonResponse
{
return $this->successResponse(data: $budgetService->delete($budget), status: Response::HTTP_NO_CONTENT);
$budgetService->delete($budget);

return $this->successResponse(data: [], status: Response::HTTP_NO_CONTENT);
}
}
8 changes: 5 additions & 3 deletions app/src/Controller/Budget/GetBudgetController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ class GetBudgetController extends BaseRestController
operationId: 'get_budget',
summary: 'get budget',
responses: [
new SuccessResponse(responseClassFqcn: Budget::class, groups: [
SerializationGroups::BUDGET_GET,
], description: 'Budget get'),
new SuccessResponse(
responseClassFqcn: Budget::class,
groups: [SerializationGroups::BUDGET_GET],
description: 'Budget get',
),
new NotFoundResponse(description: 'Budget not found'),
],
)]
Expand Down
51 changes: 51 additions & 0 deletions app/src/Controller/Transaction/CreateTransactionController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace App\Controller\Transaction;

use App\Dto\Transaction\Payload\TransactionPayload;
use App\Entity\Transaction;
use App\Serializable\SerializationGroups;
use App\Service\TransactionService;
use My\RestBundle\Attribute\MyOpenApi\MyOpenApi;
use My\RestBundle\Attribute\MyOpenApi\Response\SuccessResponse;
use My\RestBundle\Controller\BaseRestController;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\MapRequestPayload;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/accounts/{accountId}/transactions')]
#[OA\Tag(name: 'Transactions')]
class CreateTransactionController extends BaseRestController
{
#[MyOpenApi(
httpMethod: Request::METHOD_POST,
operationId: 'post_transaction',
summary: 'post transaction',
responses: [
new SuccessResponse(
responseClassFqcn: Transaction::class,
groups: [SerializationGroups::TRANSACTION_CREATE],
responseCode: Response::HTTP_CREATED,
description: 'Transaction creation',
),
],
requestBodyClassFqcn: TransactionPayload::class
)]
#[Route('', name: 'api_transactions_create', methods: Request::METHOD_POST)]
public function __invoke(
int $accountId,
TransactionService $transactionService,
#[MapRequestPayload] TransactionPayload $transactionPayload
): JsonResponse {
return $this->successResponse(
data: $transactionService->create($accountId, $transactionPayload),
groups: [SerializationGroups::TRANSACTION_CREATE],
status: Response::HTTP_CREATED,
);
}
}
Loading

0 comments on commit d1296e8

Please sign in to comment.