Completed
Push — master ( b4cd60...2701aa )
by Scott
03:56
created

Discount::getProductIds()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
rs 9.4285
cc 1
eloc 8
nc 1
nop 0
1
<?php namespace Bedard\Shop\Models;
2
3
use Carbon\Carbon;
4
use Flash;
5
use Lang;
6
use Model;
7
use October\Rain\Database\ModelException;
8
9
/**
10
 * Discount Model.
11
 */
12
class Discount extends Model
13
{
14
    use \Bedard\Shop\Traits\Subqueryable,
15
        \Bedard\Shop\Traits\Timeable,
16
        \October\Rain\Database\Traits\Purgeable,
17
        \October\Rain\Database\Traits\Validation;
18
19
    /**
20
     * @var string The database table used by the model.
21
     */
22
    public $table = 'bedard_shop_discounts';
23
24
    /**
25
     * @var array Default attributes
26
     */
27
    public $attributes = [
28
        'is_percentage' => true,
29
    ];
30
31
    /**
32
     * @var array Guarded fields
33
     */
34
    protected $guarded = ['*'];
35
36
    /**
37
     * @var array Fillable fields
38
     */
39
    protected $fillable = [
40
        'amount',
41
        'amount_exact',
42
        'amount_percentage',
43
        'end_at',
44
        'is_percentage',
45
        'name',
46
        'start_at',
47
    ];
48
49
    /**
50
     * @var array Purgeable vields
51
     */
52
    protected $purgeable = [
53
        'amount_exact',
54
        'amount_percentage',
55
    ];
56
57
    /**
58
     * @var array Relations
59
     */
60
    public $belongsToMany = [
61
        'categories' => [
62
            'Bedard\Shop\Models\Category',
63
            'table' => 'bedard_shop_category_discount',
64
        ],
65
        'products' => [
66
            'Bedard\Shop\Models\Product',
67
            'table' => 'bedard_shop_discount_product',
68
        ],
69
    ];
70
71
    public $hasMany = [
72
        'prices' => [
73
            'Bedard\Shop\Models\Price',
74
            'delete' => true,
75
        ],
76
    ];
77
78
    /**
79
     * @var  array Validation rules
80
     */
81
    public $rules = [
82
        'end_at' => 'date',
83
        'name' => 'required',
84
        'start_at' => 'date',
85
        'amount_exact' => 'numeric|min:0',
86
        'amount_percentage' => 'integer|min:0',
87
    ];
88
89
    /**
90
     * After validate.
91
     *
92
     * @return void
93
     */
94
    public function afterValidate()
95
    {
96
        $this->validateDates();
97
    }
98
99
    /**
100
     * Before save.
101
     *
102
     * @return void
103
     */
104
    public function beforeSave()
105
    {
106
        $this->setAmount();
107
    }
108
109
    /**
110
     * Filter form fields.
111
     *
112
     * @param  object   $fields
113
     * @return void
114
     */
115
    public function filterFields($fields)
116
    {
117
        $fields->amount_exact->hidden = $this->is_percentage;
118
        $fields->amount_percentage->hidden = ! $this->is_percentage;
119
    }
120
121
    /**
122
     * Fetch all of the products within the scope of this discount.
123
     *
124
     * @return array
125
     */
126
    public function getProductIds()
127
    {
128
        $categoryProductIds = $this->categories()
129
            ->select('id')
130
            ->with(['products' => function($products) {
131
                return $products->select('id');
132
            }])
133
            ->lists('categories.products.id');
134
135
        $productIds = $this->products()->lists('id');
136
137
        return array_unique(array_merge($productIds, $categoryProductIds));
138
    }
139
140
    /**
141
     * This exists to makes statuses sortable by assigning them a value.
142
     *
143
     * Expired  0
144
     * Running  1
145
     * Upcoming 2
146
     *
147
     * @param  \October\Rain\Database\Builder   $query
148
     * @return \October\Rain\Database\Builder
149
     */
150
    public function scopeSelectStatus($query)
151
    {
152
        $grammar = $query->getQuery()->getGrammar();
153
        $start_at = $grammar->wrap($this->table.'.start_at');
154
        $end_at = $grammar->wrap($this->table.'.end_at');
155
        $now = Carbon::now();
156
157
        $subquery = 'CASE '.
158
            "WHEN ({$end_at} IS NOT NULL AND {$end_at} < '{$now}') THEN 0 ".
159
            "WHEN ({$start_at} IS NOT NULL AND {$start_at} > '{$now}') THEN 2 ".
160
            'ELSE 1 '.
161
        'END';
162
163
        return $query->selectSubquery($subquery, 'status');
164
    }
165
166
    /**
167
     * Set the discount amount.
168
     *
169
     * @return  void
170
     */
171
    public function setAmount()
172
    {
173
        $exact = $this->getOriginalPurgeValue('amount_exact');
174
        $percentage = $this->getOriginalPurgeValue('amount_percentage');
175
176
        $this->amount = $this->is_percentage
177
            ? $percentage
178
            : $exact;
179
    }
180
181
    /**
182
     * Ensure the start and end dates are valid.
183
     *
184
     * @return void
185
     */
186
    public function validateDates()
187
    {
188
        // Start date must be after the end date
189
        if ($this->start_at !== null &&
190
            $this->end_at !== null &&
191
            $this->start_at >= $this->end_at) {
192
            Flash::error(Lang::get('bedard.shop::lang.discounts.form.start_at_invalid'));
193
            throw new ModelException($this);
194
        }
195
    }
196
}
197