Passed
Push — main ( 891842...6f03e1 )
by Thierry
05:41
created

Bill::scopeOfRound()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 31
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 25
nc 1
nop 2
dl 0
loc 31
rs 9.52
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
     * The attributes that should be mutated to dates.
54
     *
55
     * @var array
56
     */
57
    protected $dates = [
58
        'issued_at',
59
        'deadline',
60
    ];
61
62
63
    /**
64
     * @return Attribute
65
     */
66
    protected function libre(): Attribute
67
    {
68
        return Attribute::make(
69
            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...
70
        );
71
    }
72
73
    public function session()
74
    {
75
        return $this->belongsTo(Session::class);
76
    }
77
78
    public function settlement()
79
    {
80
        return $this->hasOne(Settlement::class);
81
    }
82
83
    public function tontine_bill()
84
    {
85
        return $this->hasOne(TontineBill::class);
86
    }
87
88
    public function round_bill()
89
    {
90
        return $this->hasOne(RoundBill::class);
91
    }
92
93
    public function session_bill()
94
    {
95
        return $this->hasOne(SessionBill::class);
96
    }
97
98
    public function libre_bill()
99
    {
100
        return $this->hasOne(LibreBill::class);
101
    }
102
103
    /**
104
     * @param  Builder  $query
105
     *
106
     * @return Builder
107
     */
108
    public function scopePaid(Builder $query): Builder
109
    {
110
        return $query->whereHas('settlement');
111
    }
112
113
    /**
114
     * @param  Builder  $query
115
     *
116
     * @return Builder
117
     */
118
    public function scopeUnpaid(Builder $query): Builder
119
    {
120
        return $query->whereDoesntHave('settlement');
121
    }
122
123
    /**
124
     * @param  Builder  $query
125
     *
126
     * @return Builder
127
     */
128
    public function scopeLibre(Builder $query): Builder
129
    {
130
        return $query->where('v.bill_type', self::TYPE_LIBRE);
131
    }
132
133
    /**
134
     * @param  Builder  $query
135
     *
136
     * @return Builder
137
     */
138
    public function scopeFixed(Builder $query): Builder
139
    {
140
        return $query->where('v.bill_type', '!=', self::TYPE_LIBRE);
141
    }
142
143
    /**
144
     * @param  Builder  $query
145
     * @param Session $session
146
     *
147
     * @return Builder
148
     */
149
    public function scopeOfSession(Builder $query, Session $session): Builder
150
    {
151
        return $query->addSelect(['bills.*', 'v.*', DB::raw('s.start_at 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...
152
            ->join(DB::raw('v_bills as v'), 'v.bill_id', '=', 'bills.id')
153
            ->join(DB::raw('sessions as s'), 'v.session_id', '=', 's.id')
154
            ->where(function($query) use($session) {
155
                $query->orWhere(function($query) use($session) {
156
                    $query->where('v.bill_type', self::TYPE_LIBRE)
157
                        ->where('v.round_id', $session->round_id)
158
                        ->whereDate('s.start_at', '<=', $session->start_at);
159
                })
160
                ->orWhere(function($query) use($session) {
161
                    $query->where('v.bill_type', self::TYPE_SESSION)
162
                        ->where('v.session_id', $session->id);
163
                })
164
                ->orWhere(function($query) use($session) {
165
                    $query->where('v.bill_type', self::TYPE_ROUND)
166
                        ->where('v.round_id', $session->round_id);
167
                })
168
                ->orWhere(function($query) use($session) {
169
                    $query->where('v.bill_type', self::TYPE_TONTINE)
170
                        ->where('v.tontine_id', $session->round->tontine_id)
171
                        ->whereDate('s.start_at', '<=', $session->start_at);
172
                });
173
            })
174
            ->where(function(Builder $query) use($session) {
175
                // The bills that are not yet paid, or that are paid in this round.
176
                $query->orWhere(function(Builder $query) {
177
                    $query->whereDoesntHave('settlement');
178
                })
179
                ->orWhere(function(Builder $query) use($session) {
180
                    $query->whereHas('settlement', function(Builder $query) use($session) {
181
                        $query->where('session_id', $session->id);
182
                    });
183
                });
184
            });
185
    }
186
187
    /**
188
     * @param Builder $query
189
     * @param Session $session
190
     *
191
     * @return Builder
192
     */
193
    public function scopeOfRound(Builder $query, Session $session): Builder
194
    {
195
        return $query->addSelect(['bills.*', 'v.*', DB::raw('s.start_at 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...
196
            ->join(DB::raw('v_bills as v'), 'v.bill_id', '=', 'bills.id')
197
            ->join(DB::raw('sessions as s'), 'v.session_id', '=', 's.id')
198
            ->where(function($query) use($session) {
199
                $query->orWhere(function($query) use($session) {
200
                    $query->where('v.bill_type', self::TYPE_LIBRE)
201
                        ->where('v.round_id', $session->round_id)
202
                        ->whereDate('s.start_at', '<', $session->start_at);
203
                })
204
                ->orWhere(function($query) use($session) {
205
                    $query->where('v.bill_type', self::TYPE_SESSION)
206
                        ->where('v.round_id', $session->round_id)
207
                        ->whereDate('s.start_at', '<', $session->start_at);
208
                })
209
                ->orWhere(function($query) use($session) {
210
                    $query->where('v.bill_type', self::TYPE_ROUND)
211
                        ->where('v.round_id', $session->round_id);
212
                })
213
                ->orWhere(function($query) use($session) {
214
                    $query->where('v.bill_type', self::TYPE_TONTINE)
215
                        ->where('v.tontine_id', $session->round->tontine_id)
216
                        ->where(function($query) use($session) {
217
                            $query->orWhere(function(Builder $query) {
218
                                $query->whereDoesntHave('settlement');
219
                            })
220
                            ->orWhere(function(Builder $query) use($session) {
221
                                $query->whereHas('settlement', function(Builder $query) use($session) {
222
                                    $query->whereHas('session', function(Builder $query) use($session) {
223
                                        $query->where('round_id', $session->round_id);
224
                                    });
225
                                });
226
                            });
227
                        });
228
                });
229
            });
230
    }
231
}
232