Issues (196)

src/Service/Planning/PoolService.php (8 issues)

1
<?php
2
3
namespace Siak\Tontine\Service\Planning;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Relations\Relation;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Facades\DB;
9
use Siak\Tontine\Exception\MessageException;
10
use Siak\Tontine\Model\Pool;
11
use Siak\Tontine\Model\PoolDef;
12
use Siak\Tontine\Model\Round;
13
use Siak\Tontine\Model\Session;
14
use Siak\Tontine\Service\TenantService;
15
use Exception;
16
17
class PoolService
18
{
19
    use SessionTrait;
0 ignored issues
show
The trait Siak\Tontine\Service\Planning\SessionTrait requires some properties which are not provided by Siak\Tontine\Service\Planning\PoolService: $end, $start, $day_date
Loading history...
20
21
    /**
22
     * @param TenantService $tenantService
23
     * @param PoolSyncService $poolSyncService
24
     * @param FundSyncService $fundSyncService
25
     */
26
    public function __construct(protected TenantService $tenantService,
27
        private PoolSyncService $poolSyncService, private FundSyncService $fundSyncService)
28
    {}
29
30
    /**
31
     * @param Round $round
32
     * @param bool $filter|null
33
     *
34
     * @return Builder|Relation
35
     */
36
    public function getQuery(Round $round, ?bool $filter): Builder|Relation
37
    {
38
        $onRoundFilter = fn(Builder|Relation $q) => $q->ofRound($round);
39
        return $round->guild->pools()
40
            ->when($filter === true, fn(Builder|Relation $query) => $query
41
                ->whereHas('pools', $onRoundFilter))
42
            ->when($filter === false, fn(Builder|Relation $query) => $query
43
                ->whereDoesntHave('pools', $onRoundFilter));
44
    }
45
46
    /**
47
     * Get a paginated list of pools.
48
     *
49
     * @param Round $round
50
     * @param bool $filter|null
51
     * @param int $page
52
     *
53
     * @return Collection
54
     */
55
    public function getPoolDefs(Round $round, ?bool $filter, int $page = 0): Collection
56
    {
57
        return $this->getQuery($round, $filter)
58
            ->with([
59
                'pools' => fn(Builder|Relation $q) => $q->where('round_id', $round->id),
60
            ])
61
            ->withCount([
62
                'pools as pools_in_round_count' => fn(Builder|Relation $q) => $q->ofRound($round),
63
            ])
64
            ->page($page, $this->tenantService->getLimit())
65
            ->get();
66
    }
67
68
    /**
69
     * Get the number of pools.
70
     *
71
     * @param Round $round
72
     * @param bool $filter|null
73
     *
74
     * @return int
75
     */
76
    public function getPoolDefCount(Round $round, ?bool $filter): int
77
    {
78
        return $this->getQuery($round, $filter)->count();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getQuery($round, $filter)->count() could return the type Illuminate\Database\Eloq...uent\Relations\Relation which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
79
    }
80
81
    /**
82
     * @param Round $round
83
     * @param int $defId
84
     *
85
     * @return PoolDef|null
86
     */
87
    public function getPoolDef(Round $round, int $defId): ?PoolDef
88
    {
89
        return $round->guild->pools()
90
            ->with([
91
                'pools' => fn(Builder|Relation $q) => $q->where('round_id', $round->id),
92
            ])
93
            ->find($defId);
94
    }
95
96
    /**
97
     * @param Round $round
98
     * @param int $defId
99
     *
100
     * @return void
101
     */
102
    public function enablePool(Round $round, int $defId): void
103
    {
104
        $def = $this->getPoolDef($round, $defId);
105
        if(!$def || $def->pools->count() > 0)
106
        {
107
            return; // Todo: throw an exception
108
        }
109
110
        $itemQuery = Pool::withoutGlobalScopes()->where('def_id', $defId);
111
        $startSession = $this->getStartSession($round, $itemQuery);
0 ignored issues
show
It seems like $itemQuery can also be of type Illuminate\Database\Eloq...gHasThroughRelationship; however, parameter $itemQuery of Siak\Tontine\Service\Pla...vice::getStartSession() does only seem to accept Illuminate\Database\Eloquent\Builder, 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

111
        $startSession = $this->getStartSession($round, /** @scrutinizer ignore-type */ $itemQuery);
Loading history...
112
        $endSession = $this->getEndSession($round, $itemQuery);
0 ignored issues
show
It seems like $itemQuery can also be of type Illuminate\Database\Eloq...gHasThroughRelationship; however, parameter $itemQuery of Siak\Tontine\Service\Pla...ervice::getEndSession() does only seem to accept Illuminate\Database\Eloquent\Builder, 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

112
        $endSession = $this->getEndSession($round, /** @scrutinizer ignore-type */ $itemQuery);
Loading history...
113
        if($endSession->day_date <= $startSession->day_date)
114
        {
115
            return; // Todo: throw an exception
116
        }
117
118
        // Create the pool
119
        DB::transaction(function() use($def, $round, $startSession, $endSession) {
120
            $pool = $def->pools()->create([
121
                'title' => $def->title,
122
                'amount' => $def->amount,
123
                'deposit_fixed' => $def->deposit_fixed,
0 ignored issues
show
The property deposit_fixed does not seem to exist on Siak\Tontine\Model\PoolDef. 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...
124
                'deposit_lendable' => $def->deposit_lendable,
0 ignored issues
show
The property deposit_lendable does not seem to exist on Siak\Tontine\Model\PoolDef. 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...
125
                'remit_planned' => $def->remit_planned,
0 ignored issues
show
The property remit_planned does not seem to exist on Siak\Tontine\Model\PoolDef. 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...
126
                'remit_auction' => $def->remit_auction,
0 ignored issues
show
The property remit_auction does not seem to exist on Siak\Tontine\Model\PoolDef. 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...
127
                'round_id' => $round->id,
128
                'start_sid' => $startSession->id,
129
                'end_sid' => $endSession->id,
130
            ]);
131
132
            $this->fundSyncService->poolEnabled($round, $pool);
133
        });
134
    }
135
136
    /**
137
     * @param Round $round
138
     * @param int $defId
139
     *
140
     * @return void
141
     */
142
    public function disablePool(Round $round, int $defId): void
143
    {
144
        $def = $this->getPoolDef($round, $defId);
145
        if(!$def || $def->pools->count() === 0)
146
        {
147
            return;
148
        }
149
150
        try
151
        {
152
            // Delete the pool
153
            DB::transaction(function() use($def, $round) {
154
                $pool = $def->pools->first();
155
                $this->fundSyncService->poolDisabled($round, $pool);
156
157
                DB::table('pool_session_disabled')
158
                    ->where('pool_id', $pool->id)
159
                    ->delete();
160
                $pool->delete();
161
            });
162
        }
163
        catch(Exception $e)
164
        {
165
            throw new MessageException(trans('tontine.pool.errors.cannot_remove'));
166
        }
167
    }
168
169
    /**
170
     * Get a paginated list of pools.
171
     *
172
     * @param Round $round
173
     * @param int $page
174
     *
175
     * @return Collection
176
     */
177
    public function getPools(Round $round, int $page = 0): Collection
178
    {
179
        return Pool::ofRound($round)
180
            ->page($page, $this->tenantService->getLimit())
181
            ->get();
182
    }
183
184
    /**
185
     * Get a pool.
186
     *
187
     * @param Round $round
188
     * @param int $poolId
189
     *
190
     * @return Pool|null
191
     */
192
    public function getPool(Round $round, int $poolId): ?Pool
193
    {
194
        return Pool::ofRound($round)
195
            ->with(['sessions', 'disabled_sessions'])
196
            ->find($poolId);
197
    }
198
199
    /**
200
     * Get the sessions enabled for a pool.
201
     *
202
     * @param Pool $pool
203
     *
204
     * @return Collection
205
     */
206
    public function getActiveSessions(Pool $pool): Collection
207
    {
208
        return $pool->sessions()->orderBy('day_date')->get();
209
    }
210
211
    /**
212
     * Get the number of sessions enabled for a pool.
213
     *
214
     * @param Pool $pool
215
     *
216
     * @return int
217
     */
218
    public function getActiveSessionCount(Pool $pool): int
219
    {
220
        return $pool->sessions()->count();
221
    }
222
223
    /**
224
     * Save the pool sessions.
225
     *
226
     * @param Pool $pool
227
     * @param array $values
228
     *
229
     * @return void
230
     */
231
    public function saveSessions(Pool $pool, array $values)
232
    {
233
        DB::transaction(function() use($pool, $values) {
234
            $pool->update($values);
235
236
            $this->poolSyncService->sessionsChanged($pool);
237
        });
238
    }
239
240
    /**
241
     * Enable or disable a session for a pool.
242
     *
243
     * @param Pool $pool
244
     * @param Session $session
245
     *
246
     * @return void
247
     */
248
    public function enableSession(Pool $pool, Session $session)
249
    {
250
        // Enable the session for the pool.
251
        DB::transaction(function() use($pool, $session) {
252
            DB::table('pool_session_disabled')
253
                ->where('pool_id', $pool->id)
254
                ->where('session_id', $session->id)
255
                ->delete();
256
257
            $this->poolSyncService->sessionEnabled($pool, $session);
258
        });
259
    }
260
261
    /**
262
     * Enable or disable a session for a pool.
263
     *
264
     * @param Pool $pool
265
     * @param Session $session
266
     *
267
     * @return void
268
     */
269
    public function disableSession(Pool $pool, Session $session)
270
    {
271
        try
272
        {
273
            // Disable the session for the pool.
274
            DB::transaction(function() use($pool, $session) {
275
                DB::table('pool_session_disabled')
276
                    ->updateOrInsert([
277
                        'pool_id' => $pool->id,
278
                        'session_id' => $session->id,
279
                    ]);
280
281
                $this->poolSyncService->sessionDisabled($pool, $session);
282
            });
283
        }
284
        catch(Exception $e)
285
        {
286
            throw new MessageException(trans('tontine.session.errors.cannot_disable'));
287
        }
288
    }
289
290
    /**
291
     * Get the number of active pools in the round.
292
     *
293
     * @param Round $round
294
     *
295
     * @return int
296
     */
297
    public function getPoolCount(Round $round): int
298
    {
299
        return $round->pools()->count();
300
    }
301
}
302