|
1
|
|
|
<?php |
|
2
|
|
|
namespace app\modules\shop\actions; |
|
3
|
|
|
|
|
4
|
|
|
use Yii; |
|
5
|
|
|
use yii\base\Action; |
|
6
|
|
|
use yii\web\Response; |
|
7
|
|
|
use app\modules\shop\models\Category; |
|
8
|
|
|
use app\modules\shop\models\Currency; |
|
9
|
|
|
use app\modules\shop\models\Product; |
|
10
|
|
|
|
|
11
|
|
|
class BatchEditPriceAction extends Action |
|
12
|
|
|
{ |
|
13
|
|
|
protected $pRound = []; // params of round |
|
14
|
|
|
|
|
15
|
|
|
public function run() |
|
16
|
|
|
{ |
|
17
|
|
|
if (false === Yii::$app->request->isAjax) { |
|
18
|
|
|
throw new NotFoundHttpException(); |
|
19
|
|
|
} |
|
20
|
|
|
|
|
21
|
|
|
ini_set('max_execution_time', 0); |
|
22
|
|
|
Yii::$app->response->format = Response::FORMAT_JSON; |
|
23
|
|
|
Yii::$app->log->flushInterval = 100; |
|
24
|
|
|
Yii::$app->log->traceLevel = 0; |
|
25
|
|
|
Yii::$app->log->targets = [ |
|
26
|
|
|
new yii\log\FileTarget( |
|
27
|
|
|
[ |
|
28
|
|
|
'levels' => ['error'], |
|
29
|
|
|
'exportInterval' => 100 |
|
30
|
|
|
] |
|
31
|
|
|
) |
|
32
|
|
|
]; |
|
33
|
|
|
|
|
34
|
|
|
return $this->editPrices( |
|
35
|
|
|
Yii::$app->request->post('items', []), |
|
36
|
|
|
Yii::$app->request->post('context', '') |
|
37
|
|
|
); |
|
38
|
|
|
} |
|
39
|
|
|
|
|
40
|
|
|
/** |
|
41
|
|
|
* Gets products from selected categories |
|
42
|
|
|
* @param $list int[] |
|
43
|
|
|
* @return int[] |
|
44
|
|
|
*/ |
|
45
|
|
|
protected function getParentCategories($list) |
|
46
|
|
|
{ |
|
47
|
|
|
$incChild = Yii::$app->request->post('is_child_inc', false); |
|
48
|
|
|
$count = count($list); |
|
49
|
|
|
|
|
50
|
|
|
// read child cats |
|
51
|
|
|
if ($incChild) { |
|
52
|
|
|
for ($i = 0; $i < $count; $i++) { |
|
53
|
|
|
$cats = Category::getByParentId($list[$i]); |
|
54
|
|
|
foreach ($cats as $category) { |
|
55
|
|
|
$list[] = $category->id; |
|
56
|
|
|
$count ++; |
|
57
|
|
|
} |
|
58
|
|
|
// unset($cats); |
|
|
|
|
|
|
59
|
|
|
} |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
return $list; |
|
63
|
|
|
} |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* Set the algorithm of calculation |
|
67
|
|
|
* @return float function (float, float) |
|
|
|
|
|
|
68
|
|
|
*/ |
|
69
|
|
|
protected function getCalculator() |
|
70
|
|
|
{ |
|
71
|
|
|
$kind = Yii::$app->request->post('kind'); |
|
72
|
|
|
$operation = Yii::$app->request->post('operation'); |
|
73
|
|
|
|
|
74
|
|
|
if ($kind == 'fixed') { // fixed value |
|
75
|
|
|
if ($operation == 'inc') { |
|
76
|
|
|
$calculator = function ($subj, $value) { |
|
77
|
|
|
return $subj + $value; |
|
78
|
|
|
}; |
|
79
|
|
|
} else { |
|
80
|
|
|
$calculator = function ($subj, $value) { |
|
81
|
|
|
return $subj - $value; |
|
82
|
|
|
}; |
|
83
|
|
|
} |
|
84
|
|
|
} else { // percent value |
|
85
|
|
|
if ($operation == 'inc') { |
|
86
|
|
|
$calculator = function ($subj, $value) { |
|
87
|
|
|
return $subj * (1 + $value / 100); |
|
88
|
|
|
}; |
|
89
|
|
|
} else { |
|
90
|
|
|
$calculator = function ($subj, $value) { |
|
91
|
|
|
return $subj * (1 - $value / 100); |
|
92
|
|
|
}; |
|
93
|
|
|
} |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
return $calculator; |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
/** |
|
100
|
|
|
* To compare with zero and round |
|
101
|
|
|
* @param &$price float - $price can be rounded |
|
102
|
|
|
* @return bool |
|
103
|
|
|
*/ |
|
104
|
|
|
protected function checkAndRound(&$price) |
|
105
|
|
|
{ |
|
106
|
|
|
if ($price >= 0) { |
|
107
|
|
|
if ($this->pRound['is_round']) { |
|
108
|
|
|
$price = round( |
|
109
|
|
|
$price, |
|
110
|
|
|
$this->pRound['round_val'] |
|
111
|
|
|
); |
|
112
|
|
|
} |
|
113
|
|
|
} else { |
|
114
|
|
|
return false; |
|
115
|
|
|
} |
|
116
|
|
|
|
|
117
|
|
|
return true; |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
/** |
|
121
|
|
|
* Main function. Change prices and saving it |
|
122
|
|
|
* @param $data int[] |
|
123
|
|
|
* @param $context string |
|
124
|
|
|
* @return mixed[] |
|
|
|
|
|
|
125
|
|
|
*/ |
|
126
|
|
|
protected function editPrices($data, $context) |
|
127
|
|
|
{ |
|
128
|
|
|
$calculator = $this->getCalculator(); |
|
129
|
|
|
$selectedField = Yii::$app->request->post('apply_for'); |
|
130
|
|
|
$value = Yii::$app->request->post('value'); |
|
131
|
|
|
$type = Yii::$app->request->post('type'); |
|
132
|
|
|
$currencyId = Yii::$app->request->post('currency_id'); |
|
133
|
|
|
$this->pRound = [ |
|
134
|
|
|
'is_round' => Yii::$app->request->post('is_round'), |
|
135
|
|
|
'round_val' => Yii::$app->request->post('round_val'), |
|
136
|
|
|
]; |
|
137
|
|
|
|
|
138
|
|
|
$report = [ |
|
139
|
|
|
'all' => 0, |
|
140
|
|
|
'success' => 0, |
|
141
|
|
|
'error' => 0, |
|
142
|
|
|
'skipped' => 0, |
|
143
|
|
|
'errors' => [] |
|
144
|
|
|
]; |
|
145
|
|
|
|
|
146
|
|
|
if ($context == 'backend-product') { |
|
147
|
|
|
$sql = ['in', 'id', $data]; |
|
148
|
|
|
} else { |
|
149
|
|
|
$sql = ['in', 'main_category_id', $this->getParentCategories($data)]; |
|
150
|
|
|
} |
|
151
|
|
|
|
|
152
|
|
|
$items = Product::find() |
|
153
|
|
|
->select(['id', 'name', 'currency_id', 'price', 'old_price']) |
|
154
|
|
|
->where($sql) |
|
155
|
|
|
->asArray() |
|
156
|
|
|
->all(); |
|
157
|
|
|
|
|
158
|
|
|
foreach ($items as $item) { |
|
159
|
|
|
if ($item['currency_id'] != $currencyId) { |
|
160
|
|
|
$report['skipped']++; |
|
161
|
|
|
continue; |
|
162
|
|
|
} |
|
163
|
|
|
|
|
164
|
|
|
// change prices |
|
165
|
|
|
$fError = false; |
|
166
|
|
|
$errorKey = '[' . $item['id'] . '] ' . $item['name']; |
|
167
|
|
|
$calcPrice = $item['price']; |
|
168
|
|
|
$calcOldPrice = $item['old_price']; |
|
169
|
|
|
|
|
170
|
|
|
if ($type == 'normal') { |
|
171
|
|
|
// price |
|
172
|
|
View Code Duplication |
if ($selectedField == 'price' || $selectedField == 'all') { |
|
173
|
|
|
$calcPrice = $calculator($calcPrice, $value); |
|
174
|
|
|
if (!$this->checkAndRound($calcPrice)) { |
|
175
|
|
|
$fError = true; |
|
176
|
|
|
$report['errors'][$errorKey][Yii::t('app', 'Price')] = Yii::t('app', 'Сalculated value is less than zero'); |
|
|
|
|
|
|
177
|
|
|
} |
|
178
|
|
|
} |
|
179
|
|
|
// old price |
|
180
|
|
View Code Duplication |
if ($selectedField == 'old_price' || $selectedField == 'all') { |
|
181
|
|
|
$calcOldPrice = $calculator($calcOldPrice, $value); |
|
182
|
|
|
if (!$this->checkAndRound($calcOldPrice)) { |
|
183
|
|
|
$fError = true; |
|
184
|
|
|
$report['errors'][$errorKey][Yii::t('app', 'Old Price')] = Yii::t('app', 'Сalculated value is less than zero'); |
|
|
|
|
|
|
185
|
|
|
} |
|
186
|
|
|
} |
|
187
|
|
|
} else { // type == relative |
|
188
|
|
|
if ($selectedField == 'price') { |
|
189
|
|
|
$calcOldPrice = $calculator($calcPrice, $value); |
|
190
|
|
|
if (!$this->checkAndRound($calcOldPrice)) { |
|
191
|
|
|
$fError = true; |
|
192
|
|
|
$report['errors'][$errorKey][Yii::t('app', 'Old Price')] = Yii::t('app', 'Сalculated value is less than zero'); |
|
|
|
|
|
|
193
|
|
|
} |
|
194
|
|
|
} else { |
|
195
|
|
|
$calcPrice = $calculator($calcOldPrice, $value); |
|
196
|
|
|
if (!$this->checkAndRound($calcPrice)) { |
|
197
|
|
|
$fError = true; |
|
198
|
|
|
$report['errors'][$errorKey][Yii::t('app', 'Price')] = Yii::t('app', 'Сalculated value is less than zero'); |
|
|
|
|
|
|
199
|
|
|
} |
|
200
|
|
|
} |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
$report['all']++; |
|
204
|
|
|
if ($fError) { |
|
205
|
|
|
$report['error']++; |
|
206
|
|
|
} else { |
|
207
|
|
|
$report['success']++; |
|
208
|
|
|
Product::updateAll( |
|
209
|
|
|
['price' => $calcPrice, 'old_price' => $calcOldPrice], |
|
210
|
|
|
['id' => $item['id']] |
|
211
|
|
|
); |
|
212
|
|
|
} |
|
213
|
|
|
} |
|
214
|
|
|
|
|
215
|
|
|
return $report; |
|
216
|
|
|
} |
|
217
|
|
|
} |
|
218
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.