Passed
Push — main ( 34d123...876c9b )
by Thierry
05:11
created

OutflowService::getAmountAvailableValue()   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
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Siak\Tontine\Service\Meeting\Cash;
4
5
use Illuminate\Support\Collection;
6
use Siak\Tontine\Exception\MessageException;
7
use Siak\Tontine\Model\Category;
8
use Siak\Tontine\Model\Charge;
9
use Siak\Tontine\Model\Outflow;
10
use Siak\Tontine\Model\Member;
11
use Siak\Tontine\Model\Session;
12
use Siak\Tontine\Service\BalanceCalculator;
13
use Siak\Tontine\Service\LocaleService;
14
use Siak\Tontine\Service\TenantService;
15
16
use function trans;
17
use function trim;
18
19
class OutflowService
20
{
21
    /**
22
     * @param LocaleService $localeService
23
     * @param TenantService $tenantService
24
     * @param BalanceCalculator $balanceCalculator
25
     */
26
    public function __construct(protected LocaleService $localeService,
27
        protected TenantService $tenantService, protected BalanceCalculator $balanceCalculator)
28
    {}
29
30
    /**
31
     * Get a list of members for the dropdown select component.
32
     *
33
     * @return Collection
34
     */
35
    public function getMembers(): Collection
36
    {
37
        return $this->tenantService->guild()->members()->active()
38
            ->orderBy('name', 'asc')->pluck('name', 'id')->prepend('', 0);
39
    }
40
41
    /**
42
     * Find a member.
43
     *
44
     * @param int $memberId
45
     *
46
     * @return Member|null
47
     */
48
    public function getMember(int $memberId): ?Member
49
    {
50
        return $this->tenantService->guild()->members()->active()->find($memberId);
51
    }
52
53
    /**
54
     * Get a list of charges for the dropdown select component.
55
     *
56
     * @return Collection
57
     */
58
    public function getCharges(): Collection
59
    {
60
        return $this->tenantService->guild()->charges()->fee()->active()
61
            ->orderBy('name', 'asc')->pluck('name', 'id')->prepend('', 0);
62
    }
63
64
    /**
65
     * Find a charge.
66
     *
67
     * @param int $chargeId
68
     *
69
     * @return Charge|null
70
     */
71
    public function getCharge(int $chargeId): ?Charge
72
    {
73
        return $this->tenantService->guild()->charges()->fee()->find($chargeId);
74
    }
75
76
    /**
77
     * Get the outflow categories for the dropdown select component.
78
     *
79
     * @return Collection
80
     */
81
    public function getAccounts(): Collection
82
    {
83
        // It is important to call get() before pluck() so the name field is translated.
84
        $globalCategories = Category::outflow()->get();
85
        // We need to move the "other" category to the end of the list.
86
        // getAttributes()['name'] returns the name field, without calling the getter.
87
        [$otherCategory, $globalCategories] = $globalCategories->partition(fn($category) =>
88
            $category->getAttributes()['name'] === 'other');
89
90
        $guildCategories = $this->tenantService->guild()->categories()->outflow()
91
            ->active()->get();
92
        return $globalCategories->concat($guildCategories)->concat($otherCategory)
93
            ->pluck('name', 'id');
94
    }
95
96
    /**
97
     * Find a cash outflow category.
98
     *
99
     * @param int $categoryId
100
     *
101
     * @return Category|null
102
     */
103
    public function getAccount(int $categoryId): ?Category
104
    {
105
        return Category::outflow()->find($categoryId);
106
    }
107
108
    /**
109
     * Get the amount available for outflow.
110
     *
111
     * @param Session $session    The session
112
     *
113
     * @return int
114
     */
115
    public function getAmountAvailable(Session $session): int
116
    {
117
        return $this->balanceCalculator->getTotalBalance($session);
118
    }
119
120
    /**
121
     * Get the outflows.
122
     *
123
     * @param int $page
124
     *
125
     * @return Collection
126
     */
127
    public function getOutflows(int $page = 0): Collection
128
    {
129
        return Outflow::with(['member', 'charge', 'category', 'session'])
130
            ->page($page, $this->tenantService->getLimit())->get();
131
    }
132
133
    /**
134
     * Count the outflows for a given session.
135
     *
136
     * @param Session $session
137
     *
138
     * @return int
139
     */
140
    public function getSessionOutflowCount(Session $session): int
141
    {
142
        return $session->outflows()->count();
143
    }
144
145
    /**
146
     * Get the outflows for a given session.
147
     *
148
     * @param Session $session
149
     * @param int $page
150
     *
151
     * @return Collection
152
     */
153
    public function getSessionOutflows(Session $session, int $page = 0): Collection
154
    {
155
        return $session->outflows()
156
            ->with(['member', 'charge', 'category'])
157
            ->page($page, $this->tenantService->getLimit())
158
            ->get();
159
    }
160
161
    /**
162
     * Get a cash outflow for a given session.
163
     *
164
     * @param Session $session
165
     * @param int $outflowId
166
     *
167
     * @return Outflow|null
168
     */
169
    public function getSessionOutflow(Session $session, int $outflowId): ?Outflow
170
    {
171
        return $session->outflows()->find($outflowId);
172
    }
173
174
    /**
175
     * Create a cash outflow.
176
     *
177
     * @param Session $session The session
178
     * @param array $values
179
     *
180
     * @return void
181
     */
182
    public function createOutflow(Session $session, array $values): void
183
    {
184
        $member = $this->getMember($values['member']);
185
        $charge = $this->getCharge($values['charge']);
186
        $category = $this->getAccount($values['category']);
187
        if(!$category)
0 ignored issues
show
introduced by
$category is of type Siak\Tontine\Model\Category, thus it always evaluated to true.
Loading history...
188
        {
189
            throw new MessageException(trans('meeting.category.errors.not_found'));
190
        }
191
192
        $outflow = new Outflow();
193
        $outflow->amount = $values['amount'];
194
        $outflow->comment = trim($values['comment']);
195
        if(($member))
196
        {
197
            $outflow->member()->associate($member);
198
        }
199
        if(($charge))
200
        {
201
            $outflow->charge_lendable = $charge->lendable;
202
            $outflow->charge()->associate($charge);
203
        }
204
        else
205
        {
206
            $outflow->charge_lendable = true;
207
        }
208
        $outflow->category()->associate($category);
209
        $outflow->session()->associate($session);
210
        $outflow->save();
211
    }
212
213
    /**
214
     * Update a cash outflow.
215
     *
216
     * @param Session $session The session
217
     * @param int $outflowId
218
     * @param array $values
219
     *
220
     * @return void
221
     */
222
    public function updateOutflow(Session $session, int $outflowId, array $values): void
223
    {
224
        $member = $this->getMember($values['member']);
225
        $charge = $this->getCharge($values['charge']);
226
        $category = $this->getAccount($values['category']);
227
        if(!$category)
0 ignored issues
show
introduced by
$category is of type Siak\Tontine\Model\Category, thus it always evaluated to true.
Loading history...
228
        {
229
            throw new MessageException(trans('meeting.category.errors.not_found'));
230
        }
231
        $outflow = $session->outflows()->find($outflowId);
232
        if(!$outflow)
233
        {
234
            throw new MessageException(trans('meeting.outflow.errors.not_found'));
235
        }
236
237
        $outflow->amount = $values['amount'];
238
        $outflow->comment = trim($values['comment']);
239
        if(($member))
240
        {
241
            $outflow->member()->associate($member);
242
        }
243
        else
244
        {
245
            $outflow->member()->dissociate();
246
        }
247
        if(($charge))
248
        {
249
            $outflow->charge_lendable = $charge->lendable;
250
            $outflow->charge()->associate($charge);
251
        }
252
        else
253
        {
254
            $outflow->charge_lendable = true;
255
            $outflow->charge()->dissociate();
256
        }
257
        $outflow->category()->associate($category);
258
        $outflow->save();
259
    }
260
261
    /**
262
     * Delete a cash outflow.
263
     *
264
     * @param Session $session The session
265
     * @param int $outflowId
266
     *
267
     * @return void
268
     */
269
    public function deleteOutflow(Session $session, int $outflowId): void
270
    {
271
        $session->outflows()->where('id', $outflowId)->delete();
272
    }
273
}
274