ReportService::getSessionReport()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 43
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 33
nc 1
nop 1
dl 0
loc 43
rs 9.392
c 3
b 0
f 0
1
<?php
2
3
namespace Siak\Tontine\Service\Report;
4
5
use Siak\Tontine\Model\Loan;
6
use Siak\Tontine\Model\Round;
7
use Siak\Tontine\Model\Session;
8
use Siak\Tontine\Service\LocaleService;
9
use Siak\Tontine\Service\Meeting\Credit\DebtCalculator;
10
use Siak\Tontine\Service\Meeting\Saving\FundService;
11
use Siak\Tontine\Service\Meeting\Saving\ProfitService;
12
use Siak\Tontine\Service\Meeting\Session\SummaryService;
13
use Siak\Tontine\Service\Report\RoundService;
14
15
use function compact;
16
17
class ReportService
18
{
19
    /**
20
     * @param LocaleService $localeService
21
     * @param SessionService $sessionService
22
     * @param MemberService $memberService
23
     * @param RoundService $roundService
24
     * @param FundService $fundService
25
     * @param SummaryService $summaryService
26
     * @param ProfitService $profitService
27
     * @param DebtCalculator $debtCalculator
28
     */
29
    public function __construct(protected LocaleService $localeService,
30
        protected SessionService $sessionService,
31
        protected MemberService $memberService, protected RoundService $roundService,
32
        protected FundService $fundService, protected SummaryService $summaryService,
33
        protected ProfitService $profitService, protected DebtCalculator $debtCalculator)
34
    {}
35
36
    /**
37
     * @param Session $session
38
     *
39
     * @return array
40
     */
41
    public function getSessionReport(Session $session): array
42
    {
43
        $guild = $session->round->guild;
44
        [$country] = $this->localeService->getNameFromGuild($guild);
45
46
        return [
47
            'guild' => $guild,
48
            'session' => $session,
49
            'country' => $country,
50
            'deposits' => [
51
                'session' => $session,
52
                'receivables' => $this->memberService->getReceivables($session),
53
                'pools' => $this->sessionService->getReceivables($session),
54
            ],
55
            'remitments' => [
56
                'session' => $session,
57
                'payables' => $this->memberService->getPayables($session),
58
                'pools' => $this->sessionService->getPayables($session),
59
                'auctions' => $this->memberService->getAuctions($session),
60
            ],
61
            'bills' => [
62
                'bills' => $this->memberService->getBills($session),
63
                'charges' => [
64
                    'session' => $this->sessionService->getSessionCharges($session),
65
                    'total' => $this->sessionService->getTotalCharges($session),
66
                ],
67
            ],
68
            'loans' => [
69
                'loans' => $this->memberService->getLoans($session),
70
                'total' => $this->sessionService->getLoan($session),
71
            ],
72
            'refunds' => [
73
                'refunds' => $this->memberService->getRefunds($session),
74
                'total' => $this->sessionService->getRefund($session),
75
            ],
76
            'savings' => [
77
                'savings' => $this->memberService->getSavings($session),
78
                'funds' => $this->fundService->getSessionFundList($session),
79
                'total' => $this->sessionService->getSaving($session),
80
            ],
81
            'outflows' => [
82
                'outflows' => $this->memberService->getOutflows($session),
83
                'total' => $this->sessionService->getOutflow($session),
84
            ],
85
        ];
86
    }
87
88
    /**
89
     * @param Session $session
90
     *
91
     * @return array
92
     */
93
    public function getSessionEntry(Session $session): array
94
    {
95
        $guild = $session->round->guild;
96
        [$country] = $this->localeService->getNameFromGuild($guild);
97
98
        return [
99
            'guild' => $guild,
100
            'session' => $session,
101
            'country' => $country,
102
            'deposits' => [
103
                'session' => $session,
104
                'receivables' => $this->memberService->getReceivables($session),
105
                'pools' => $this->sessionService->getReceivables($session),
106
            ],
107
            'remitments' => [
108
                'session' => $session,
109
                'payables' => $this->memberService->getPayables($session),
110
                'pools' => $this->sessionService->getPayables($session),
111
            ],
112
            'bills' => [
113
                'bills' => $this->memberService->getBills($session),
114
                'charges' => $session->round->charges()->fixed()->get(),
115
            ],
116
        ];
117
    }
118
119
    /**
120
     * @param Session $session
121
     *
122
     * @return array
123
     */
124
    public function getSavingsReport(Session $session): array
125
    {
126
        $guild = $session->round->guild;
127
        [$country] = $this->localeService->getNameFromGuild($guild);
128
        $funds = $this->fundService->getSessionFunds($session);
129
        $profits = $session->funds->keyBy('id')->map(fn($fund) => $fund->profit_amount);
130
131
        $funds = $funds
132
            ->map(fn($fund) => [
133
                'fund' => $fund,
134
                'distribution' => $this->profitService->getDistribution($session,
135
                    $fund, $profits[$fund->id] ?? 0),
136
            ])
137
            ->filter(fn($report) => $report['distribution']->savings->count() > 0);
138
139
        return compact('guild', 'session', 'country', 'funds');
140
    }
141
142
    /**
143
     * @param Loan $loan
144
     * @param Session $session
145
     *
146
     * @return void
147
     */
148
    private function setDebtAmount(Loan $loan, Session $session)
149
    {
150
        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...
151
        {
152
            $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...
153
        }
154
    }
155
156
    /**
157
     * @param Session $session
158
     *
159
     * @return array
160
     */
161
    public function getCreditReport(Session $session): array
162
    {
163
        $round = $session->round;
164
        $guild = $round->guild;
165
        [$country, $currency] = $this->localeService->getNameFromGuild($guild);
166
167
        $funds = $this->fundService->getSessionFunds($session)
168
            ->each(function($fund) use($session) {
169
                $sessionIds = $this->fundService->getFundSessionIds($fund, $session);
170
                $fund->loans = Loan::select('loans.*')
171
                    ->join('sessions', 'loans.session_id', '=', 'sessions.id')
172
                    ->where(fn($query) => $query->where('fund_id', $fund->id))
173
                    ->whereIn('loans.session_id', $sessionIds)
174
                    ->with(['member', 'session', 'debts.refund', 'debts.refund.session',
175
                        'debts.partial_refunds' => function($query) use($sessionIds) {
176
                            $query->whereIn('session_id', $sessionIds);
177
                        },
178
                        'debts.partial_refunds.session'])
179
                    ->orderBy('sessions.day_date')
0 ignored issues
show
Bug introduced by
'sessions.day_date' 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

179
                    ->orderBy(/** @scrutinizer ignore-type */ 'sessions.day_date')
Loading history...
180
                    ->get()
181
                    ->each(fn(Loan $loan) => $this->setDebtAmount($loan, $session))
182
                    ->groupBy('member.id');
183
            })
184
            ->filter(fn($fund) => $fund->loans->count() > 0);
185
186
        return compact('guild', 'round', 'session', 'country', 'currency', 'funds');
187
    }
188
189
    /**
190
     * @param Round $round
191
     *
192
     * @return array
193
     */
194
    public function getRoundReport(Round $round): array
195
    {
196
        [$country, $currency] = $this->localeService->getNameFromGuild($round->guild);
197
198
        $figures = $this->summaryService->getFigures($round);
199
      
200
        $sessions = $this->roundService->getRoundSessions($round);
201
        $sessionIds = $sessions->pluck('id');
202
        $balance = [
203
            'sessions' => $sessions,
204
            'settlements' => $this->roundService->getSettlementAmounts($sessionIds),
205
            'loans' => $this->roundService->getLoanAmounts($sessionIds),
206
            'refunds' => $this->roundService->getRefundAmounts($sessionIds),
207
            'savings' => $this->roundService->getSavingAmounts($sessionIds),
208
            'outflows' => $this->roundService->getOutflowAmounts($sessionIds),
209
            'pools' => $this->summaryService->getPoolsBalance($figures),
210
        ];
211
212
        return compact('round', 'country', 'currency', 'figures', 'balance');
213
    }
214
}
215