Passed
Push — main ( a28ddf...3e6196 )
by Michael
04:09
created

Coupon   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 27
c 2
b 0
f 1
dl 0
loc 108
ccs 22
cts 22
cp 1
rs 10
wmc 12

7 Methods

Rating   Name   Duplication   Size   Complexity  
A isOverQuantity() 0 5 2
A __construct() 0 5 1
A isNotExpired() 0 3 1
A isExpired() 0 5 2
A redeemer() 0 5 2
A isRedeemedBy() 0 9 2
A isOverLimitFor() 0 5 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\Couponables\Models;
6
7
use Illuminate\Database\Eloquent\Factories\HasFactory;
8
use Illuminate\Database\Eloquent\Model;
9
use MichaelRubel\Couponables\Models\Contracts\CouponContract;
10
use MichaelRubel\Couponables\Models\Traits\DefinesColumns;
11
12
class Coupon extends Model implements CouponContract
13
{
14
    use HasFactory, DefinesColumns;
15
16
    /**
17
     * The attributes that aren't mass assignable.
18
     *
19
     * @var array<string>|bool
20
     */
21
    protected $guarded = [];
22
23
    /**
24
     * The attributes that should be cast.
25
     *
26
     * @var array
27
     */
28
    protected $casts = [
29
        'code'     => 'string',
30
        'data'     => 'collection',
31
        'quantity' => 'integer',
32
        'limit'    => 'integer',
33
        'datetime' => 'datetime',
34
    ];
35
36
    /**
37
     * @param array $attributes
38
     */
39 21
    public function __construct(array $attributes = [])
40
    {
41 21
        parent::__construct($attributes);
42
43 21
        $this->table = config('couponables.table', 'coupons');
44
    }
45
46
    /**
47
     * @return Model|null
48
     */
49 2
    public function redeemer(): ?Model
50
    {
51 2
        return $this->isMorphColumnsFilled()
52 2
            ? $this->morphTo()->first()
53 2
            : null;
54
    }
55
56
    /**
57
     * Check if code is expired.
58
     *
59
     * @return bool
60
     */
61 16
    public function isExpired(): bool
62
    {
63 16
        $expires_at = $this->{call(CouponContract::class)->getExpiresAtColumn()};
64
65 16
        return $expires_at && now()->gte($expires_at);
66
    }
67
68
    /**
69
     * Check if code is not expired.
70
     *
71
     * @return bool
72
     */
73 1
    public function isNotExpired(): bool
74
    {
75 1
        return ! call($this)->isExpired();
76
    }
77
78
    /**
79
     * Check if code amount is over.
80
     *
81
     * @return bool
82
     */
83 13
    public function isOverQuantity(): bool
84
    {
85 13
        $quantity = $this->{call(CouponContract::class)->getQuantityColumn()};
86
87 13
        return ! is_null($quantity) && $quantity <= 0;
88
    }
89
90
    /**
91
     * Check if coupon is already redeemed by the model.
92
     *
93
     * @param Model $redeemer
94
     *
95
     * @return bool
96
     */
97 2
    public function isRedeemedBy(Model $redeemer): bool
98
    {
99 2
        $column = call(CouponContract::class)->getCodeColumn();
100 2
        $code   = $this->{$column};
101
102 2
        return ! is_null($code) && $redeemer
103
            ->coupons()
104
            ->where($column, $code)
105
            ->exists();
106
    }
107
108
    /**
109
     * Check if code is for one-time use.
110
     *
111
     * @param Model $redeemer
112
     *
113
     * @return bool
114
     */
115 13
    public function isOverLimitFor(Model $redeemer): bool
116
    {
117 13
        $limit = $this->{call(CouponContract::class)->getLimitColumn()};
118
119 13
        return ! is_null($limit) && $limit <= $redeemer->coupons()->count();
120
    }
121
}
122