Passed
Push — main ( 1c458a...5a987a )
by Thierry
10:56 queued 05:26
created

SummaryService   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 273
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 113
c 0
b 0
f 0
dl 0
loc 273
rs 10
wmc 25

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getFunds() 0 5 3
A getRemitments() 0 15 1
A getDeposits() 0 16 1
A getAuctions() 0 18 1
A getCollectedFigures() 0 19 3
A getSessionRemitmentCount() 0 18 3
A __construct() 0 4 1
A getPoolFigures() 0 15 3
A getPoolsBalance() 0 11 3
A getSessionFigures() 0 27 4
A getFigures() 0 18 2
1
<?php
2
3
namespace Siak\Tontine\Service\Meeting\Session;
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\Payment\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\Mee...\Session\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
        $figures = new stdClass();
196
        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...
197
        {
198
            $figures->expected = $this->getExpectedFigures($pool, $sessions);
199
        }
200
        $figures->collected = $this->getCollectedFigures($pool, $sessions);
201
        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...
202
        {
203
            $figures->auctions = $this->auctions[$pool->id] ?? collect();
204
        }
205
206
        return compact('pool', 'figures', 'sessions');
207
    }
208
209
    /**
210
     * Get the receivables of a given pool.
211
     *
212
     * @param Round $round
213
     * @param int $poolId
214
     *
215
     * @return Collection
216
     */
217
    public function getFigures(Round $round, int $poolId = 0): Collection
218
    {
219
        $pools = $round->pools()
220
            ->with(['round.guild', 'sessions'])
221
            ->whereHas('subscriptions')
222
            ->when($poolId > 0, fn($query) => $query->where('pools.id', $poolId))
223
            ->get();
224
        if($pools->count() === 0)
225
        {
226
            return collect();
227
        }
228
229
        $poolIds = $pools->pluck('id');
230
        $this->getDeposits($round, $poolIds);
231
        $this->getRemitments($round, $poolIds);
232
        $this->getAuctions($round, $poolIds);
233
234
        return $pools->map(fn(Pool $pool) => $this->getPoolFigures($pool));
235
    }
236
237
    /**
238
     * @param Collection $figures
239
     *
240
     * @return array
241
     */
242
    public function getPoolsBalance(Collection $figures): array
243
    {
244
        $pools = [];
245
        foreach($figures as $poolData)
246
        {
247
            foreach($poolData['figures']->collected as $sessionId => $collected)
248
            {
249
                $pools[$sessionId] = ($pools[$sessionId] ?? 0) + $collected->cashier->end;
250
            }
251
        }
252
        return $pools;
253
    }
254
255
    /**
256
     * Get the funds.
257
     *
258
     * @param Round $round
259
     *
260
     * @return Collection
261
     */
262
    public function getFunds(Round $round): Collection
263
    {
264
        return Fund::ofRound($round)->get()
265
            ->filter(fn($fund) => $fund->start_amount > 0 ||
266
                $fund->end_amount > 0 || $fund->profit_amount > 0);
267
    }
268
269
    /**
270
     * @param Pool $pool
271
     * @param Session $session
272
     *
273
     * @return int
274
     */
275
    public function getSessionRemitmentCount(Pool $pool, Session $session): int
276
    {
277
        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...
278
        {
279
            return -1;
280
        }
281
        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...
282
        {
283
            return 1;
284
        }
285
286
        $sessions = $this->poolService->getActiveSessions($pool);
287
        $position = $sessions->filter(
288
            fn($_session) => $_session->day_date->lt($session->day_date)
289
        )->count();
290
291
        return $this->getRemitmentCount($sessions->count(),
292
            $pool->subscriptions()->count(), $position);
293
    }
294
}
295