Skip to content

Commit

Permalink
Implement multiple tags filtering per wallet endpoints (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
vokomarov authored Apr 28, 2024
2 parents 953292e + 9c2a3db commit 2574fcc
Show file tree
Hide file tree
Showing 14 changed files with 933 additions and 1,118 deletions.
3 changes: 2 additions & 1 deletion app/src/Controller/Wallets/Charges/ChargesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function list(string $walletId, InputManager $input): ResponseInterface
$charges = $this->chargeRepository
->filter($input->query->fetch(['date-from', 'date-to']))
->paginate($this->paginationFactory->createPaginator())
->findByWalletIdWithPagination((int) $wallet->id);
->findByWalletIdAndTagIdsWithPagination((int) $wallet->id, $this->fetchFilteredTagIDs($input));

return $this->chargesView->jsonPaginated($charges, $this->chargeRepository->getPaginationState());
}
Expand All @@ -72,6 +72,7 @@ public function graph(string $walletId, InputManager $input, ChargeAmountGraph $

$graph->filter($input->query->fetch(['date-from', 'date-to']));
$graph->groupBy($input->query('group-by'));
$graph->groupByTags($this->fetchFilteredTagIDs($input));

return $this->response->json([
'data' => $graph->getGraph(wallet: $wallet),
Expand Down
79 changes: 0 additions & 79 deletions app/src/Controller/Wallets/Charges/TagsController.php

This file was deleted.

13 changes: 13 additions & 0 deletions app/src/Controller/Wallets/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,20 @@
namespace App\Controller\Wallets;

use App\Controller\AuthAwareController;
use Spiral\Http\Request\InputManager;

class Controller extends AuthAwareController
{
/**
* @param \Spiral\Http\Request\InputManager $input
* @param string $key
* @return int[]
*/
protected function fetchFilteredTagIDs(InputManager $input, string $key = 'tags'): array
{
$ids = $input->query->get($key, '');
$ids = explode(',', $ids);
$ids = array_map(fn($id) => (int) $id, $ids);
return array_filter($ids, fn($id) => $id > 0);
}
}
29 changes: 0 additions & 29 deletions app/src/Controller/Wallets/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@

namespace App\Controller\Wallets;

use App\Database\Charge;
use App\Database\Wallet;
use App\Repository\ChargeRepository;
use App\Repository\WalletRepository;
use App\Service\ChargeWalletService;
use App\View\WalletView;
use Psr\Http\Message\ResponseInterface;
use Spiral\Auth\AuthScope;
use Spiral\Http\Request\InputManager;
use Spiral\Http\ResponseWrapper;
use Spiral\Router\Annotation\Route;

Expand All @@ -23,8 +19,6 @@ public function __construct(
private ResponseWrapper $response,
private WalletRepository $walletRepository,
private WalletView $walletView,
private ChargeRepository $chargeRepository,
private ChargeWalletService $chargeWalletService,
) {
parent::__construct($auth);
}
Expand All @@ -40,27 +34,4 @@ public function index(string $id): ResponseInterface

return $this->walletView->json($wallet);
}

#[Route(route: '/wallets/<id>/total', name: 'wallet.index.total', methods: 'GET', group: 'auth')]
public function indexTotal(string $id, InputManager $input): ResponseInterface
{
$wallet = $this->walletRepository->findByPKByUserPK((int) $id, (int) $this->user->id);

if (! $wallet instanceof Wallet) {
return $this->response->create(404);
}

$this->chargeRepository->filter($input->query->fetch(['date-from', 'date-to']));

$income = $this->chargeRepository->totalByWalletPK((int) $wallet->id, Charge::TYPE_INCOME);
$expense = $this->chargeRepository->totalByWalletPK((int) $wallet->id, Charge::TYPE_EXPENSE);

return $this->response->json([
'data' => [
'totalAmount' => $this->chargeWalletService->totalByIncomeAndExpense($income, $expense),
'totalIncomeAmount' => $income,
'totalExpenseAmount' => $expense,
],
]);
}
}
36 changes: 0 additions & 36 deletions app/src/Controller/Wallets/TagsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@

namespace App\Controller\Wallets;

use App\Database\Charge;
use App\Database\Tag;
use App\Database\Wallet;
use App\Repository\ChargeRepository;
use App\Repository\TagRepository;
use App\Repository\WalletRepository;
use App\Service\ChargeWalletService;
use App\View\TagsView;
use Psr\Http\Message\ResponseInterface;
use Spiral\Auth\AuthScope;
use Spiral\Http\Request\InputManager;
use Spiral\Http\ResponseWrapper;
use Spiral\Router\Annotation\Route;

Expand All @@ -24,10 +19,8 @@ public function __construct(
AuthScope $auth,
private ResponseWrapper $response,
private WalletRepository $walletRepository,
private ChargeRepository $chargeRepository,
private TagRepository $tagRepository,
private TagsView $tagsView,
private ChargeWalletService $chargeWalletService,
) {
parent::__construct($auth);
}
Expand All @@ -46,35 +39,6 @@ public function list(string $id): ResponseInterface
return $this->tagsView->json($tags);
}

