RoundService::getRounds()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Siak\Tontine\Service\Guild;
4
5
use Exception;
6
use Illuminate\Support\Arr;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Facades\DB;
9
use Siak\Tontine\Exception\MessageException;
10
use Siak\Tontine\Model\Guild;
11
use Siak\Tontine\Model\Round;
12
use Siak\Tontine\Model\Session;
13
use Siak\Tontine\Service\Planning\FundSyncService;
14
use Siak\Tontine\Service\TenantService;
15
use Siak\Tontine\Validation\Guild\RoundValidator;
16
17
use function trans;
18
19
class RoundService
20
{
21
    /**
22
     * @param TenantService $tenantService
23
     * @param PoolService $poolService
24
     * @param RoundValidator $validator
25
     * @param FundSyncService $fundSyncService
26
     */
27
    public function __construct(protected TenantService $tenantService,
28
        protected PoolService $poolService, protected RoundValidator $validator,
29
        private FundSyncService $fundSyncService)
30
    {}
31
32
    /**
33
     * Get a paginated list of rounds in the selected guild.
34
     *
35
     * @param Guild $guild
36
     * @param int $page
37
     *
38
     * @return Collection
39
     */
40
    public function getRounds(Guild $guild, int $page = 0): Collection
41
    {
42
        return $guild->rounds()
43
            ->page($page, $this->tenantService->getLimit())
44
            ->get();
45
    }
46
47
    /**
48
     * Get a list of rounds for the dropdown select.
49
     *
50
     * @param Guild $guild
51
     *
52
     * @return Collection
53
     */
54
    public function getRoundList(Guild $guild): Collection
55
    {
56
        // Only rounds with at least 2 sessions are selectable.
57
        return $guild->rounds()
58
            ->join('sessions', 'sessions.round_id', '=', 'rounds.id')
59
            ->select('rounds.title', 'rounds.id', DB::raw('count(sessions.id)'))
60
            ->groupBy('rounds.title', 'rounds.id')
61
            ->havingRaw('count(sessions.id) > ?', [1])
62
            ->pluck('title', 'id');
63
    }
64
65
    /**
66
     * Get the number of rounds in the selected guild.
67
     *
68
     * @param Guild $guild
69
     *
70
     * @return int
71
     */
72
    public function getRoundCount(Guild $guild): int
73
    {
74
        return $guild->rounds()->count();
75
    }
76
77
    /**
78
     * Get a single round.
79
     *
80
     * @param Guild $guild
81
     * @param int $roundId
82
     *
83
     * @return Round|null
84
     */
85
    public function getRound(Guild $guild, int $roundId): ?Round
86
    {
87
        return $guild->rounds()->find($roundId);
88
    }
89
90
    /**
91
     * Add a new round.
92
     *
93
     * @param Guild $guild
94
     * @param array $values
95
     *
96
     * @return bool
97
     */
98
    public function createRound(Guild $guild, array $values): bool
99
    {
100
        $values = $this->validator->validateItem($values);
101
        DB::transaction(function() use($guild, $values) {
102
            $round = $guild->rounds()->create(Arr::except($values, 'savings'));
103
            $properties = $round->properties;
104
            $properties['savings']['fund']['default'] = $values['savings'];
105
            $round->saveProperties($properties);
106
107
            // Add all active members to the new round.
108
            $members = $guild->members()->active()->get()
109
                ->map(fn($member) => ['def_id' => $member->id]);
110
            $round->members()->createMany($members);
111
            // Add all active charges to the new round.
112
            $charges = $guild->charges()->active()->get()
113
                ->map(fn($charge) => ['def_id' => $charge->id]);
114
            $round->charges()->createMany($charges);
115
        });
116
        return true;
117
    }
118
119
    /**
120
     * Update a round.
121
     *
122
     * @param Guild $guild
123
     * @param int $roundId
124
     * @param array $values
125
     *
126
     * @return int
127
     */
128
    public function updateRound(Guild $guild, int $roundId, array $values): int
129
    {
130
        $values = $this->validator->validateItem($values);
131
        $round = $guild->rounds()->find($roundId);
132
        return DB::transaction(function() use($round, $values) {
133
            $properties = $round->properties;
134
            $properties['savings']['fund']['default'] = $values['savings'];
135
            $round->saveProperties($properties);
136
137
            return $round->update(Arr::except($values, 'savings'));
138
        });
139
    }
140
141
    /**
142
     * Delete a round.
143
     *
144
     * @param Guild $guild
145
     * @param int $roundId
146
     *
147
     * @return void
148
     */
149
    public function deleteRound(Guild $guild, int $roundId)
150
    {
151
        // Delete the session. Will fail if there's still some data attached.
152
        $round = $guild->rounds()->find($roundId);
153
        try
154
        {
155
            DB::transaction(function() use($round) {
156
                $this->fundSyncService->roundDeleted($round);
157
158
                // Delete the associated members.
159
                $round->members()->delete();
160
                // Delete the associated charges.
161
                $round->charges()->delete();
162
163
                // Delete the round.
164
                $round->delete();
165
            });
166
        }
167
        catch(Exception $e)
168
        {
169
            throw new MessageException(trans('tontine.round.errors.delete'));
170
        }
171
    }
172
173
    /**
174
     * Find a session.
175
     *
176
     * @param Round $round
177
     * @param int $sessionId    The session id
178
     *
179
     * @return Session|null
180
     */
181
    public function getSession(Round $round, int $sessionId): ?Session
182
    {
183
        return $round->sessions()->find($sessionId);
184
    }
185
186
    /**
187
     * Get the number of sessions in the selected round.
188
     *
189
     * @param Round $round
190
     *
191
     * @return int
192
     */
193
    public function getSessionCount(Round $round): int
194
    {
195
        return $round->sessions()->count();
196
    }
197
198
    /**
199
     * Get a paginated list of sessions in the selected round.
200
     *
201
     * @param Round $round
202
     * @param int $page
203
     * @param bool $orderAsc
204
     *
205
     * @return Collection
206
     */
207
    public function getSessions(Round $round, int $page = 0, bool $orderAsc = true): Collection
208
    {
209
        return $round->sessions()
210
            ->orderBy('day_date', $orderAsc ? 'asc' : 'desc')
211
            ->page($page, $this->tenantService->getLimit())
212
            ->get();
213
    }
214
}
215