Passed
Pull Request — main (#63)
by Thierry
06:38
created

Pool::startDate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Siak\Tontine\Model;
4
5
use Carbon\Carbon;
6
use Database\Factories\PoolFactory;
7
use Illuminate\Database\Eloquent\Casts\Attribute;
8
use Illuminate\Database\Eloquent\Builder;
9
use Illuminate\Database\Eloquent\Collection;
10
use Illuminate\Database\Eloquent\Factories\Factory;
11
use Illuminate\Database\Eloquent\Factories\HasFactory;
12
use Illuminate\Support\Facades\DB;
13
use Siak\Tontine\Model\Traits\HasCurrency;
14
15
use function trans;
16
17
/**
18
 * @property string $title
19
 * @property int $amount
20
 * @property string $notes
21
 * @property array $properties
22
 * @property-read Carbon $start_at
23
 * @property-read Carbon $end_at
24
 * @property-read string $start_date
25
 * @property-read string $end_date
26
 * @property-read bool $deposit_fixed
27
 * @property-read bool $deposit_lendable
28
 * @property-read bool $remit_planned
29
 * @property-read bool $remit_auction
30
 * @property-read bool $remit_payable
31
 * @property-read Collection $subscriptions
32
 * @property-read Collection $sessions
33
 * @property-read Collection $disabled_sessions
34
 * @property-read Round $round
35
 * @property-read PoolRound $pool_round
36
 * @property-read Tontine $tontine
37
 * @method static Builder ofSession(Session $session)
38
 * @method static Builder ofRound(Round $round)
39
 */
40
class Pool extends Base
41
{
42
    use HasFactory;
43
    use HasCurrency;
44
45
    /**
46
     * Indicates if the model should be timestamped.
47
     *
48
     * @var bool
49
     */
50
    public $timestamps = false;
51
52
    /**
53
     * The attributes that are mass assignable.
54
     *
55
     * @var array
56
     */
57
    protected $fillable = [
58
        'title',
59
        'amount',
60
        'notes',
61
        'properties',
62
    ];
63
64
    /**
65
     * The attributes that should be cast.
66
     *
67
     * @var array
68
     */
69
    protected $casts = [
70
        'start_at' => 'datetime',
71
        'end_at' => 'datetime',
72
        'properties' => 'array',
73
    ];
74
75
    /**
76
     * The model's default values for attributes.
77
     *
78
     * @var array
79
     */
80
    protected $attributes = [
81
        'properties' => '{}',
82
    ];
83
84
    /**
85
     * The relationships that should always be loaded.
86
     *
87
     * @var array
88
     */
89
    protected $with = [
90
        'pool_round',
91
    ];
92
93
    /**
94
     * Create a new factory instance for the model.
95
     *
96
     * @return Factory
97
     */
98
    protected static function newFactory()
99
    {
100
        return PoolFactory::new();
101
    }
102
103
    /**
104
     * The "booted" method of the model.
105
     *
106
     * @return void
107
     */
108
    protected static function booted()
109
    {
110
        static::addGlobalScope('dates', function (Builder $query) {
111
            $query
112
                ->addSelect(['pools.*', 'v.end_at', 'v.start_at', 'v.tontine_id'])
113
                ->join(DB::raw('v_pools as v'), 'v.id', '=', 'pools.id');
114
        });
115
    }
116
117
    /**
118
     * @param Builder $query
119
     * @param Carbon $startDate
120
     * @param Carbon $endDate
121
     *
122
     * @return Builder
123
     */
124
    private function filterOnDates(Builder $query, Carbon $startDate, Carbon $endDate): Builder
125
    {
126
        return $query
0 ignored issues
show
Bug Best Practice introduced by
The expression return $query->whereDate...dDate->format('Y-m-d')) 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...
127
            ->whereDate('v.end_at', '>=', $startDate->format('Y-m-d'))
128
            ->whereDate('v.start_at', '<=', $endDate->format('Y-m-d'));
129
    }
130
131
    /**
132
     * Scope to active pools for a given round.
133
     *
134
     * @param Builder $query
135
     * @param Round $round
136
     *
137
     * @return Builder
138
     */
139
    public function scopeOfRound(Builder $query, Round $round): Builder
140
    {
141
        return $query->where(function($query) use($round) {
142
            $query->where('pools.round_id', $round->id)
143
                ->when($round->start_at !== null && $round->end_at !== null,
0 ignored issues
show
Bug introduced by
The property end_at 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...
Bug introduced by
The property start_at 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...
144
                    function($query) use($round) {
145
                        $query->orWhere(function($query) use($round) {
146
                            // Take the other pools of the tontine with overlapped sessions.
147
                            $query->where('v.tontine_id', $round->tontine_id);
148
                            $this->filterOnDates($query, $round->start_at, $round->end_at);
0 ignored issues
show
Bug introduced by
The property start_at 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...
Bug introduced by
The property end_at 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...
149
                        });
150
                    });
151
        });
152
    }
153
154
    /**
155
     * Scope to active pools for a given session.
156
     *
157
     * @param Builder $query
158
     * @param Session $session
159
     *
160
     * @return Builder
161
     */
162
    public function scopeOfSession(Builder $query, Session $session): Builder
163
    {
164
        $query->where('v.tontine_id', $session->round->tontine_id);
165
        return $this->filterOnDates($query, $session->start_at, $session->start_at)
0 ignored issues
show
Bug introduced by
$session->start_at of type string is incompatible with the type Carbon\Carbon expected by parameter $startDate of Siak\Tontine\Model\Pool::filterOnDates(). ( Ignorable by Annotation )

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

165
        return $this->filterOnDates($query, /** @scrutinizer ignore-type */ $session->start_at, $session->start_at)
Loading history...
Bug Best Practice introduced by
The expression return $this->filterOnDa...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...
Bug introduced by
$session->start_at of type string is incompatible with the type Carbon\Carbon expected by parameter $endDate of Siak\Tontine\Model\Pool::filterOnDates(). ( Ignorable by Annotation )

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

165
        return $this->filterOnDates($query, $session->start_at, /** @scrutinizer ignore-type */ $session->start_at)
Loading history...
166
            // Also filter on enabled sessions.
167
            ->whereDoesntHave('disabled_sessions',
168
                fn($q) => $q->where('sessions.id', $session->id));
169
    }
170
171
    public function startDate(): Attribute
172
    {
173
        return Attribute::make(
174
            get: fn() => $this->start_at->translatedFormat(trans('tontine.date.format')),
175
        );
176
    }
177
178
    public function endDate(): Attribute
179
    {
180
        return Attribute::make(
181
            get: fn() => $this->end_at->translatedFormat(trans('tontine.date.format')),
182
        );
183
    }
184
185
    public function depositFixed(): Attribute
186
    {
187
        return Attribute::make(
188
            get: fn() => ($this->properties['deposit']['fixed'] ?? true) === true,
189
        );
190
    }
191
192
    public function depositLendable(): Attribute
193
    {
194
        return Attribute::make(
195
            get: fn() => ($this->properties['deposit']['lendable'] ?? false) === true,
196
        );
197
    }
198
199
    public function remitPlanned(): Attribute
200
    {
201
        return Attribute::make(
202
            get: fn() => ($this->properties['remit']['planned'] ?? true) === true,
203
        );
204
    }
205
206
    public function remitAuction(): Attribute
207
    {
208
        return Attribute::make(
209
            get: fn() => ($this->properties['remit']['auction'] ?? false) === true,
210
        );
211
    }
212
213
    public function remitPayable(): Attribute
214
    {
215
        return Attribute::make(
216
            get: fn() => $this->remit_planned && !$this->remit_auction,
217
        );
218
    }
219
220
    public function round()
221
    {
222
        return $this->belongsTo(Round::class);
223
    }
224
225
    public function pool_round()
226
    {
227
        return $this->hasOne(PoolRound::class);
228
    }
229
230
    public function counter()
231
    {
232
        return $this->hasOne(PoolCounter::class, 'id');
233
    }
234
235
    public function subscriptions()
236
    {
237
        return $this->hasMany(Subscription::class);
238
    }
239
240
    public function tontine()
241
    {
242
        // The "tontine_id" field is added to the table by the join
243
        // with the v_pools view. So we can now add this relationship.
244
        return $this->belongsTo(Tontine::class);
245
    }
246
247
    public function disabled_sessions()
248
    {
249
        return $this->belongsToMany(Session::class, 'pool_session_disabled');
250
    }
251
}
252