Passed
Push — main ( 6510e5...eb2c28 )
by Thierry
06:37
created

ReportService::getFundSavingsReport()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
nc 1
nop 3
dl 0
loc 11
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Siak\Tontine\Service\Report;
4
5
use Illuminate\Support\Collection;
6
use Siak\Tontine\Model\Fund;
7
use Siak\Tontine\Model\Loan;
8
use Siak\Tontine\Model\Round;
9
use Siak\Tontine\Model\Session;
10
use Siak\Tontine\Service\LocaleService;
11
use Siak\Tontine\Service\TenantService;
12
use Siak\Tontine\Service\Meeting\Credit\DebtCalculator;
13
use Siak\Tontine\Service\Meeting\Saving\ClosingService;
14
use Siak\Tontine\Service\Meeting\Saving\ProfitService;
15
use Siak\Tontine\Service\Meeting\SummaryService;
16
use Siak\Tontine\Service\Report\RoundService;
17
use Siak\Tontine\Service\Tontine\FundService;
18
19
use function compact;
20
21
class ReportService
22
{
23
    /**
24
     * @param LocaleService $localeService
25
     * @param TenantService $tenantService
26
     * @param SessionService $sessionService
27
     * @param MemberService $memberService
28
     * @param RoundService $roundService
29
     * @param FundService $fundService
30
     * @param ClosingService $closingService
31
     * @param SummaryService $summaryService
32
     * @param ProfitService $profitService
33
     */
34
    public function __construct(protected LocaleService $localeService,
35
        protected TenantService $tenantService, protected SessionService $sessionService,
36
        protected MemberService $memberService, protected RoundService $roundService,
37
        protected FundService $fundService, protected ClosingService $closingService,
38
        protected SummaryService $summaryService, protected ProfitService $profitService,
39
        protected DebtCalculator $debtCalculator)
40
    {}
41
42
    /**
43
     * @param Session $session
44
     *
45
     * @return array
46
     */
47
    public function getSessionReport(Session $session): array
48
    {
49
        $tontine = $this->tenantService->tontine();
50
        [$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

50
        [$country] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
51
52
        return [
53
            'tontine' => $tontine,
54
            'session' => $session,
55
            'country' => $country,
56
            'deposits' => [
57
                'session' => $session,
58
                'receivables' => $this->memberService->getReceivables($session),
59
                'pools' => $this->sessionService->getReceivables($session),
60
            ],
61
            'remitments' => [
62
                'session' => $session,
63
                'payables' => $this->memberService->getPayables($session),
64
                'pools' => $this->sessionService->getPayables($session),
65
                'auctions' => $this->memberService->getAuctions($session),
66
            ],
67
            'bills' => [
68
                'bills' => $this->memberService->getBills($session),
69
                'charges' => [
70
                    'session' => $this->sessionService->getSessionCharges($session),
71
                    'total' => $this->sessionService->getTotalCharges($session),
72
                ],
73
            ],
74
            'loans' => [
75
                'loans' => $this->memberService->getLoans($session),
76
                'total' => $this->sessionService->getLoan($session),
77
            ],
78
            'refunds' => [
79
                'refunds' => $this->memberService->getRefunds($session),
80
                'total' => $this->sessionService->getRefund($session),
81
            ],
82
            'savings' => [
83
                'savings' => $this->memberService->getSavings($session),
84
                'funds' => $this->fundService->getFundList(),
85
                'total' => $this->sessionService->getSaving($session),
86
            ],
87
            'disbursements' => [
88
                'disbursements' => $this->memberService->getDisbursements($session),
89
                'total' => $this->sessionService->getDisbursement($session),
90
            ],
91
        ];
92
    }
93
94
    /**
95
     * @param Session $session
96
     *
97
     * @return array
98
     */
99
    public function getSessionEntry(Session $session): array
100
    {
101
        $tontine = $this->tenantService->tontine();
102
        [$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

102
        [$country] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
103
104
        return [
105
            'tontine' => $tontine,
106
            'session' => $session,
107
            'country' => $country,
108
            'deposits' => [
109
                'session' => $session,
110
                'receivables' => $this->memberService->getReceivables($session),
111
                'pools' => $this->sessionService->getReceivables($session),
112
            ],
113
            'remitments' => [
114
                'session' => $session,
115
                'payables' => $this->memberService->getPayables($session),
116
                'pools' => $this->sessionService->getPayables($session),
117
            ],
118
            'bills' => [
119
                'bills' => $this->memberService->getBills($session),
120
                'charges' => $this->tenantService->tontine()->charges()
121
                    ->active()->fixed()->get(),
122
            ],
123
        ];
124
    }
125
126
    /**
127
     * @param Session $session
128
     *
129
     * @return Collection
130
     */
131
    private function getSessionProfitAmounts(Session $session): Collection
132
    {
133
        $closings = $this->closingService->getRoundClosings($session);
134
135
        return $closings->keyBy('fund_id')->map(fn($closing) => $closing->profit);
136
    }
137
138
    /**
139
     * @param Session $session
140
     *
141
     * @return array
142
     */
143
    public function getSavingsReport(Session $session): array
144
    {
145
        $tontine = $this->tenantService->tontine();
146
        [$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

146
        [$country] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
147
        $funds = $this->fundService->getActiveFunds();
148
        $profits = $this->getSessionProfitAmounts($session);
149
150
        $funds = $funds
151
            ->map(fn($fund) => [
152
                'fund' => $fund,
153
                'distribution' => $this->profitService->getDistribution($session,
154
                    $fund, $profits[$fund->id] ?? 0),
155
            ])
156
            ->filter(fn($report) => $report['distribution']->savings->count() > 0);
157
158
        return compact('tontine', 'session', 'country', 'funds');
159
    }
160
161
    /**
162
     * @param Loan $loan
163
     * @param Session $session
164
     *
165
     * @return void
166
     */
167
    private function setDebtAmount(Loan $loan, Session $session)
168
    {
169
        if(($debt = $loan->i_debt) !== null)
0 ignored issues
show
Bug introduced by
The property i_debt does not seem to exist on Siak\Tontine\Model\Loan. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
170
        {
171
            $loan->iDebtAmount = $this->debtCalculator->getDebtAmount($debt, $session);
0 ignored issues
show
Bug introduced by
The property iDebtAmount does not seem to exist on Siak\Tontine\Model\Loan. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
172
        }
173
    }
174
175
    /**
176
     * @param Session $session
177
     *
178
     * @return array
179
     */
180
    public function getCreditReport(Session $session): array
181
    {
182
        $round = $session->round;
183
        $tontine = $this->tenantService->tontine();
184
        [$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

184
        [$country, $currency] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
185
186
        $funds = $this->fundService->getActiveFunds()
187
            ->each(function($fund) use($session) {
188
                $sessionIds = $this->fundService->getFundSessionIds($session, $fund);
189
                $fund->loans = Loan::select('loans.*')
190
                    ->join('sessions', 'loans.session_id', '=', 'sessions.id')
191
                    ->where(fn($query) => $query->where('fund_id', $fund->id))
192
                    ->whereIn('loans.session_id', $sessionIds)
193
                    ->with(['member', 'session', 'debts.refund', 'debts.refund.session',
194
                        'debts.partial_refunds' => function($query) use($sessionIds) {
195
                            $query->whereIn('session_id', $sessionIds);
196
                        },
197
                        'debts.partial_refunds.session'])
198
                    ->orderBy('sessions.start_at')
0 ignored issues
show
Bug introduced by
'sessions.start_at' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderBy(). ( Ignorable by Annotation )

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

198
                    ->orderBy(/** @scrutinizer ignore-type */ 'sessions.start_at')
Loading history...
199
                    ->get()
200
                    ->each(fn(Loan $loan) => $this->setDebtAmount($loan, $session))
201
                    ->groupBy('member.id');
202
            })
203
            ->filter(fn($fund) => $fund->loans->count() > 0);
204
205
        return compact('tontine', 'round', 'session', 'country', 'currency', 'funds');
206
    }
207
208
    /**
209
     * @param Round $round
210
     *
211
     * @return array
212
     */
213
    public function getRoundReport(Round $round): array
214
    {
215
        $tontine = $this->tenantService->tontine();
216
        [$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

216
        [$country, $currency] = $this->localeService->getNameFromTontine(/** @scrutinizer ignore-type */ $tontine);
Loading history...
217
218
        $figures = $this->summaryService->getFigures($round);
219
      
220
        $sessions = $this->roundService->getRoundSessions($round);
221
        $sessionIds = $sessions->pluck('id');
222
        $balance = [
223
            'sessions' => $sessions,
224
            'settlements' => $this->roundService->getSettlementAmounts($sessionIds),
225
            'loans' => $this->roundService->getLoanAmounts($sessionIds),
226
            'refunds' => $this->roundService->getRefundAmounts($sessionIds),
227
            'savings' => $this->roundService->getSavingAmounts($sessionIds),
228
            'disbursements' => $this->roundService->getDisbursementAmounts($sessionIds),
229
            'pools' => $this->summaryService->getPoolsBalance($figures),
230
        ];
231
232
        return compact('tontine', 'round', 'country', 'currency', 'figures', 'balance');
233
    }
234
}
235