Passed
Push — main ( 0be37e...fc9941 )
by Thierry
06:01
created

SummaryService::getFunds()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Siak\Tontine\Service\Meeting;
4
5
use Illuminate\Support\Collection;
6
use Illuminate\Support\Facades\DB;
7
use Siak\Tontine\Model\Fund;
8
use Siak\Tontine\Model\Pool;
9
use Siak\Tontine\Model\Round;
10
use Siak\Tontine\Model\Session;
11
use Siak\Tontine\Service\BalanceCalculator;
12
use Siak\Tontine\Service\Planning\PoolService;
13
use Siak\Tontine\Service\TenantService;
14
use Siak\Tontine\Service\Traits\ReportTrait;
15
use stdClass;
16
17
use function collect;
18
use function compact;
19
20
class SummaryService
21
{
22
    use ReportTrait;
0 ignored issues
show
introduced by
The trait Siak\Tontine\Service\Traits\ReportTrait requires some properties which are not provided by Siak\Tontine\Service\Meeting\SummaryService: $deposit_fixed, $id
Loading history...
23
24
    /**
25
     * @var Collection
26
     */
27
    private $deposits;
28
29
    /**
30
     * @var Collection
31
     */
32
    private $remitments;
33
34
    /**
35
     * @var Collection
36
     */
37
    private $auctions;
38
39
    /**
40
     * @param BalanceCalculator $balanceCalculator
41
     * @param TenantService $tenantService
42
     * @param PoolService $poolService
43
     */
44
    public function __construct(protected BalanceCalculator $balanceCalculator,
45
        protected TenantService $tenantService, PoolService $poolService)
46
    {
47
        $this->poolService = $poolService;
48
    }
49
50
    /**
51
     * @param Pool $pool
52
     * @param int $cashier
53
     * @param stdClass|null $deposit
54
     * @param stdClass|null $remitment
55
     *
56
     * @return stdClass
57
     */
58
    private function getSessionFigures(Pool $pool, int $cashier,
59
        ?stdClass $deposit, ?stdClass $remitment): stdClass
60
    {
61
        $figures = $this->makeFigures(0);
62
        $figures->cashier->start = $cashier;
63
        $figures->cashier->recv = $cashier;
64
65
        $depositCount = $deposit?->count ?? 0;
66
        $depositAmount = $pool->deposit_fixed ?
0 ignored issues
show
Bug introduced by
The property deposit_fixed does not seem to exist on Siak\Tontine\Model\Pool. 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...
67
            $pool->def->amount * $depositCount : ($deposit?->amount ?? 0);
68
69
        $figures->deposit->amount += $depositAmount;
70
        $figures->cashier->recv += $depositAmount;
71
        $figures->deposit->count = $depositCount;
72
73
        $sessionCount = $pool->sessions->count();
74
        $remitmentCount = $remitment?->count ?? 0;
75
        $remitmentAmount = $pool->deposit_fixed ?
76
            $pool->def->amount * $sessionCount * $remitmentCount :
77
            ($remitmentCount > 0 ? $depositAmount : 0);
78
79
        $figures->cashier->end = $figures->cashier->recv;
80
        $figures->remitment->amount += $remitmentAmount;
81
        $figures->cashier->end -= $remitmentAmount;
82
        $figures->remitment->count += $remitmentCount;
83
84
        return $figures;
85
    }
86
87
    /**
88
     * @param Pool $pool
89
     * @param Collection $sessions
90
     *
91
     * @return array
92
     */
93
    private function getCollectedFigures(Pool $pool, Collection $sessions): array
94
    {
95
        $cashier = 0;
96
        $collectedFigures = [];
97
        foreach($sessions as $session)
98
        {
99
            $deposit = $this->deposits[$pool->id][$session->id] ?? null;
100
            $remitment = $this->remitments[$pool->id][$session->id] ?? null;
101
            $figures = $this->getSessionFigures($pool, $cashier, $deposit, $remitment);
102
            if($pool->remit_auction)
0 ignored issues
show
Bug introduced by
The property remit_auction does not seem to exist on Siak\Tontine\Model\Pool. 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...
103
            {
104
                // Add the auctions amount to the cash amount.
105
                $figures->cashier->end += $this->auctions[$pool->id][$session->id]?->amount ?? 0;
106
            }
107
            $cashier = $figures->cashier->end;
108
            $collectedFigures[$session->id] = $figures;
109
        }
110
111
        return $collectedFigures;
112
    }
113
114
    /**
115
     * @param Round $round
116
     * @param Collection $poolIds
117
     *
118
     * @return void
119
     */
120
    private function getDeposits(Round $round, Collection $poolIds): void
121
    {
122
        $this->deposits = DB::table('deposits')
123
            ->select('subscriptions.pool_id', 'receivables.session_id',
124
                DB::raw('count(*) as count'), DB::raw('sum(deposits.amount) as amount'))
125
            ->join('receivables', 'receivables.id', '=', 'deposits.receivable_id')
126
            ->join('subscriptions', 'receivables.subscription_id', '=', 'subscriptions.id')
127
            ->join('sessions', 'receivables.session_id', '=', 'sessions.id')
128
            ->whereIn('subscriptions.pool_id', $poolIds)
129
            ->where('sessions.round_id', $round->id)
130
            ->groupBy(['subscriptions.pool_id', 'receivables.session_id'])
131
            ->get()
132
            // Group the data by pool id and session id.
133
            ->groupBy('pool_id')
134
            ->map(fn($poolDeposits) => $poolDeposits->groupBy('session_id')
135
                ->map(fn($array) => $array->first()));
136
    }
137
138
    /**
139
     * @param Round $round
140
     * @param Collection $poolIds
141
     *
142
     * @return void
143
     */
144
    private function getRemitments(Round $round, Collection $poolIds): void
145
    {
146
        $this->remitments = DB::table('remitments')
147
            ->select('subscriptions.pool_id', 'payables.session_id', DB::raw('count(*) as count'))
148
            ->join('payables', 'payables.id', '=', 'remitments.payable_id')
149
            ->join('subscriptions', 'payables.subscription_id', '=', 'subscriptions.id')
150
            ->join('sessions', 'payables.session_id', '=', 'sessions.id')
151
            ->whereIn('subscriptions.pool_id', $poolIds)
152
            ->where('sessions.round_id', $round->id)
153
            ->groupBy(['subscriptions.pool_id', 'payables.session_id'])
154
            ->get()
155
            // Group the data by pool id and session id.
156
            ->groupBy('pool_id')
157
            ->map(fn($poolRemitments) => $poolRemitments->groupBy('session_id')
158
                ->map(fn($array) => $array->first()));
159
    }
160
161
    /**
162
     * @param Round $round
163
     * @param Collection $poolIds
164
     *
165
     * @return void
166
     */
167
    private function getAuctions(Round $round, Collection $poolIds): void
168
    {
169
        $this->auctions = DB::table('auctions')
170
            ->select('subscriptions.pool_id', 'auctions.session_id',
171
                DB::raw('count(*) as count'), DB::raw('sum(amount) as amount'))
172
            ->join('remitments', 'auctions.remitment_id', '=', 'remitments.id')
173
            ->join('payables', 'remitments.payable_id', '=', 'payables.id')
174
            ->join('subscriptions', 'payables.subscription_id', '=', 'subscriptions.id')
175
            ->join('sessions', 'payables.session_id', '=', 'sessions.id')
176
            ->where('paid', true)
177
            ->whereIn('subscriptions.pool_id', $poolIds)
178
            ->where('sessions.round_id', $round->id)
179
            ->groupBy(['subscriptions.pool_id', 'auctions.session_id'])
180
            ->get()
181
            // Group the data by pool id and session id.
182
            ->groupBy('pool_id')
183
            ->map(fn($poolAuctions) => $poolAuctions->groupBy('session_id')
184
                ->map(fn($array) => $array->first()));
185
    }
186
187
    /**
188
     * @param Pool $pool
189
     *
190
     * @return array
191
     */
192
    private function getPoolFigures(Pool $pool): array
193
    {
194
        $sessions = $this->poolService->getActiveSessions($pool);
195
196
        $figures = new stdClass();
197
        if($pool->remit_planned)
0 ignored issues
show
Bug introduced by
The property remit_planned does not seem to exist on Siak\Tontine\Model\Pool. 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...
198
        {
199
            $figures->expected = $this->getExpectedFigures($pool, $sessions);
200
        }
201
        $figures->collected = $this->getCollectedFigures($pool, $sessions);
202
        if($pool->remit_auction)
0 ignored issues
show
Bug introduced by
The property remit_auction does not seem to exist on Siak\Tontine\Model\Pool. 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...
203
        {
204
            $figures->auctions = $this->auctions[$pool->id] ?? collect();
205
        }
206
207
        return compact('pool', 'figures', 'sessions');
208
    }
209
210
    /**
211
     * Get the receivables of a given pool.
212
     *
213
     * @param Round $round
214
     * @param int $poolId
215
     *
216
     * @return Collection
217
     */
218
    public function getFigures(Round $round, int $poolId = 0): Collection
219
    {
220
        $pools = $round->pools()
221
            ->with(['round.guild', 'sessions'])
222
            ->whereHas('subscriptions')
223
            ->when($poolId > 0, fn($query) => $query->where('pools.id', $poolId))
224
            ->get();
225
        if($pools->count() === 0)
226
        {
227
            return collect();
228
        }
229
230
        $poolIds = $pools->pluck('id');
231
        $this->getDeposits($round, $poolIds);
232
        $this->getRemitments($round, $poolIds);
233
        $this->getAuctions($round, $poolIds);
234
235
        return $pools->map(fn(Pool $pool) => $this->getPoolFigures($pool));
236
    }
237
238
    /**
239
     * @param Collection $figures
240
     *
241
     * @return array
242
     */
243
    public function getPoolsBalance(Collection $figures): array
244
    {
245
        $pools = [];
246
        foreach($figures as $poolData)
247
        {
248
            foreach($poolData['figures']->collected as $sessionId => $collected)
249
            {
250
                $pools[$sessionId] = ($pools[$sessionId] ?? 0) + $collected->cashier->end;
251
            }
252
        }
253
        return $pools;
254
    }
255
256
    /**
257
     * Get the funds.
258
     *
259
     * @param Round $round
260
     *
261
     * @return Collection
262
     */
263
    public function getFunds(Round $round): Collection
264
    {
265
        return Fund::ofRound($round)->get()
266
            ->filter(fn($fund) => $fund->start_amount > 0 ||
267
                $fund->end_amount > 0 || $fund->profit_amount > 0);
268
    }
269
270
    /**
271
     * @param Pool $pool
272
     * @param Session $session
273
     *
274
     * @return int
275
     */
276
    public function getSessionRemitmentCount(Pool $pool, Session $session): int
277
    {
278
        if(!$pool->remit_planned)
0 ignored issues
show
Bug introduced by
The property remit_planned does not seem to exist on Siak\Tontine\Model\Pool. 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...
279
        {
280
            return -1;
281
        }
282
        if(!$pool->deposit_fixed)
0 ignored issues
show
Bug introduced by
The property deposit_fixed does not seem to exist on Siak\Tontine\Model\Pool. 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...
283
        {
284
            return 1;
285
        }
286
287
        $sessions = $this->poolService->getActiveSessions($pool);
288
        $position = $sessions->filter(
289
            fn($_session) => $_session->day_date->lt($session->day_date)
290
        )->count();
291
292
        return $this->getRemitmentCount($sessions->count(),
293
            $pool->subscriptions()->count(), $position);
294
    }
295
}
296