Skip to content

Commit

Permalink
Merge pull request #64 from cash-track/feature/profile-statistics
Browse files Browse the repository at this point in the history
Feature / Profile Statistics
  • Loading branch information
vokomarov authored Oct 16, 2021
2 parents e4d4c59 + 83f76e9 commit 9426274
Show file tree
Hide file tree
Showing 13 changed files with 739 additions and 337 deletions.
12 changes: 11 additions & 1 deletion .github/workflows/pull.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache composer dependencies
- name: Prepare cache for composer
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
Expand All @@ -48,6 +48,16 @@ jobs:
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Prepare cache for vulnerability database
uses: actions/cache@v2
id: vulnerability-db-cache
with:
path: ~/.vulnerability-db/cache
key: vulnerability-db

- name: Scan packages for vulnerability
uses: symfonycorp/security-checker-action@v2

- name: Setup application
run: |
cp .env.actions .env
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM php:8.0.9-cli
FROM php:8.0.11-cli

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
Expand Down
30 changes: 30 additions & 0 deletions app/src/Controller/AuthAwareController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Controller;

use App\Database\User;
use Spiral\Auth\AuthScope;

abstract class AuthAwareController
{
/**
* @var \App\Database\User
*/
protected User $user;

/**
* ProfileStatisticsController constructor.
*
* @param \Spiral\Auth\AuthScope $auth
*/
public function __construct(AuthScope $auth)
{
$user = $auth->getActor();

if (! $user instanceof User) {
throw new \RuntimeException('Unable to get authenticated user');
}

$this->user = $user;
}
}
88 changes: 88 additions & 0 deletions app/src/Controller/Profile/ProfileStatisticsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace App\Controller\Profile;

use App\Controller\AuthAwareController;
use App\Database\Currency;
use App\Repository\ChargeRepository;
use App\Repository\CurrencyRepository;
use App\Repository\WalletRepository;
use App\Service\Statistics\ProfileStatistics;
use App\View\CurrencyView;
use App\View\WalletsView;
use Doctrine\Common\Collections\ArrayCollection;
use Psr\Http\Message\ResponseInterface;
use Spiral\Http\ResponseWrapper;
use Spiral\Router\Annotation\Route;

class ProfileStatisticsController extends AuthAwareController
{
/**
* @Route(route="/profile/statistics/charges-flow", name="profile.statistics.charges-flow", methods="GET", group="auth")
*
* @param \Spiral\Http\ResponseWrapper $response
* @param \App\Repository\CurrencyRepository $currencyRepository
* @param \App\View\CurrencyView $currencyView
* @param \App\Service\Statistics\ProfileStatistics $statistics
* @return \Psr\Http\Message\ResponseInterface
*/
public function chargesFlow(
ResponseWrapper $response,
CurrencyRepository $currencyRepository,
CurrencyView $currencyView,
ProfileStatistics $statistics,
): ResponseInterface {
$currency = $currencyRepository->findByPK($this->user->defaultCurrencyCode ?? Currency::DEFAULT_CURRENCY_CODE);

if (! $currency instanceof Currency) {
return $response->json([
'message' => 'Unable to find currency.',
], 400);
}

$data = $statistics->getChargeFlow($this->user, $currency);
$data['currency'] = $currencyView->map($currency);

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

/**
* @Route(route="/profile/statistics/counters", name="profile.statistics.counters", methods="GET", group="auth")
*
* @param \Spiral\Http\ResponseWrapper $response
* @param \App\Service\Statistics\ProfileStatistics $statistics
* @return \Psr\Http\Message\ResponseInterface
*/
public function counters(ResponseWrapper $response, ProfileStatistics $statistics): ResponseInterface
{
return $response->json([
'data' => $statistics->getCounters($this->user),
]);
}

/**
* @Route(route="/profile/wallets/latest", name="profile.wallets.latest", methods="GET", group="auth")
*
* @param \App\Repository\WalletRepository $walletRepository
* @param \App\Repository\ChargeRepository $chargeRepository
* @param \App\View\WalletsView $view
* @return \Psr\Http\Message\ResponseInterface
*/
public function walletsLatest(
WalletRepository $walletRepository,
ChargeRepository $chargeRepository,
WalletsView $view
): ResponseInterface {
$wallets = $walletRepository->findAllUnArchivedByUserPKWithLimit($this->user->id);

foreach ($wallets as $wallet) {
$wallet->latestCharges = new ArrayCollection($chargeRepository->findByWalletIDLatest($wallet->id));
}

return $view->json($wallets);
}
}
4 changes: 2 additions & 2 deletions app/src/Database/Charge.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ class Charge

/**
* @Cycle\Column(type = "string(36)", primary = true)
* @var string
* @var string|null
*/
public $id = '';
public $id;

/**
* @Cycle\Column(type = "int", name = "wallet_id")
Expand Down
6 changes: 6 additions & 0 deletions app/src/Database/Wallet.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ class Wallet
*/
public $users;

/**
* @var \Doctrine\Common\Collections\ArrayCollection|null
*/
public ArrayCollection|null $latestCharges = null;

/**
* Wallet constructor.
*/
Expand All @@ -101,5 +106,6 @@ public function __construct()
$this->users = new PivotedCollection();
$this->createdAt = new \DateTimeImmutable();
$this->updatedAt = new \DateTimeImmutable();
$this->latestCharges = new ArrayCollection();
}
}
54 changes: 54 additions & 0 deletions app/src/Repository/ChargeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Repository;

