Issues (214)

src/Service/Planning/PoolService.php (4 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\Model\Pool;
10
use Siak\Tontine\Model\PoolDef;
11
use Siak\Tontine\Model\Round;
12
use Siak\Tontine\Model\Session;
13
use Siak\Tontine\Service\TenantService;
14
15
class PoolService
16
{
17
    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...
18
19
    /**
20
     * @param TenantService $tenantService
21
     * @param PoolSyncService $poolSyncService
22
     * @param FundSyncService $fundSyncService
23
     */
24
    public function __construct(protected TenantService $tenantService,
25
        private PoolSyncService $poolSyncService, private FundSyncService $fundSyncService)
26
    {}
27
28
    /**
29
     * @param Round $round
30
     * @param bool $filter|null
31
     *
32
     * @return Builder|Relation
33
     */
34
    public function getQuery(Round $round, ?bool $filter): Builder|Relation
35
    {
36
        $onRoundFilter = fn(Builder|Relation $q) => $q->ofRound($round);
37
        return $round->guild->pools()
38
            ->when($filter === true, fn(Builder|Relation $query) => $query
39
                ->whereHas('pools', $onRoundFilter))
40
            ->when($filter === false, fn(Builder|Relation $query) => $query
41
                ->whereDoesntHave('pools', $onRoundFilter));
42
    }
43
44
    /**
45
     * Get a paginated list of pools.
46
     *
47
     * @param Round $round
48
     * @param bool $filter|null
49
     * @param int $page
50
     *
51
     * @return Collection
52
     */
53
    public function getPoolDefs(Round $round, ?bool $filter, int $page = 0): Collection
54
    {
55
        return $this->getQuery($round, $filter)
56
            ->with([
57
                'pools' => fn(Builder|Relation $q) => $q->where('round_id', $round->id),
58
            ])
59
            ->withCount([
60
                'pools as pools_in_round_count' => fn(Builder|Relation $q) => $q->ofRound($round),
61
            ])
62
            ->page($page, $this->tenantService->getLimit())
63
            ->get();
64
    }
65
66
    /**
67
     * Get the number of pools.
68
     *
69
     * @param Round $round
70
     * @param bool $filter|null
71
     *
72
     * @return int
73
     */
74
    public function getPoolDefCount(Round $round, ?bool $filter): int
75
    {
76
        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...
77
    }
78
79
    /**
80
     * @param Round $round
81
     * @param int $defId
82
     *
83
     * @return PoolDef|null
84
     */
85
    public function getPoolDef(Round $round, int $defId): ?PoolDef
86
    {
87
        return $round->guild->pools()
88
            ->with([
89
                'pools' => fn(Builder|Relation $q) => $q->where('round_id', $round->id),
90
            ])
91
            ->find($defId);
92
    }
93
94
    /**
95
     * @param Round $round
96
     * @param int $defId
97
     *
98
     * @return void
99
     */
100
    public function enablePool(Round $round, int $defId): void
101
    {
102
        $def = $this->getPoolDef($round, $defId);
103
        if(!$def || $def->pools->count() > 0)
104
        {
105
            return; // Todo: throw an exception
106
        }
107
108
        $itemQuery = Pool::withoutGlobalScopes()->where('def_id', $defId);
109
        $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

109
        $startSession = $this->getStartSession($round, /** @scrutinizer ignore-type */ $itemQuery);
Loading history...
110
        $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

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