Passed
Push — main ( 9b7af3...eeb558 )
by Thierry
05:55
created

Bill::scopeSearch()   A

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
nc 1
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Siak\Tontine\Model;
4
5
use Illuminate\Database\Eloquent\Casts\Attribute;
6
use Illuminate\Database\Eloquent\Builder;
7
use Illuminate\Support\Facades\DB;
8
9
class Bill extends Base
10
{
11
    /**
12
     * @const
13
     */
14
    const TYPE_LIBRE = 0;
15
16
    /**
17
     * @const
18
     */
19
    const TYPE_SESSION = 1;
20
21
    /**
22
     * @const
23
     */
24
    const TYPE_ROUND = 2;
25
26
    /**
27
     * @const
28
     */
29
    const TYPE_TONTINE = 3;
30
31
    /**
32
     * Indicates if the model should be timestamped.
33
     *
34
     * @var bool
35
     */
36
    public $timestamps = false;
37
38
    /**
39
     * The attributes that are mass assignable.
40
     *
41
     * @var array
42
     */
43
    protected $fillable = [
44
        'charge',
45
        'amount',
46
        'lendable',
47
        'issued_at',
48
        'deadline',
49
        'notes',
50
    ];
51
52
    /**
53
     * Get the attributes that should be cast.
54
     *
55
     * @return array<string, string>
56
     */
57
    protected function casts(): array
58
    {
59
        return [
60
            'issued_at' => 'datetime',
61
            'deadline' => 'datetime',
62
        ];
63
    }
64
65
    /**
66
     * @return Attribute
67
     */
68
    protected function libre(): Attribute
69
    {
70
        return Attribute::make(
71
            get: fn() => $this->bill_type === self::TYPE_LIBRE,
0 ignored issues
show
Bug introduced by
The property bill_type does not seem to exist on Siak\Tontine\Model\Bill. 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...
72
        );
73
    }
74
75
    public function session()
76
    {
77
        return $this->belongsTo(Session::class);
78
    }
79
80
    public function settlement()
81
    {
82
        return $this->hasOne(Settlement::class);
83
    }
84
85
    public function oneoff_bill()
86
    {
87
        return $this->hasOne(OneoffBill::class);
88
    }
89
90
    public function round_bill()
91
    {
92
        return $this->hasOne(RoundBill::class);
93
    }
94
95
    public function session_bill()
96
    {
97
        return $this->hasOne(SessionBill::class);
98
    }
99
100
    public function libre_bill()
101
    {
102
        return $this->hasOne(LibreBill::class);
103
    }
104
105
    /**
106
     * @param  Builder  $query
107
     *
108
     * @return Builder
109
     */
110
    public function scopePaid(Builder $query): Builder
111
    {
112
        return $query->whereHas('settlement');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->whereHas('settlement') could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
113
    }
114
115
    /**
116
     * @param  Builder  $query
117
     *
118
     * @return Builder
119
     */
120
    public function scopeUnpaid(Builder $query): Builder
121
    {
122
        return $query->whereDoesntHave('settlement');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->whereDoesntHave('settlement') could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
123
    }
124
125
    /**
126
     * @param  Builder  $query
127
     *
128
     * @return Builder
129
     */
130
    public function scopeLibre(Builder $query): Builder
131
    {
132
        return $query->where('v.bill_type', self::TYPE_LIBRE);
133
    }
134
135
    /**
136
     * @param  Builder  $query
137
     *
138
     * @return Builder
139
     */
140
    public function scopeFixed(Builder $query): Builder
141
    {
142
        return $query->where('v.bill_type', '!=', self::TYPE_LIBRE);
143
    }
144
145
    /**
146
     * @param  Builder  $query
147
     * @param Session $session
148
     *
149
     * @return Builder
150
     */
151
    public function scopeOfSession(Builder $query, Session $session): Builder
152
    {
153
        return $query->addSelect(['bills.*', 'v.*', DB::raw('s.day_date as bill_date')])
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->addSelect...ion(...) { /* ... */ }) could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
154
            ->join(DB::raw('v_bills as v'), 'v.bill_id', '=', 'bills.id')
155
            ->join(DB::raw('sessions as s'), 'v.session_id', '=', 's.id')
156
            ->where(function($query) use($session) {
157
                $query->orWhere(function($query) use($session) {
158
                    $query->where('v.bill_type', self::TYPE_LIBRE)
159
                        ->where('v.round_id', $session->round_id)
160
                        ->where('s.day_date', '<=', $session->day_date);
161
                })
162
                ->orWhere(function($query) use($session) {
163
                    $query->where('v.bill_type', self::TYPE_SESSION)
164
                        ->where('v.session_id', $session->id);
165
                })
166
                ->orWhere(function($query) use($session) {
167
                    $query->where('v.bill_type', self::TYPE_ROUND)
168
                        ->where('v.round_id', $session->round_id);
169
                })
170
                ->orWhere(function($query) use($session) {
171
                    $query->where('v.bill_type', self::TYPE_TONTINE)
172
                        ->where('v.guild_id', $session->round->guild_id)
0 ignored issues
show
Bug introduced by
The property guild_id does not exist on Siak\Tontine\Model\Round. Did you mean guild?
Loading history...
173
                        ->where('s.day_date', '<=', $session->day_date);
174
                });
175
            })
176
            ->where(function(Builder $query) use($session) {
177
                // The bills that are not yet paid, or that are paid in this round.
178
                $query->orWhere(function(Builder $query) {
179
                    $query->whereDoesntHave('settlement');
180
                })
181
                ->orWhere(function(Builder $query) use($session) {
182
                    $query->whereHas('settlement', function(Builder $query) use($session) {
183
                        $query->where('session_id', $session->id);
184
                    });
185
                });
186
            });
187
    }
