Passed
Push — main ( aad503...73e694 )
by Thierry
08:30
created

ReportService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
c 2
b 0
f 0
nc 1
nop 9
dl 0
loc 6
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Siak\Tontine\Service\Report;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Collection;
8
use Siak\Tontine\Model\Fund;
9
use Siak\Tontine\Model\Loan;
10
use Siak\Tontine\Model\Round;
11
use Siak\Tontine\Model\Session;
12
use Siak\Tontine\Service\LocaleService;
13
use Siak\Tontine\Service\TenantService;
14
use Siak\Tontine\Service\Meeting\Saving\SavingService;
15
use Siak\Tontine\Service\Meeting\Saving\ProfitService;
16
use Siak\Tontine\Service\Meeting\SummaryService;
17
use Siak\Tontine\Service\Report\RoundService;
18
use Siak\Tontine\Service\Tontine\FundService;
19
20
use function collect;
21
use function compact;
22
23
class ReportService
24
{
25
    /**
26
     * @param LocaleService $localeService
27
     * @param TenantService $tenantService
28
     * @param SessionService $sessionService
29
     * @param MemberService $memberService
30
     * @param RoundService $roundService
31
     * @param FundService $fundService
32
     * @param SavingService $savingService
33
     * @param SummaryService $summaryService
34
     * @param ProfitService $profitService
35
     */
36
    public function __construct(protected LocaleService $localeService,
37
        protected TenantService $tenantService, protected SessionService $sessionService,
38
        protected MemberService $memberService, protected RoundService $roundService,
39
        protected FundService $fundService, protected SavingService $savingService,
40
        protected SummaryService $summaryService, protected ProfitService $profitService)
41
    {}
42
43
    /**
44
     * @param Session $session
45
     * @param Collection $fundIds
46
     *
47
     * @return array
48
     */
49
    private function getFundClosings(Session $session, Collection $fundIds): array
50
    {
51
        $closings = $this->savingService->getSessionClosings($session);
52
        return Arr::only($closings, $fundIds->all());
53
    }
54
55
    /**
56
     * @param Session $session
57
     *
58
     * @return array
59
     */
60
    public function getClosings(Session $session): array
61
    {
62
        $closings = $this->savingService->getSessionClosings($session);
63
        $funds = $this->fundService->getFundList();
64
        return Arr::only($closings, $funds->keys()->all());
65
    }
66
67
    /**
68
     * @param Session $session
69
     *
70
     * @return array
71
     */
72
    public function getSessionReport(Session $session): array
73
    {
74
        $tontine = $this->tenantService->tontine();
75
        [$country] = $this->localeService->getNameFromTontine($tontine);
0 ignored issues
show
Bug introduced by
It seems like $tontine can also be of type null; however, parameter $tontine of Siak\Tontine\Service\Loc...e::getNameFromTontine() does only seem to accept Siak\Tontine\Model\Tontine, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
        [$country] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
76
77
        return [
78
            'tontine' => $tontine,
79
            'session' => $session,
80
            'country' => $country,
81
            'deposits' => [
82
                'session' => $session,
83
                'receivables' => $this->memberService->getReceivables($session),
84
                'pools' => $this->sessionService->getReceivables($session),
85
            ],
86
            'remitments' => [
87
                'session' => $session,
88
                'payables' => $this->memberService->getPayables($session),
89
                'pools' => $this->sessionService->getPayables($session),
90
                'auctions' => $this->memberService->getAuctions($session),
91
            ],
92
            'bills' => [
93
                'bills' => $this->memberService->getBills($session),
94
                'charges' => [
95
                    'session' => $this->sessionService->getSessionCharges($session),
96
                    'total' => $this->sessionService->getTotalCharges($session),
97
                ],
98
            ],
99
            'loans' => [
100
                'loans' => $this->memberService->getLoans($session),
101
                'total' => $this->sessionService->getLoan($session),
102
            ],
103
            'refunds' => [
104
                'refunds' => $this->memberService->getRefunds($session),
105
                'total' => $this->sessionService->getRefund($session),
106
            ],
107
            'savings' => [
108
                'savings' => $this->memberService->getSavings($session),
109
                'funds' => $this->fundService->getFundList(),
110
                'total' => $this->sessionService->getSaving($session),
111
            ],
112
            'disbursements' => [
113
                'disbursements' => $this->memberService->getDisbursements($session),
114
                'total' => $this->sessionService->getDisbursement($session),
115
            ],
116
        ];
117
    }
118
119
    /**
120
     * @param Session $session
121
     *
122
     * @return array
123
     */
124
    public function getSessionEntry(Session $session): array
125
    {
126
        $tontine = $this->tenantService->tontine();
127
        [$country] = $this->localeService->getNameFromTontine($tontine);
0 ignored issues
show
Bug introduced by
It seems like $tontine can also be of type null; however, parameter $tontine of Siak\Tontine\Service\Loc...e::getNameFromTontine() does only seem to accept Siak\Tontine\Model\Tontine, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

127
        [$country] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
128
129
        return [
130
            'tontine' => $tontine,
131
            'session' => $session,
132
            'country' => $country,
133
            'deposits' => [
134
                'session' => $session,
135
                'receivables' => $this->memberService->getReceivables($session),
136
                'pools' => $this->sessionService->getReceivables($session),
137
            ],
138
            'remitments' => [
139
                'session' => $session,
140
                'payables' => $this->memberService->getPayables($session),
141
                'pools' => $this->sessionService->getPayables($session),
142
            ],
143
            'bills' => [
144
                'bills' => $this->memberService->getBills($session),
145
                'charges' => $this->tenantService->tontine()->charges()
146
                    ->active()->fixed()->get(),
147
            ],
148
        ];
149
    }
150
151
    /**
152
     * @param Session $session
153
     * @param int $profitAmount
154
     * @param string $fund
155
     * @param int $fundId
156
     *
157
     * @return array
158
     */
159
    private function getFundSavings(Session $session, int $profitAmount,
160
        string $name, int $fundId): array
161
    {
162
        $savings = $this->profitService->getDistributions($session, $fundId, $profitAmount);
163
        $partUnitValue = $this->profitService->getPartUnitValue($savings);
164
        $distributionSum = $savings->sum('distribution');
165
        $distributionCount = $savings->filter(fn($saving) => $saving->distribution > 0)->count();
166
167
        return compact('name', 'savings', 'profitAmount', 'partUnitValue',
168
            'distributionSum', 'distributionCount');
169
    }
170
171
    /**
172
     * @param Session $session
173
     *
174
     * @return array
175
     */
176
    public function getSavingsReport(Session $session): array
177
    {
178
        $tontine = $this->tenantService->tontine();
179
        [$country] = $this->localeService->getNameFromTontine($tontine);
0 ignored issues
show
Bug introduced by
It seems like $tontine can also be of type null; however, parameter $tontine of Siak\Tontine\Service\Loc...e::getNameFromTontine() does only seem to accept Siak\Tontine\Model\Tontine, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

179
        [$country] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
180
        $funds = $this->fundService->getFundList();
181
        $closings = $this->getFundClosings($session, $funds->keys());
182
183
        $funds = $funds
184
            ->map(fn($name, $fundId) => $this->getFundSavings($session,
185
                $closings[$fundId] ?? 0, $name, $fundId))
186
            ->filter(fn($fund) => $fund['savings']->count() > 0);
187
188
        return compact('tontine', 'session', 'country', 'funds');
189
    }
190
191
    /**
192
     * @param Round $round
193
     *
194
     * @return array
195
     */
196
    public function getRoundReport(Round $round): array
197
    {
198
        $tontine = $this->tenantService->tontine();
199
        [$country, $currency] = $this->localeService->getNameFromTontine($tontine);
0 ignored issues
show
Bug introduced by
It seems like $tontine can also be of type null; however, parameter $tontine of Siak\Tontine\Service\Loc...e::getNameFromTontine() does only seem to accept Siak\Tontine\Model\Tontine, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

199
        [$country, $currency] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
200
201
        $pools = $this->summaryService->getFigures($round);
202
        $sessions = $round->sessions()->orderBy('start_at', 'asc')->get();
203
        // Sessions with data
204
        $sessionIds = $sessions->filter(function($session) {
205
            return $session->status === Session::STATUS_CLOSED ||
206
                $session->status === Session::STATUS_OPENED;
207
        })->pluck('id');
208
        $amounts = [
209
            'sessions' => $sessions,
210
            'auctions' => $this->roundService->getAuctionAmounts($sessionIds),
211
            'settlements' => $this->roundService->getSettlementAmounts($sessionIds),
212
            'loans' => $this->roundService->getLoanAmounts($sessionIds),
213
            'refunds' => $this->roundService->getRefundAmounts($sessionIds),
214
            'savings' => $this->roundService->getSavingAmounts($sessionIds),
215
            'disbursements' => $this->roundService->getDisbursementAmounts($sessionIds),
216
        ];
217
218
        return compact('tontine', 'round', 'country', 'currency', 'pools', 'amounts');
219
    }
220
221
    /**
222
     * @param Round $round
223
     *
224
     * @return Collection
225
     */
226
    private function getCreditReportFunds(Round $round): Collection
227
    {
228
        if(!($session = $round->sessions()->orderByDesc('start_at')->first()))
229
        {
230
            return collect();
231
        }
232
233
        return $this->fundService->getActiveFunds()
234
            ->each(function($fund) use($session) {
235
                $sessions = $this->profitService->getFundSessions($session, $fund->id);
236
                $fund->loans = Loan::select('loans.*')
237
                    ->join('sessions', 'loans.session_id', '=', 'sessions.id')
238
                    ->whereIn('session_id', $sessions->pluck('id'))
239
                    ->when($fund->id > 0, fn(Builder $query) =>
240
                        $query->where('fund_id', $fund->id))
241
                    ->when($fund->id === 0, fn(Builder $query) =>
242
                        $query->whereNull('fund_id'))
243
                    ->with(['member', 'session', 'debts.refund', 'debts.refund.session',
244
                        'debts.partial_refunds', 'debts.partial_refunds.session'])
245
                    ->orderBy('sessions.start_at')
246
                    ->get();
247
            })
248
            ->filter(fn($fund) => $fund->loans->count() > 0);
249
    }
250
251
    /**
252
     * @param Round $round
253
     *
254
     * @return array
255
     */
256
    public function getCreditReport(Round $round): array
257
    {
258
        $tontine = $this->tenantService->tontine();
259
        [$country, $currency] = $this->localeService->getNameFromTontine($tontine);
0 ignored issues
show
Bug introduced by
It seems like $tontine can also be of type null; however, parameter $tontine of Siak\Tontine\Service\Loc...e::getNameFromTontine() does only seem to accept Siak\Tontine\Model\Tontine, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

259
        [$country, $currency] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
260
        $funds = $this->getCreditReportFunds($round);
261
262
        return compact('tontine', 'round', 'country', 'currency', 'funds');
263
    }
264
}
265