Passed
Push — main ( 656b91...db5ad9 )
by Thierry
15:24
created

FundService::getDefaultFund()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Siak\Tontine\Service\Tontine;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Relations\Relation;
7
use Illuminate\Support\Collection;
8
use Siak\Tontine\Model\Fund;
9
use Siak\Tontine\Model\Session;
10
use Siak\Tontine\Service\TenantService;
11
12
use function trans;
13
14
class FundService
15
{
16
    /**
17
     * @param TenantService $tenantService
18
     */
19
    public function __construct(protected TenantService $tenantService)
20
    {}
21
22
    /**
23
     * Get the default fund.
24
     *
25
     * @return Fund
26
     */
27
    public function getDefaultFund(): Fund
28
    {
29
        $defaultFund = $this->tenantService->tontine()->default_fund;
30
        $defaultFund->title = trans('tontine.fund.labels.default');
31
        return $defaultFund;
32
    }
33
34
    /**
35
     * Get all active funds, included the default one.
36
     *
37
     * @return Collection
38
     */
39
    public function getActiveFunds(): Collection
40
    {
41
        return $this->tenantService->tontine()->funds()->active()
42
            ->get()
43
            ->prepend($this->getDefaultFund());
44
    }
45
46
    /**
47
     * Get a list of funds for the dropdown select component.
48
     *
49
     * @return Collection
50
     */
51
    public function getFundList(): Collection
52
    {
53
        return $this->getActiveFunds()->pluck('title', 'id');
54
    }
55
56
    /**
57
     * Get a paginated list of funds.
58
     *
59
     * @param int $page
60
     *
61
     * @return Collection
62
     */
63
    public function getFunds(int $page = 0): Collection
64
    {
65
        return $this->tenantService->tontine()->funds()
66
            ->page($page, $this->tenantService->getLimit())
67
            ->get();
68
    }
69
70
    /**
71
     * Get the number of funds.
72
     *
73
     * @return int
74
     */
75
    public function getFundCount(): int
76
    {
77
        return $this->tenantService->tontine()->funds()->count();
78
    }
79
80
    /**
81
     * Get a single fund.
82
     *
83
     * @param int $fundId    The fund id
84
     * @param bool $onlyActive
85
     * @param bool $withDefault
86
     *
87
     * @return Fund|null
88
     */
89
    public function getFund(int $fundId, bool $onlyActive = false, bool $withDefault = false): ?Fund
90
    {
91
        if($withDefault && $fundId === $this->tenantService->tontine()->default_fund->id)
92
        {
93
            return $this->getDefaultFund();
94
        }
95
        return $this->tenantService->tontine()->funds()
96
            ->when($onlyActive, fn(Builder $query) => $query->active())
97
            ->find($fundId);
98
    }
99
100
    /**
101
     * @param Fund $fund
102
     *
103
     * @return string
104
     */
105
    public function getFundTitle(Fund $fund): string
106
    {
107
        return $fund->id === $this->tenantService->tontine()->default_fund->id ?
108
            $this->getDefaultFund()->title : $fund->title;
109
    }
110
111
    /**
112
     * Add new fund.
113
     *
114
     * @param array $values
115
     *
116
     * @return bool
117
     */
118
    public function createFund(array $values): bool
119
    {
120
        $this->tenantService->tontine()->funds()->create($values);
121
        return true;
122
    }
123
124
    /**
125
     * Update a fund.
126
     *
127
     * @param Fund $fund
128
     * @param array $values
129
     *
130
     * @return bool
131
     */
132
    public function updateFund(Fund $fund, array $values): bool
133
    {
134
        return $fund->update($values);
135
    }
136
137
    /**
138
     * Toggle a fund.
139
     *
140
     * @param Fund $fund
141
     *
142
     * @return void
143
     */
144
    public function toggleFund(Fund $fund)
145
    {
146
        $fund->update(['active' => !$fund->active]);
147
    }
148
149
    /**
150
     * Delete a fund.
151
     *
152
     * @param Fund $fund
153
     *
154
     * @return void
155
     */
156
    public function deleteFund(Fund $fund)
157
    {
158
        $fund->delete();
159
    }
160
161
    /**
162
     * @param Session $currentSession
163
     * @param Fund $fund
164
     *
165
     * @return Builder|Relation
166
     */
167
    private function getFundSessionsQuery(Session $currentSession, Fund $fund): Builder|Relation
168
    {
169
        // Will return all the tontine sessions,
170
        // or all those after the last closing, if there's any.
171
        $lastSessionDate = $currentSession->start_at->format('Y-m-d');
172
        $sessionsQuery = $this->tenantService->tontine()->sessions()
173
            ->whereDate('start_at', '<=', $lastSessionDate);
174
175
        // The closing sessions before te current session.
176
        $closingSessions = $this->tenantService->tontine()->sessions()
177
            ->whereDate('start_at', '<', $lastSessionDate)
178
            ->whereHas('closings', function(Builder|Relation $query) use($fund) {
179
                $query->round()->where('fund_id', $fund->id);
180
            })
181
            ->orderByDesc('start_at')
182
            ->get();
183
        if($closingSessions->count() === 0)
184
        {
185
            // All the closing sessions are after the current session.
186
            return $sessionsQuery;
187
        }
188
189
        // The most recent previous closing session
190
        $firstSessionDate = $closingSessions->last()->start_at->format('Y-m-d');
191
        // Return all the sessions after the most recent previous closing session
192
        return $sessionsQuery->whereDate('start_at', '>', $firstSessionDate);
193
    }
194
195
    /**
196
     * Get the sessions to be used for profit calculation.
197
     *
198
     * @param Session $currentSession
199
     * @param Fund $fund
200
     *
201
     * @return Collection
202
     */
203
    public function getFundSessions(Session $currentSession, Fund $fund): Collection
204
    {
205
        return $this->getFundSessionsQuery($currentSession, $fund)->get();
206
    }
207
208
    /**
209
     * Get the id of sessions to be used for profit calculation.
210
     *
211
     * @param Session $currentSession
212
     * @param Fund $fund
213
     *
214
     * @return Collection
215
     */
216
    public function getFundSessionIds(Session $currentSession, Fund $fund): Collection
217
    {
218
        return $this->getFundSessionsQuery($currentSession, $fund)->pluck('id');
219
    }
220
}
221