Issues (214)

src/Model/Fund.php (10 issues)

1
<?php
2
3
namespace Siak\Tontine\Model;
4
5
use Carbon\Carbon;
6
use Illuminate\Database\Eloquent\Casts\Attribute;
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Support\Facades\DB;
9
10
use function trans;
11
12
class Fund extends Base
13
{
14
    use Traits\DateFormatter;
15
16
    /**
17
     * Indicates if the model should be timestamped.
18
     *
19
     * @var bool
20
     */
21
    public $timestamps = false;
22
23
    /**
24
     * The attributes that are mass assignable.
25
     *
26
     * @var array
27
     */
28
    protected $fillable = [
29
        'options',
30
        'def_id',
31
        'round_id',
32
        'start_sid',
33
        'end_sid',
34
        'interest_sid',
35
        'pool_id',
36
    ];
37
38
    /**
39
     * The model's default values for attributes.
40
     *
41
     * @var array
42
     */
43
    protected $attributes = [
44
        'options' => '{}',
45
    ];
46
47
    /**
48
     * The relationships that should always be loaded.
49
     *
50
     * @var array
51
     */
52
    protected $with = [
53
        'def',
54
    ];
55
56
    /**
57
     * The "booted" method of the model.
58
     *
59
     * @return void
60
     */
61
    protected static function booted()
62
    {
63
        // Scope for fund sessions. Always applied by default.
64
        static::addGlobalScope('sessions', function (Builder $query) {
65
            $query->addSelect([
66
                'funds.*',
67
                'v.end_date',
68
                'v.start_date',
69
                'v.interest_date',
70
                'v.sessions_count',
71
            ])->join(DB::raw('v_funds as v'), 'v.fund_id', '=', 'funds.id');
72
        });
73
    }
74
75
    /**
76
     * Get the attributes that should be cast.
77
     *
78
     * @return array<string, string>
79
     */
80
    protected function casts(): array
81
    {
82
        return [
83
            'options' => 'array',
84
            'start_date' => 'datetime:Y-m-d',
85
            'end_date' => 'datetime:Y-m-d',
86
            'interest_date' => 'datetime:Y-m-d',
87
        ];
88
    }
89
90
    public function title(): Attribute
91
    {
92
        return Attribute::make(
93
            get: fn() => match(true) {
94
                $this->def->type_user => $this->def->title,
0 ignored issues
show
The property type_user does not seem to exist on Siak\Tontine\Model\FundDef. 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...
95
                $this->pool !== null => $this->pool->title,
0 ignored issues
show
The property title 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...
96
                default => trans('tontine.fund.labels.default'),
97
            },
98
        );
99
    }
100
101
    public function notes(): Attribute
102
    {
103
        return Attribute::make(
104
            get: fn() => $this->def->notes,
105
        );
106
    }
107
108
    /**
109
     * Get the start amount.
110
     *
111
     * @return Attribute
112
     */
113
    public function startAmount(): Attribute
114
    {
115
        return Attribute::make(
116
            get: fn() => $this->options['amount']['start'] ?? 0,
117
        );
118
    }
119
120
    /**
121
     * Get the end amount.
122
     *
123
     * @return Attribute
124
     */
125
    public function endAmount(): Attribute
126
    {
127
        return Attribute::make(
128
            get: fn() => $this->options['amount']['end'] ?? 0,
129
        );
130
    }
131
132
    /**
133
     * Get the profit amount.
134
     *
135
     * @return Attribute
136
     */
137
    protected function profitAmount(): Attribute
138
    {
139
        return Attribute::make(
140
            get: fn() => $this->options['amount']['profit'] ?? 0,
141
        );
142
    }
143
144
    /**
145
     * @param Builder $query
146
     * @param Carbon $startDate
147
     * @param Carbon $endDate
148
     *
149
     * @return Builder
150
     */
151
    private function filterOnDates(Builder $query, Carbon $startDate, Carbon $endDate): Builder
152
    {
153
        return $query->where('v.end_date', '>=', $startDate)
154
            ->where('v.start_date', '<=', $endDate);
155
    }
156
157
    /**
158
     * Scope to active pools for a given round.
159
     *
160
     * @param Builder $query
161
     * @param Round $round
162
     *
163
     * @return Builder
164
     */
165
    public function scopeOfRound(Builder $query, Round $round): Builder
166
    {
167
        $query->whereHas('def', fn($q) => $q->where('guild_id', $round->guild_id));
0 ignored issues
show
The property guild_id does not exist on Siak\Tontine\Model\Round. Did you mean guild?
Loading history...
168
        return $this->filterOnDates($query, $round->start_date, $round->end_date);
0 ignored issues
show
The property start_date does not seem to exist on Siak\Tontine\Model\Round. 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...
The property end_date does not seem to exist on Siak\Tontine\Model\Round. 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...
169
    }
170
171
    /**
172
     * Scope to active pools for a given session.
173
     *
174
     * @param Builder $query
175
     * @param Session $session
176
     *
177
     * @return Builder
178
     */
179
    public function scopeOfSession(Builder $query, Session $session): Builder
180
    {
181
        $query->whereHas('def', fn($q) => $q->where('guild_id', $session->round->guild_id));
0 ignored issues
show
The property guild_id does not exist on Siak\Tontine\Model\Round. Did you mean guild?
Loading history...
182
        return $this->filterOnDates($query, $session->day_date, $session->day_date);
0 ignored issues
show
$session->day_date of type string is incompatible with the type Carbon\Carbon expected by parameter $endDate of Siak\Tontine\Model\Fund::filterOnDates(). ( Ignorable by Annotation )

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

182
        return $this->filterOnDates($query, $session->day_date, /** @scrutinizer ignore-type */ $session->day_date);
Loading history...
$session->day_date of type string is incompatible with the type Carbon\Carbon expected by parameter $startDate of Siak\Tontine\Model\Fund::filterOnDates(). ( Ignorable by Annotation )

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

182
        return $this->filterOnDates($query, /** @scrutinizer ignore-type */ $session->day_date, $session->day_date);
Loading history...
183
    }
184
185
    public function def()
186
    {
187
        return $this->belongsTo(FundDef::class, 'def_id');
188
    }
189
190
    public function start()
191
    {
192
        return $this->belongsTo(Session::class, 'start_sid');
193
    }
194
195
    public function end()
196
    {
197
        return $this->belongsTo(Session::class, 'end_sid');
198
    }
199
200
    public function interest()
201
    {
202
        return $this->belongsTo(Session::class, 'interest_sid');
203
    }
204
205
    public function round()
206
    {
207
        return $this->belongsTo(Round::class);
208
    }
209
210
    public function pool()
211
    {
212
        return $this->belongsTo(Pool::class);
213
    }
214
215
    public function sessions()
216
    {
217
        return $this->belongsToMany(Session::class, 'v_fund_session');
218
    }
219
220
    public function savings()
221
    {
222
        return $this->hasMany(Saving::class);
223
    }
224
225
    /**
226
     * @param  Builder  $query
227
     *
228
     * @return Builder
229
     */
230
    public function scopeReal(Builder $query): Builder
231
    {
232
        return $query->whereNull('pool_id');
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->whereNull('pool_id') 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...
233
    }
234
235
    /**
236
     * @param  Builder  $query
237
     *
238
     * @return Builder
239
     */
240
    public function scopeUser(Builder $query): Builder
241
    {
242
        return $query->whereHas('def', fn($def) => $def->user());
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->whereHas(...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...
243
    }
244
}
245