Passed
Pull Request — main (#63)
by Thierry
06:38
created

PoolService::enabled()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Siak\Tontine\Service\Planning;
4
5
use Exception;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Database\Eloquent\Relations\Relation;
8
use Illuminate\Support\Collection;
9
use Illuminate\Support\Facades\DB;
10
use Siak\Tontine\Exception\MessageException;
11
use Siak\Tontine\Model\Pool;
12
use Siak\Tontine\Model\Session;
13
use Siak\Tontine\Service\TenantService;
14
15
use function trans;
16
17
class PoolService
18
{
19
    /**
20
     * @param TenantService $tenantService
21
     * @param DataSyncService $dataSyncService
22
     */
23
    public function __construct(protected TenantService $tenantService,
24
        private DataSyncService $dataSyncService)
25
    {}
26
27
    /**
28
     * @return Builder|Relation
29
     */
30
    private function getQuery(): Builder|Relation
31
    {
32
        return Pool::ofRound($this->tenantService->round());
33
    }
34
35
    /**
36
     * Get a paginated list of pools.
37
     *
38
     * @param int $page
39
     *
40
     * @return Collection
41
     */
42
    public function getPools(int $page = 0): Collection
43
    {
44
        return $this->getQuery()
45
            ->page($page, $this->tenantService->getLimit())
46
            ->get();
47
    }
48
49
    /**
50
     * Get the number of pools.
51
     *
52
     * @return int
53
     */
54
    public function getPoolCount(): int
55
    {
56
        return $this->getQuery()->count();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getQuery()->count() could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
57
    }
58
59
    /**
60
     * Get a single pool.
61
     *
62
     * @param int $poolId    The pool id
63
     *
64
     * @return Pool|null
65
     */
66
    public function getPool(int $poolId): ?Pool
67
    {
68
        return $this->getQuery()->with('counter')->find($poolId);
69
    }
70
71
    /**
72
     * Get the pools in the current round.
73
     *
74
     * @return Collection
75
     */
76
    public function getRoundPools(): Collection
77
    {
78
        return $this->tenantService->round()->pools()->get();
79
    }
80
81
    /**
82
     * Add a new pool.
83
     *
84
     * @param array $values
85
     *
86
     * @return bool
87
     */
88
    public function createPool(array $values): bool
89
    {
90
        $this->tenantService->round()->pools()->create($values);
91
92
        return true;
93
    }
94
95
    /**
96
     * Update a pool.
97
     *
98
     * @param Pool $pool
99
     * @param array $values
100
     *
101
     * @return bool
102
     */
103
    public function updatePool(Pool $pool, array $values): bool
104
    {
105
        return $pool->update($values);
106
    }
107
108
    /**
109
     * Delete a pool.
110
     *
111
     * @param Pool $pool
112
     *
113
     * @return void
114
     */
115
    public function deletePool(Pool $pool)
116
    {
117
        DB::transaction(function() use($pool) {
118
            $this->dataSyncService->syncPool($pool, false);
119
120
            $pool->pool_round()->delete();
121
            $pool->subscriptions()->delete();
122
            $pool->delete();
123
        });
124
    }
125
126
    /**
127
     * @param int $count
128
     *
129
     * @return Collection
130
     */
131
    public function getFakePools(int $count): Collection
132
    {
133
        return Pool::factory()->count($count)->make([
134
            'round_id' => $this->tenantService->round(),
135
        ]);
136
    }
137
138
    /**
139
     * Save the pool start and/or end session.
140
     *
141
     * @param Pool $pool
142
     * @param array $values
143
     *
144
     * @return void
145
     */
146
    private function _saveSessions(Pool $pool, array $values)
147
    {
148
        if($pool->pool_round !== null)
149
        {
150
            $pool->pool_round()->update($values);
151
            return;
152
        }
153
154
        // The initial value is the same for start and end sessions.
155
        if(!isset($values['start_session_id']))
156
        {
157
            $values['start_session_id'] = $this
158
                ->getPoolStartSession($pool)?->id ?? $values['end_session_id'];
159
        }
160
        if(!isset($values['end_session_id']))
161
        {
162
            $values['end_session_id'] = $this
163
                ->getPoolEndSession($pool)?->id ?? $values['start_session_id'];
164
        }
165
        $pool->pool_round()->create($values);
166
    }
167
168
    /**
169
     * Save the pool start and/or end session.
170
     *
171
     * @param Pool $pool
172
     * @param array $values
173
     *
174
     * @return void
175
     */
176
    public function saveSessions(Pool $pool, array $values)
177
    {
178
        DB::transaction(function() use($pool, $values) {
179
            $this->_saveSessions($pool, $values);
180
181
            $this->dataSyncService->syncPool($pool, true);
182
        });
183
    }
184
185
    /**
186
     * Delete the pool round.
187
     *
188
     * @param Pool $pool
189
     *
190
     * @return void
191
     */
192
    public function deleteRound(Pool $pool)
193
    {
194
        DB::transaction(function() use($pool) {
195
            $pool->pool_round()->delete();
196
197
            $this->dataSyncService->syncPool($pool, true);
198
        });
199
    }
200
201
    /**
202
     * Get the first session of the pool.
203
     *
204
     * @param Pool $pool
205
     *
206
     * @return Session|null
207
     */
208
    public function getPoolStartSession(Pool $pool): ?Session
209
    {
210
        return $pool->pool_round?->start_session ??
211
            $pool->round->sessions()->orderBy('start_at', 'asc')->first();
212
    }
213
214
    /**
215
     * Get the last session of the pool.
216
     *
217
     * @param Pool $pool
218
     *
219
     * @return Session|null
220
     */
221
    public function getPoolEndSession(Pool $pool): ?Session
222
    {
223
        return $pool->pool_round?->end_session ??
224
            $pool->round->sessions()->orderBy('start_at', 'desc')->first();
225
    }
226
227
    /**
228
     * Enable or disable a session for a pool.
229
     *
230
     * @param Pool $pool
231
     * @param int $sessionId    The session id
232
     *
233
     * @return void
234
     */
235
    public function enableSession(Pool $pool, int $sessionId)
236
    {
237
        // When the remitments are planned, don't enable or disable a session
238
        // if receivables already exist on the pool.
239
        // if($pool->remit_planned &&
240
        //     $pool->subscriptions()->whereHas('receivables')->count() > 0)
241
        // {
242
        //     return;
243
        // }
244
        $session = $this->tenantService->tontine()
245
            ->sessions()
246
            ->ofPool($pool)
247
            ->disabled($pool)
248
            ->find($sessionId);
249
        if(!$session)
250
        {
251
            return;
252
        }
253
254
        // Enable the session for the pool.
255
        $pool->disabled_sessions()->detach($session->id);
256
    }
257
258
    /**
259
     * Enable or disable a session for a pool.
260
     *
261
     * @param Pool $pool
262
     * @param int $sessionId    The session id
263
     *
264
     * @return void
265
     */
266
    public function disableSession(Pool $pool, int $sessionId)
267
    {
268
        // When the remitments are planned, don't enable or disable a session
269
        // if receivables already exist on the pool.
270
        // if($pool->remit_planned &&
271
        //     $pool->subscriptions()->whereHas('receivables')->count() > 0)
272
        // {
273
        //     return;
274
        // }
275
        $session = $this->tenantService->tontine()
276
            ->sessions()
277
            ->ofPool($pool)
278
            ->enabled($pool)
279
            ->find($sessionId);
280
        if(!$session)
281
        {
282
            return;
283
        }
284
285
        // Disable the session for the pool.
286
        DB::transaction(function() use($pool, $session) {
287
            $pool->disabled_sessions()->attach($session->id);
288
289
            $this->dataSyncService->syncPool($pool, true);
290
        });
291
    }
292
293
    /**
294
     * @param Pool $pool
295
     * @param Session $session
296
     *
297
     * @return bool
298
     */
299
    public function enabled(Pool $pool, Session $session): bool
300
    {
301
        return $session->disabled_pools->find($pool->id) === null;
302
    }
303
304
    /**
305
     * @param Pool $pool
306
     * @param Session $session
307
     *
308
     * @return bool
309
     */
310
    public function disabled(Pool $pool, Session $session): bool
311
    {
312
        return $session->disabled_pools->find($pool->id) !== null;
313
    }
314
315
    /**
316
     * Get the sessions enabled for a pool.
317
     *
318
     * @param Pool $pool
319
     *
320
     * @return Collection
321
     */
322
    public function getEnabledSessions(Pool $pool): Collection
323
    {
324
        return $this->tenantService->tontine()
325
            ->sessions()
326
            ->ofPool($pool)
327
            ->enabled($pool)
328
            ->orderBy('start_at')
329
            ->get();
330
    }
331
332
    /**
333
     * Get the number of sessions enabled for a pool.
334
     *
335
     * @param Pool $pool
336
     *
337
     * @return int
338
     */
339
    public function getEnabledSessionCount(Pool $pool): int
340
    {
341
        return $this->tenantService->tontine()
342
            ->sessions()
343
            ->ofPool($pool)
344
            ->enabled($pool)
345
            ->count();
346
    }
347
}
348