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

ReportService::getSessionReport()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 43
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 0 Features 0
Metric Value
cc 1
eloc 33
nc 1
nop 1
dl 0
loc 43
rs 9.392
c 8
b 0
f 0
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