188
189
    /**
190
     * @param Builder $query
191
     * @param Session $session
192
     *
193
     * @return Builder
194
     */
195
    public function scopeOfRound(Builder $query, Session $session): Builder
196
    {
197
        return $query->addSelect(['bills.*', 'v.*', DB::raw('s.day_date as bill_date')])
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->addSelect...ion(...) { /* ... */ }) could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
198
            ->join(DB::raw('v_bills as v'), 'v.bill_id', '=', 'bills.id')
199
            ->join(DB::raw('sessions as s'), 'v.session_id', '=', 's.id')
200
            ->where(function($query) use($session) {
201
                $query->orWhere(function($query) use($session) {
202
                    $query->where('v.bill_type', self::TYPE_LIBRE)
203
                        ->where('v.round_id', $session->round_id)
204
                        ->where('s.day_date', '<', $session->day_date);
205
                })
206
                ->orWhere(function($query) use($session) {
207
                    $query->where('v.bill_type', self::TYPE_SESSION)
208
                        ->where('v.round_id', $session->round_id)
209
                        ->where('s.day_date', '<', $session->day_date);
210
                })
211
                ->orWhere(function($query) use($session) {
212
                    $query->where('v.bill_type', self::TYPE_ROUND)
213
                        ->where('v.round_id', $session->round_id);
214
                })
215
                ->orWhere(function($query) use($session) {
216
                    $query->where('v.bill_type', self::TYPE_TONTINE)
217
                        ->where('v.guild_id', $session->round->guild_id)
0 ignored issues
show
Bug introduced by
The property guild_id does not exist on Siak\Tontine\Model\Round. Did you mean guild?
Loading history...
218
                        ->where(function($query) use($session) {
219
                            $query->orWhere(function(Builder $query) {
220
                                $query->whereDoesntHave('settlement');
221
                            })
222
                            ->orWhere(function(Builder $query) use($session) {
223
                                $query->whereHas('settlement', function(Builder $query) use($session) {
224
                                    $query->whereHas('session', function(Builder $query) use($session) {
225
                                        $query->where('round_id', $session->round_id);
226
                                    });
227
                                });
228
                            });
229
                        });
230
                });
231
            });
232
    }
233
234
    /**
235
     * @param Builder $query
236
     * @param Charge $charge
237
     * @param bool $withLibre
238
     *
239
     * @return Builder
240
     */
241
    public function scopeOfCharge(Builder $query, Charge $charge, bool $withLibre): Builder
242
    {
243
        return $query->addSelect(['bills.*'])
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->addSelect...ion(...) { /* ... */ }) could return the type Illuminate\Database\Query\Builder which is incompatible with the type-hinted return Illuminate\Database\Eloquent\Builder. Consider adding an additional type-check to rule them out.
Loading history...
244
            ->where(function($query) use($charge, $withLibre) {
245
                $query->orWhereHas('oneoff_bill', function($query) use($charge) {
246
                        $query->where('charge_id', $charge->id);
247
                    })
248
                    ->orWhereHas('round_bill', function($query) use($charge) {
249
                        $query->where('charge_id', $charge->id);
250
                    })
251
                    ->orWhereHas('session_bill', function($query) use($charge) {
252
                        $query->where('charge_id', $charge->id);
253
                    })
254
                    ->when($withLibre, function($query) use($charge) {
255
                        $query->orWhereHas('libre_bill', function($query) use($charge) {
256
                            $query->where('charge_id', $charge->id);
257
                        });
258
                    });
259
            });
260
    }
261
262
    /**
263
     * @param  Builder  $query
264
     * @param  string $search
265
     *
266
     * @return Builder
267
     */
268
    public function scopeSearch(Builder $query, string $search): Builder
269
    {
270
        return $query
271
            ->when($search !== '', fn($query) => $query
272
                ->where(DB::raw('lower(member)'), 'like', "%{$search}%"));
273
    }
274
}
275