Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
50.00% covered (danger)
50.00%
17 / 34
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
AdminService
50.00% covered (danger)
50.00%
17 / 34
57.14% covered (warning)
57.14%
4 / 7
38.50
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStats
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getInvestorsList
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 getInvestorDetail
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getInvestorAllocations
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getAllTransactions
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
 getAumHistory
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace App\Domain\Admin\Service;
6
7use App\Domain\Account\Data\BalanceHistoryPointData;
8use App\Domain\Admin\Data\AdminStatsData;
9use App\Domain\Admin\Repository\AdminRepository;
10use App\Domain\Exception\NotFoundException;
11
12use function ceil;
13use function max;
14use function min;
15
16/**
17 * Service for admin operations.
18 */
19final class AdminService
20{
21    private AdminRepository $repository;
22
23    public function __construct(AdminRepository $repository)
24    {
25        $this->repository = $repository;
26    }
27
28    /**
29     * Get platform statistics.
30     */
31    public function getStats(): AdminStatsData
32    {
33        return $this->repository->getStats();
34    }
35
36    /**
37     * Get paginated investors list.
38     *
39     * @param int $page
40     * @param int $limit
41     * @param string|null $search
42     * @param string|null $kycStatus
43     * @param string|null $status
44     *
45     * @return array{investors: array<int, array<string, mixed>>, total: int, page: int, limit: int}
46     */
47    public function getInvestorsList(
48        int $page = 1,
49        int $limit = 20,
50        ?string $search = null,
51        ?string $kycStatus = null,
52        ?string $status = null,
53    ): array {
54        // Validate pagination
55        if ($page < 1) {
56            $page = 1;
57        }
58        if ($limit < 1 || $limit > 100) {
59            $limit = 20;
60        }
61
62        $result = $this->repository->getInvestorsList($page, $limit, $search, $kycStatus, $status);
63
64        return [
65            'investors' => $result['investors'],
66            'total' => $result['total'],
67            'page' => $page,
68            'limit' => $limit,
69        ];
70    }
71
72    /**
73     * Get detailed investor information.
74     *
75     * @param int $investorId
76     *
77     * @throws NotFoundException If investor not found
78     *
79     * @return array<string, mixed>
80     */
81    public function getInvestorDetail(int $investorId): array
82    {
83        $investor = $this->repository->getInvestorDetail($investorId);
84
85        if ($investor === null) {
86            throw new NotFoundException('Investor not found');
87        }
88
89        return $investor;
90    }
91
92    /**
93     * Get current allocations for an investor.
94     *
95     * @param int $investorId
96     * @return array<int, array<string, mixed>>
97     */
98    public function getInvestorAllocations(int $investorId): array
99    {
100        return $this->repository->getInvestorAllocations($investorId);
101    }
102
103    /**
104     * Get all transactions platform-wide (paginated, filterable).
105     *
106     * @param int $page
107     * @param int $limit
108     * @param string|null $type
109     * @param string|null $search
110     * @param string|null $startDate
111     * @param string|null $endDate
112     *
113     * @return array{data: array<int, array<string, mixed>>, total: int, page: int, limit: int}
114     */
115    public function getAllTransactions(
116        int $page = 1,
117        int $limit = 25,
118        ?string $type = null,
119        ?string $search = null,
120        ?string $startDate = null,
121        ?string $endDate = null,
122    ): array {
123        if ($page < 1) {
124            $page = 1;
125        }
126        if ($limit < 1 || $limit > 100) {
127            $limit = 25;
128        }
129
130        $result = $this->repository->getAllTransactions($page, $limit, $type, $search, $startDate, $endDate);
131
132        return [
133            'data' => $result['data'],
134            'total' => $result['total'],
135            'page' => $page,
136            'limit' => $limit,
137        ];
138    }
139
140    /**
141     * Get platform-wide AUM balance history for charting.
142     *
143     * @return BalanceHistoryPointData[]
144     */
145    public function getAumHistory(): array
146    {
147        $rows = $this->repository->getAumHistory();
148
149        return array_map(
150            static fn(array $row): BalanceHistoryPointData => new BalanceHistoryPointData($row),
151            $rows,
152        );
153    }
154}