#[Route(route: '/wallets/<walletId>/tags/<tagId>/total', name: 'wallet.tags.total', methods: 'GET', group: 'auth')]
public function total(string $walletId, string $tagId, InputManager $input): ResponseInterface
{
$wallet = $this->walletRepository->findByPKByUserPK((int) $walletId, (int) $this->user->id);

if (! $wallet instanceof Wallet) {
return $this->response->create(404);
}

$tag = $this->tagRepository->findByPKByUsersPK((int) $tagId, $wallet->getUserIDs());

if (! $tag instanceof Tag) {
return $this->response->create(404);
}

$this->chargeRepository->filter($input->query->fetch(['date-from', 'date-to']));

$income = $this->chargeRepository->totalByWalletPKAndTagId((int) $wallet->id, (int) $tag->id, Charge::TYPE_INCOME);
$expense = $this->chargeRepository->totalByWalletPKAndTagId((int) $wallet->id, (int) $tag->id, Charge::TYPE_EXPENSE);

return $this->response->json([
'data' => [
'totalAmount' => $this->chargeWalletService->totalByIncomeAndExpense($income, $expense),
'totalIncomeAmount' => $income,
'totalExpenseAmount' => $expense,
],
]);
}

#[Route(route: '/wallets/<walletId>/tags/find/<query>', name: 'wallet.tags.find', methods: 'GET', group: 'auth')]
public function find(string $walletId, string $query = ''): ResponseInterface
{
Expand Down
81 changes: 81 additions & 0 deletions app/src/Controller/Wallets/TotalController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

declare(strict_types=1);

namespace App\Controller\Wallets;

use App\Database\Charge;
use App\Database\Wallet;
use App\Repository\ChargeRepository;
use App\Repository\WalletRepository;
use App\Service\ChargeWalletService;
use Psr\Http\Message\ResponseInterface;
use Spiral\Auth\AuthScope;
use Spiral\Http\Request\InputManager;
use Spiral\Http\ResponseWrapper;
use Spiral\Router\Annotation\Route;

final class TotalController extends Controller
{
public function __construct(
AuthScope $auth,
private ResponseWrapper $response,
private WalletRepository $walletRepository,
private ChargeRepository $chargeRepository,
private ChargeWalletService $chargeWalletService,
) {
parent::__construct($auth);
}

#[Route(route: '/wallets/<id>/total', name: 'wallet.index.total', methods: 'GET', group: 'auth')]
public function total(string $id, InputManager $input): ResponseInterface
{
$wallet = $this->walletRepository->findByPKByUserPK((int) $id, (int) $this->user->id);

if (! $wallet instanceof Wallet) {
return $this->response->create(404);
}

$this->chargeRepository->filter($input->query->fetch(['date-from', 'date-to']));

$income = $this->chargeRepository->totalByWalletPK((int) $wallet->id, Charge::TYPE_INCOME);
$expense = $this->chargeRepository->totalByWalletPK((int) $wallet->id, Charge::TYPE_EXPENSE);

$response = [
'totalAmount' => $this->chargeWalletService->totalByIncomeAndExpense($income, $expense),
'totalIncomeAmount' => $income,
'totalExpenseAmount' => $expense,
];

$tagIDs = $this->fetchFilteredTagIDs($input);

if (count($tagIDs) > 0) {
$incomePerTag = $this->chargeRepository->totalByWalletPKGroupByTagPKs((int) $wallet->id, $tagIDs, Charge::TYPE_INCOME);
$expensePerTag = $this->chargeRepository->totalByWalletPKGroupByTagPKs((int) $wallet->id, $tagIDs, Charge::TYPE_EXPENSE);
$response['tags'] = $this->mergeGroupedTotal($tagIDs, $incomePerTag, $expensePerTag);
}

return $this->response->json([
'data' => $response,
]);
}

private function mergeGroupedTotal(array $tagIDs, array $income, array $expense): array
{
$data = [];

foreach ($tagIDs as $id) {
if (!array_key_exists($id, $income) && !array_key_exists($id, $expense)) {
continue;
}

$data[] = [
'tagId' => $id,
'totalIncomeAmount' => $income[$id] ?? 0.0,
'totalExpenseAmount' => $expense[$id] ?? 0.0,
];
}

return $data;
}
}
Loading

0 comments on commit 2574fcc

Please sign in to comment.