SettlementTargetService   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 193
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 63
c 0
b 0
f 0
dl 0
loc 193
rs 10
wmc 15

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A filterTarget() 0 4 2
A getMembersWithSettlements() 0 18 1
A deleteTarget() 0 3 1
A getMemberCount() 0 3 1
A getMembersSettlements() 0 14 1
A getDeadlineSession() 0 5 1
A getTarget() 0 7 1
A getDeadlineSessions() 0 6 1
A updateTarget() 0 14 2
A createTarget() 0 16 2
A getMembersQuery() 0 4 1
1
<?php
2
3
namespace Siak\Tontine\Service\Meeting\Charge;
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\Charge;
10
use Siak\Tontine\Model\Round;
11
use Siak\Tontine\Model\Session;
12
use Siak\Tontine\Model\SettlementTarget;
13
use Siak\Tontine\Service\TenantService;
14
use Siak\Tontine\Validation\SearchSanitizer;
15
16
class SettlementTargetService
17
{
18
    /**
19
     * @param TenantService $tenantService
20
     */
21
    public function __construct(protected TenantService $tenantService,
22
        private SearchSanitizer $searchSanitizer)
23
    {}
24
25
    /**
26
     * @param Session $session
27
     * @param SettlementTarget $target
28
     *
29
     * @return bool
30
     */
31
    private function filterTarget(Session $session, SettlementTarget $target): bool
32
    {
33
        return $session->day_date >= $target->session->day_date &&
34
            $session->day_date <= $target->deadline->day_date;
35
    }
36
37
    /**
38
     * @param Charge $charge
39
     * @param Session $session
40
     *
41
     * @return SettlementTarget|null
42
     */
43
    public function getTarget(Charge $charge, Session $session): ?SettlementTarget
44
    {
45
        return $charge->targets()
46
            ->with(['session', 'deadline'])
47
            ->get()
48
            ->filter(fn($target) => $this->filterTarget($session, $target))
49
            ->first();
50
    }
51
52
    /**
53
     * @param Round $round
54
     * @param string $search
55
     *
56
     * @return Builder|Relation
57
     */
58
    private function getMembersQuery(Round $round, string $search = ''): Builder|Relation
59
    {
60
        return $round->members()
61
            ->search($this->searchSanitizer->sanitize($search));
62
    }
63
64
    /**
65
     * @param Collection $members
66
     * @param Charge $charge
67
     * @param SettlementTarget $target
68
     *
69
     * @return Collection
70
     */
71
    public function getMembersSettlements(Collection $members, Charge $charge, SettlementTarget $target): Collection
72
    {
73
        return DB::table('settlements')
74
            ->join('sessions', 'sessions.id', '=', 'settlements.session_id')
75
            ->join('bills', 'settlements.bill_id', '=', 'bills.id')
76
            ->join('libre_bills', 'libre_bills.bill_id', '=', 'bills.id')
77
            ->where('sessions.day_date', '>=', $target->session->day_date)
78
            ->where('sessions.day_date', '<=', $target->deadline->day_date)
79
            ->whereIn('libre_bills.member_id', $members->pluck('id'))
80
            ->where('libre_bills.charge_id', $charge->id)
81
            ->select('libre_bills.member_id', DB::raw('sum(bills.amount) as amount'))
82
            ->groupBy('libre_bills.member_id')
83
            ->get()
84
            ->pluck('amount', 'member_id');
85
    }
86
87
    /**
88
     * @param Round $round
89
     * @param Charge $charge
90
     * @param SettlementTarget $target
91
     * @param string $search
92
     * @param int $page
93
     *
94
     * @return Collection
95
     */
96
    public function getMembersWithSettlements(Round $round, Charge $charge,
97
        SettlementTarget $target, string $search = '', int $page = 0): Collection
98
    {
99
        return $this->getMembersQuery($round, $search)
100
            ->addSelect([
101
                'paid' => DB::table('settlements')
102
                    ->join('sessions', 'sessions.id', '=', 'settlements.session_id')
103
                    ->join('bills', 'bills.id', '=', 'settlements.bill_id')
104
                    ->join('libre_bills', 'libre_bills.bill_id', '=', 'bills.id')
105
                    ->whereColumn('libre_bills.member_id', 'members.id')
106
                    ->where('sessions.day_date', '>=', $target->session->day_date)
107
                    ->where('sessions.day_date', '<=', $target->deadline->day_date)
108
                    ->where('libre_bills.charge_id', $charge->id)
109
                    ->select(DB::raw('sum(bills.amount)'))
110
            ])
111
            ->page($page, $this->tenantService->getLimit())
112
            ->orderBy('name', 'asc')
0 ignored issues
show
Bug introduced by
'name' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderBy(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

112
            ->orderBy(/** @scrutinizer ignore-type */ 'name', 'asc')
Loading history...
113
            ->get();
114
    }
115
116
    /**
117
     * @param Round $round
118
     * @param string $search
119
     *
120
     * @return int
121
     */
122
    public function getMemberCount(Round $round, string $search = ''): int
123
    {
124
        return $this->getMembersQuery($round, $search)->count();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getMembers...ound, $search)->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...
125
    }
126
127
    /**
128
     * @param Session $currentSession
129
     *
130
     * @return Collection
131
     */
132
    public function getDeadlineSessions(Session $currentSession): Collection
133
    {
134
        return $currentSession->round->sessions()
135
            ->where('day_date', '>', $currentSession->day_date)
136
            ->orderByDesc('day_date')
137
            ->pluck('title', 'id');
138
    }
139
140
    /**
141
     * @param Session $currentSession
142
     * @param int $sessionId
143
     *
144
     * @return Session|null
145
     */
146
    private function getDeadlineSession(Session $currentSession, int $sessionId): ?Session
147
    {
148
        return $currentSession->round->sessions()
149
            ->where('day_date', '>', $currentSession->day_date)
150
            ->find($sessionId);
151
    }
152
153
    /**
154
     * @param Charge $charge
155
     * @param Session $session
156
     * @param array $values
157
     *
158
     * @return void
159
     */
160
    public function createTarget(Charge $charge, Session $session, array $values): void
161
    {
162
        $deadline = $this->getDeadlineSession($session, $values['deadline']);
163
        if(!$deadline)
164
        {
165
            // Todo: throw an exception.
166
            return;
167
        }
168
169
        $target = new SettlementTarget();
170
        $target->amount = $values['amount'];
171
        $target->global = $values['global'];
172
        $target->charge()->associate($charge);
173
        $target->session()->associate($session);
174
        $target->deadline()->associate($deadline);
175
        $target->save();
176
    }
177
178
    /**
179
     * @param SettlementTarget $target
180
     * @param Session $session
181
     * @param array $values
182
     *
183
     * @return void
184
     */
185
    public function updateTarget(SettlementTarget $target, Session $session, array $values): void
186
    {
187
        $deadline = $this->getDeadlineSession($session, $values['deadline']);
188
        if(!$deadline)
189
        {
190
            // Todo: throw an exception.
191
            return;
192
        }
193
194
        $target->amount = $values['amount'];
195
        $target->global = $values['global'];
196
        $target->session()->associate($session);
197
        $target->deadline()->associate($deadline);
198
        $target->save();
199
    }
200
201
    /**
202
     * @param SettlementTarget $target
203
     *
204
     * @return void
205
     */
206
    public function deleteTarget(SettlementTarget $target): void
207
    {
208
        $target->delete();
209
    }
210
}
211