use Cycle\ORM\Select\Repository;
use Spiral\Database\Injection\Parameter;

class ChargeRepository extends Repository
{
Expand All @@ -26,6 +27,24 @@ public function findByWalletId(int $walletId)
return $query->fetchAll();
}

/**
* @param int $walletId
* @param int $limit
* @return \App\Database\Charge[]
*/
public function findByWalletIDLatest(int $walletId, int $limit = 4): array
{
/** @var \App\Database\Charge[] $charges */
$charges = $this->select()
->load('user')
->where('wallet_id', $walletId)
->orderBy('created_at', 'DESC')
->limit($limit)
->fetchAll();

return $charges;
}

/**
* @param string $chargeId
* @param int $walletId
Expand All @@ -51,4 +70,39 @@ public function totalByWalletPK(int $walletId, string $type = null): float

return (float) $query->sum('amount');
}

/**
* @param string $type
* @param array $walletIDs
* @param \DateTimeImmutable|null $dateFrom
* @return float
*/
public function sumTotalByTypeByCurrencyFromDate(string $type, array $walletIDs, \DateTimeImmutable $dateFrom = null): float
{
$query = $this->select()
->where('type', $type)
->where('wallet_id', 'in', new Parameter($walletIDs));

if ($dateFrom !== null) {
$query = $query->where('created_at', '>=', $dateFrom);
}

return (float) $query->sum('amount');
}

/**
* @param int $userID
* @param string|null $type
* @return int
*/
public function countAllByUserPKByType(int $userID, string $type = null): int
{
$query = $this->select()->where('user_id', $userID);

if ($type !== null) {
$query = $query->where('type', $type);
}

return $query->count();
}
}
48 changes: 48 additions & 0 deletions app/src/Repository/WalletRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace App\Repository;

use App\Database\Currency;
use Cycle\ORM\Select;
use Cycle\ORM\Select\Repository;

Expand Down Expand Up @@ -34,6 +35,53 @@ public function findAllByUserPKByArchived(int $userID, bool $isArchived = false)
return $wallets;
}

/**
* @param int $userID
* @param int $limit
* @return \App\Database\Wallet[]
*/
public function findAllUnArchivedByUserPKWithLimit(int $userID, int $limit = 4): array
{
/** @var \App\Database\Wallet[] $wallets */
$wallets = $this->allByUserPK($userID)->where('is_archived', false)->limit($limit)->fetchAll();

return $wallets;
}

/**
* @param int $userID
* @param string $currencyCode
* @return \App\Database\Wallet[]
*/
public function findAllByUserPKByCurrencyCode(int $userID, string $currencyCode = Currency::DEFAULT_CURRENCY_CODE): array
{
/** @var \App\Database\Wallet[] $wallets */
$wallets = $this->select()
->where('users.id', $userID)
->where('default_currency_code', $currencyCode)
->fetchAll();

return $wallets;
}

/**
* @param int $userID
* @return int
*/
public function countAllByUserPK(int $userID): int
{
return $this->allByUserPK($userID)->count();
}

/**
* @param int $userID
* @return int
*/
public function countArchivedByUserPK(int $userID): int
{
return $this->allByUserPK($userID)->where('is_archived', true)->count();
}

/**
* @param int $userID
* @return \Cycle\ORM\Select
Expand Down
Loading

0 comments on commit 9426274

Please sign in to comment.