1 | <?php |
||||||
2 | |||||||
3 | namespace Ronmrcdo\Inventory\Traits; |
||||||
4 | |||||||
5 | use Illuminate\Database\Eloquent\Model; |
||||||
6 | use Illuminate\Support\Facades\DB; |
||||||
7 | use Ronmrcdo\Inventory\Exceptions\NotEnoughStockException; |
||||||
8 | use Ronmrcdo\Inventory\Exceptions\InvalidMovementException; |
||||||
9 | |||||||
10 | trait HasItemStocks |
||||||
11 | { |
||||||
12 | /** |
||||||
13 | * Stores the quantity before an update. |
||||||
14 | * |
||||||
15 | * @var int|float|string |
||||||
16 | */ |
||||||
17 | private $beforeQuantity = 0; |
||||||
18 | |||||||
19 | /** |
||||||
20 | * Stores the reason for updating / creating a stock. |
||||||
21 | * |
||||||
22 | * @var string |
||||||
23 | */ |
||||||
24 | public $reason = ''; |
||||||
25 | |||||||
26 | /** |
||||||
27 | * Stores the cost for updating a stock. |
||||||
28 | * |
||||||
29 | * @var int|float|string |
||||||
30 | */ |
||||||
31 | public $cost = 0; |
||||||
32 | |||||||
33 | protected static function bootHasItemStocks() |
||||||
34 | { |
||||||
35 | static::creating(function (Model $model) { |
||||||
36 | |||||||
37 | /* |
||||||
38 | * Check if a reason has been set, if not |
||||||
39 | * let's retrieve the default first entry reason |
||||||
40 | */ |
||||||
41 | if (!$model->reason) { |
||||||
42 | $model->reason = 'First Item Record; Stock Increase'; |
||||||
43 | } |
||||||
44 | }); |
||||||
45 | |||||||
46 | static::created(function (Model $model) { |
||||||
47 | $model->postCreate(); |
||||||
48 | }); |
||||||
49 | |||||||
50 | static::updating(function (Model $model) { |
||||||
51 | /* |
||||||
52 | * Retrieve the original quantity before it was updated, |
||||||
53 | * so we can create generate an update with it |
||||||
54 | */ |
||||||
55 | $model->beforeQuantity = $model->getOriginal('quantity'); |
||||||
56 | |||||||
57 | /* |
||||||
58 | * Check if a reason has been set, if not let's retrieve the default change reason |
||||||
59 | */ |
||||||
60 | if (!$model->reason) { |
||||||
61 | $model->reason = 'Stock Adjustment'; |
||||||
62 | } |
||||||
63 | }); |
||||||
64 | |||||||
65 | static::updated(function (Model $model) { |
||||||
66 | $model->postUpdate(); |
||||||
67 | }); |
||||||
68 | } |
||||||
69 | |||||||
70 | /** |
||||||
71 | * Generates a stock movement on the creation of a stock. |
||||||
72 | */ |
||||||
73 | public function postCreate() |
||||||
74 | { |
||||||
75 | if (!$this->getLastMovement()) { |
||||||
76 | $this->generateStockMovement(0, $this->quantity, $this->reason, $this->cost); |
||||||
77 | } |
||||||
78 | } |
||||||
79 | |||||||
80 | /** |
||||||
81 | * Generates a stock movement after a stock is updated. |
||||||
82 | */ |
||||||
83 | public function postUpdate() |
||||||
84 | { |
||||||
85 | $this->generateStockMovement($this->beforeQuantity, $this->quantity, $this->reason, $this->cost); |
||||||
86 | } |
||||||
87 | |||||||
88 | /** |
||||||
89 | * Performs a quantity update. Automatically determining |
||||||
90 | * depending on the quantity entered if stock is being taken |
||||||
91 | * or added. |
||||||
92 | * |
||||||
93 | * @param int|float|string $quantity |
||||||
94 | * @param string $reason |
||||||
95 | * @param int|float|string $cost |
||||||
96 | * |
||||||
97 | * @throws InvalidQuantityException |
||||||
98 | * |
||||||
99 | * @return $this |
||||||
100 | */ |
||||||
101 | public function updateQuantity($quantity, $reason = '', $cost = 0) |
||||||
102 | { |
||||||
103 | if ($this->isValidQuantity($quantity)) { |
||||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||||
104 | return $this->processUpdateQuantityOperation($quantity, $reason, $cost); |
||||||
0 ignored issues
–
show
The expression
return $this->processUpd...antity, $reason, $cost) could also return false which is incompatible with the documented return type Ronmrcdo\Inventory\Traits\HasItemStocks . Did you maybe forget to handle an error condition?
If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled. ![]() |
|||||||
105 | } |
||||||
106 | } |
||||||
107 | |||||||
108 | /** |
||||||
109 | * Removes the specified quantity from the current stock. |
||||||
110 | * |
||||||
111 | * @param int|float|string $quantity |
||||||
112 | * @param string $reason |
||||||
113 | * @param int|float|string $cost |
||||||
114 | * |
||||||
115 | * @return $this|bool |
||||||
116 | */ |
||||||
117 | public function remove($quantity, $reason = '', $cost = 0) |
||||||
118 | { |
||||||
119 | return $this->take($quantity, $reason, $cost); |
||||||
120 | } |
||||||
121 | |||||||
122 | /** |
||||||
123 | * Processes a 'take' operation on the current stock. |
||||||
124 | * |
||||||
125 | * @param int|float|string $quantity |
||||||
126 | * @param string $reason |
||||||
127 | * @param int|float|string $cost |
||||||
128 | * |
||||||
129 | * @throws InvalidQuantityException |
||||||
130 | * @throws NotEnoughStockException |
||||||
131 | * |
||||||
132 | * @return $this|bool |
||||||
133 | */ |
||||||
134 | public function take($quantity, $reason = '', $cost = 0) |
||||||
135 | { |
||||||
136 | if ($this->isValidQuantity($quantity) && $this->hasEnoughStock($quantity)) { |
||||||
137 | return $this->processTakeOperation($quantity, $reason, $cost); |
||||||
138 | } |
||||||
139 | } |
||||||
140 | |||||||
141 | /** |
||||||
142 | * Alias for put function. |
||||||
143 | * |
||||||
144 | * @param int|float|string $quantity |
||||||
145 | * @param string $reason |
||||||
146 | * @param int|float|string $cost |
||||||
147 | * |
||||||
148 | * @return $this |
||||||
149 | */ |
||||||
150 | public function add($quantity, $reason = '', $cost = 0) |
||||||
151 | { |
||||||
152 | return $this->put($quantity, $reason, $cost); |
||||||
0 ignored issues
–
show
The expression
return $this->put($quantity, $reason, $cost) could also return false which is incompatible with the documented return type Ronmrcdo\Inventory\Traits\HasItemStocks . Did you maybe forget to handle an error condition?
If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled. ![]() |
|||||||
153 | } |
||||||
154 | |||||||
155 | /** |
||||||
156 | * Processes a 'put' operation on the current stock. |
||||||
157 | * |
||||||
158 | * @param int|float|string $quantity |
||||||
159 | * @param string $reason |
||||||
160 | * @param int|float|string $cost |
||||||
161 | * |
||||||
162 | * @throws InvalidQuantityException |
||||||
163 | * |
||||||
164 | * @return $this |
||||||
165 | */ |
||||||
166 | public function put($quantity, $reason = '', $cost = 0) |
||||||
167 | { |
||||||
168 | if ($this->isValidQuantity($quantity)) { |
||||||
169 | return $this->processPutOperation($quantity, $reason, $cost); |
||||||
0 ignored issues
–
show
The expression
return $this->processPut...antity, $reason, $cost) could also return false which is incompatible with the documented return type Ronmrcdo\Inventory\Traits\HasItemStocks . Did you maybe forget to handle an error condition?
If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled. ![]() |
|||||||
170 | } |
||||||
171 | } |
||||||
172 | |||||||
173 | /** |
||||||
174 | * Moves a stock to the specified location. |
||||||
175 | * |
||||||
176 | * @param $location |
||||||
177 | * |
||||||
178 | * @return bool |
||||||
179 | */ |
||||||
180 | public function moveTo($location) |
||||||
181 | { |
||||||
182 | $location = $this->getLocation($location); |
||||||
0 ignored issues
–
show
It seems like
getLocation() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
183 | |||||||
184 | return $this->processMoveOperation($location); |
||||||
185 | } |
||||||
186 | |||||||
187 | /** |
||||||
188 | * Rolls back the last movement, or the movement specified. If recursive is set to true, |
||||||
189 | * it will rollback all movements leading up to the movement specified. |
||||||
190 | * |
||||||
191 | * @param mixed $movement |
||||||
192 | * @param bool $recursive |
||||||
193 | * |
||||||
194 | * @return $this|bool |
||||||
195 | */ |
||||||
196 | public function rollback($movement = null, $recursive = false) |
||||||
197 | { |
||||||
198 | if ($movement) { |
||||||
199 | return $this->rollbackMovement($movement, $recursive); |
||||||
200 | } else { |
||||||
201 | $movement = $this->getLastMovement(); |
||||||
202 | |||||||
203 | if ($movement) { |
||||||
204 | return $this->processRollbackOperation($movement, $recursive); |
||||||
205 | } |
||||||
206 | } |
||||||
207 | |||||||
208 | return false; |
||||||
209 | } |
||||||
210 | |||||||
211 | /** |
||||||
212 | * Rolls back a specific movement. |
||||||
213 | * |
||||||
214 | * @param mixed $movement |
||||||
215 | * @param bool $recursive |
||||||
216 | * |
||||||
217 | * @throws InvalidMovementException |
||||||
218 | * |
||||||
219 | * @return $this|bool |
||||||
220 | */ |
||||||
221 | public function rollbackMovement($movement, $recursive = false) |
||||||
222 | { |
||||||
223 | $movement = $this->getMovement($movement); |
||||||
224 | |||||||
225 | return $this->processRollbackOperation($movement, $recursive); |
||||||
226 | } |
||||||
227 | |||||||
228 | /** |
||||||
229 | * Returns true if there is enough stock for the specified quantity being taken. |
||||||
230 | * Throws NotEnoughStockException otherwise. |
||||||
231 | * |
||||||
232 | * @param int|float|string $quantity |
||||||
233 | * |
||||||
234 | * @throws NotEnoughStockException |
||||||
235 | * |
||||||
236 | * @return bool |
||||||
237 | */ |
||||||
238 | public function hasEnoughStock($quantity = 0) |
||||||
239 | { |
||||||
240 | /* |
||||||
241 | * Using double equals for validation of complete value only, not variable type. For example: |
||||||
242 | * '20' (string) equals 20 (int) |
||||||
243 | */ |
||||||
244 | if ($this->quantity == $quantity || $this->quantity > $quantity) { |
||||||
245 | return true; |
||||||
246 | } |
||||||
247 | |||||||
248 | $message = 'Not enough stock. Tried to take '. $quantity.' but only '. $this->quantity .' is available'; |
||||||
249 | |||||||
250 | throw new NotEnoughStockException($message); |
||||||
251 | } |
||||||
252 | |||||||
253 | /** |
||||||
254 | * Returns the last movement on the current stock record. |
||||||
255 | * |
||||||
256 | * @return mixed |
||||||
257 | */ |
||||||
258 | public function getLastMovement() |
||||||
259 | { |
||||||
260 | $movement = $this->movements()->orderBy('created_at', 'DESC')->first(); |
||||||
0 ignored issues
–
show
It seems like
movements() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
261 | |||||||
262 | if ($movement) { |
||||||
263 | return $movement; |
||||||
264 | } |
||||||
265 | |||||||
266 | return false; |
||||||
267 | } |
||||||
268 | |||||||
269 | /** |
||||||
270 | * Returns a movement depending on the specified argument. If an object is supplied, it is checked if it |
||||||
271 | * is an instance of an eloquent model. If a numeric value is entered, it is retrieved by it's ID. |
||||||
272 | * |
||||||
273 | * @param mixed $movement |
||||||
274 | * |
||||||
275 | * @throws InvalidMovementException |
||||||
276 | * |
||||||
277 | * @return mixed |
||||||
278 | */ |
||||||
279 | public function getMovement($movement) |
||||||
280 | { |
||||||
281 | if ($this->isModel($movement)) { |
||||||
0 ignored issues
–
show
It seems like
isModel() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
282 | return $movement; |
||||||
283 | } elseif (is_numeric($movement)) { |
||||||
284 | return $this->getMovementById($movement); |
||||||
285 | } else { |
||||||
286 | $message = 'Movement '. $movement .' is invalid'; |
||||||
287 | |||||||
288 | throw new InvalidMovementException($message); |
||||||
289 | } |
||||||
290 | } |
||||||
291 | |||||||
292 | /** |
||||||
293 | * Creates and returns a new un-saved stock transaction |
||||||
294 | * instance with the current stock ID attached. |
||||||
295 | * |
||||||
296 | * @param string $name |
||||||
297 | * |
||||||
298 | * @return \Illuminate\Database\Eloquent\Model |
||||||
299 | */ |
||||||
300 | public function newTransaction($name = '') |
||||||
301 | { |
||||||
302 | $transaction = $this->transactions()->getRelated(); |
||||||
0 ignored issues
–
show
It seems like
transactions() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
303 | |||||||
304 | /* |
||||||
305 | * Set the transaction attributes so they don't |
||||||
306 | * need to be set manually |
||||||
307 | */ |
||||||
308 | $transaction->stock_id = $this->getKey(); |
||||||
0 ignored issues
–
show
It seems like
getKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
309 | $transaction->name = $name; |
||||||
310 | |||||||
311 | return $transaction; |
||||||
312 | } |
||||||
313 | |||||||
314 | /** |
||||||
315 | * Retrieves a movement by the specified ID. |
||||||
316 | * |
||||||
317 | * @param int|string $id |
||||||
318 | * |
||||||
319 | * @return mixed |
||||||
320 | */ |
||||||
321 | private function getMovementById($id) |
||||||
322 | { |
||||||
323 | return $this->movements()->find($id); |
||||||
324 | } |
||||||
325 | |||||||
326 | /** |
||||||
327 | * Processes a quantity update operation. |
||||||
328 | * |
||||||
329 | * @param int|float|string $quantity |
||||||
330 | * @param string $reason |
||||||
331 | * @param int|float|string $cost |
||||||
332 | * |
||||||
333 | * @return $this |
||||||
334 | */ |
||||||
335 | private function processUpdateQuantityOperation($quantity, $reason = '', $cost = 0) |
||||||
336 | { |
||||||
337 | if ($quantity > $this->quantity) { |
||||||
338 | $putting = $quantity - $this->quantity; |
||||||
339 | |||||||
340 | return $this->put($putting, $reason, $cost); |
||||||
0 ignored issues
–
show
The expression
return $this->put($putting, $reason, $cost) could also return false which is incompatible with the documented return type Ronmrcdo\Inventory\Traits\HasItemStocks . Did you maybe forget to handle an error condition?
If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled. ![]() |
|||||||
341 | } else { |
||||||
342 | $taking = $this->quantity - $quantity; |
||||||
343 | |||||||
344 | return $this->take($taking, $reason, $cost); |
||||||
345 | } |
||||||
346 | } |
||||||
347 | |||||||
348 | /** |
||||||
349 | * Processes removing quantity from the current stock. |
||||||
350 | * |
||||||
351 | * @param int|float|string $taking |
||||||
352 | * @param string $reason |
||||||
353 | * @param int|float|string $cost |
||||||
354 | * |
||||||
355 | * @return $this|bool |
||||||
356 | */ |
||||||
357 | private function processTakeOperation($taking, $reason = '', $cost = 0) |
||||||
358 | { |
||||||
359 | $left = $this->quantity - $taking; |
||||||
360 | |||||||
361 | /* |
||||||
362 | * If the updated total and the beginning total are the same, we'll check if |
||||||
363 | * duplicate movements are allowed. We'll return the current record if |
||||||
364 | * they aren't. |
||||||
365 | */ |
||||||
366 | if ($left == $this->quantity && !$this->allowDuplicateMovementsEnabled()) { |
||||||
367 | return $this; |
||||||
368 | } |
||||||
369 | |||||||
370 | $this->quantity = $left; |
||||||
0 ignored issues
–
show
|
|||||||
371 | |||||||
372 | $this->setReason($reason); |
||||||
373 | |||||||
374 | $this->setCost($cost); |
||||||
375 | |||||||
376 | DB::beginTransaction(); |
||||||
377 | |||||||
378 | try { |
||||||
379 | if ($this->save()) { |
||||||
0 ignored issues
–
show
It seems like
save() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
380 | |||||||
381 | $this->fireModelEvent('inventory.stock.taken', [ |
||||||
0 ignored issues
–
show
It seems like
fireModelEvent() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
382 | 'stock' => $this, |
||||||
383 | ]); |
||||||
384 | |||||||
385 | return $this; |
||||||
386 | } |
||||||
387 | } catch (\Exception $e) { |
||||||
388 | DB::rollBack(); |
||||||
389 | } |
||||||
390 | |||||||
391 | return false; |
||||||
392 | } |
||||||
393 | |||||||
394 | /** |
||||||
395 | * Processes adding quantity to current stock. |
||||||
396 | * |
||||||
397 | * @param int|float|string $putting |
||||||
398 | * @param string $reason |
||||||
399 | * @param int|float|string $cost |
||||||
400 | * |
||||||
401 | * @return $this|bool |
||||||
402 | */ |
||||||
403 | private function processPutOperation($putting, $reason = '', $cost = 0) |
||||||
404 | { |
||||||
405 | $before = $this->quantity; |
||||||
406 | |||||||
407 | $total = $putting + $before; |
||||||
408 | |||||||
409 | /* |
||||||
410 | * If the updated total and the beginning total are the same, |
||||||
411 | * we'll check if duplicate movements are allowed |
||||||
412 | */ |
||||||
413 | if ($total == $this->quantity && !$this->allowDuplicateMovementsEnabled()) { |
||||||
414 | return $this; |
||||||
415 | } |
||||||
416 | |||||||
417 | $this->quantity = $total; |
||||||
0 ignored issues
–
show
|
|||||||
418 | |||||||
419 | $this->setReason($reason); |
||||||
420 | |||||||
421 | $this->setCost($cost); |
||||||
422 | |||||||
423 | DB::beginTransaction(); |
||||||
424 | |||||||
425 | try { |
||||||
426 | if ($this->save()) { |
||||||
427 | DB::commit(); |
||||||
428 | |||||||
429 | $this->fireModelEvent('inventory.stock.added', [ |
||||||
430 | 'stock' => $this, |
||||||
431 | ]); |
||||||
432 | |||||||
433 | return $this; |
||||||
434 | } |
||||||
435 | } catch (\Exception $e) { |
||||||
436 | DB::rollBack(); |
||||||
437 | } |
||||||
438 | |||||||
439 | return false; |
||||||
440 | } |
||||||
441 | |||||||
442 | /** |
||||||
443 | * Processes the stock moving from it's current |
||||||
444 | * location, to the specified location. |
||||||
445 | * |
||||||
446 | * @param mixed $location |
||||||
447 | * |
||||||
448 | * @return bool |
||||||
449 | */ |
||||||
450 | private function processMoveOperation(Model $location) |
||||||
451 | { |
||||||
452 | $this->location_id = $location->getKey(); |
||||||
0 ignored issues
–
show
|
|||||||
453 | |||||||
454 | DB::beginTransaction(); |
||||||
455 | |||||||
456 | try { |
||||||
457 | if ($this->save()) { |
||||||
458 | |||||||
459 | |||||||
460 | $this->fireModelEvent('inventory.stock.moved', [ |
||||||
461 | 'stock' => $this, |
||||||
462 | ]); |
||||||
463 | |||||||
464 | DB::commit(); |
||||||
465 | return $this; |
||||||
0 ignored issues
–
show
|
|||||||
466 | } |
||||||
467 | } catch (\Exception $e) { |
||||||
468 | DB::rollBack(); |
||||||
469 | } |
||||||
470 | |||||||
471 | return false; |
||||||
472 | } |
||||||
473 | |||||||
474 | /** |
||||||
475 | * Processes a single rollback operation. |
||||||
476 | * |
||||||
477 | * @param mixed $movement |
||||||
478 | * @param bool $recursive |
||||||
479 | * |
||||||
480 | * @return $this|bool |
||||||
481 | */ |
||||||
482 | private function processRollbackOperation(Model $movement, $recursive = false) |
||||||
483 | { |
||||||
484 | if ($recursive) { |
||||||
485 | return $this->processRecursiveRollbackOperation($movement); |
||||||
0 ignored issues
–
show
|
|||||||
486 | } |
||||||
487 | |||||||
488 | $this->quantity = $movement->before; |
||||||
0 ignored issues
–
show
|
|||||||
489 | |||||||
490 | $reason = 'Rolled back to movement ID: '. $movement->getOriginal('id') .' on '. $movement->getOriginal('created_at'); |
||||||
0 ignored issues
–
show
Are you sure
$movement->getOriginal('created_at') of type array|mixed can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() Are you sure
$movement->getOriginal('id') of type array|mixed can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
491 | |||||||
492 | $this->setReason($reason); |
||||||
493 | |||||||
494 | if ($this->rollbackCostEnabled()) { |
||||||
495 | $this->setCost($movement->cost); |
||||||
0 ignored issues
–
show
It seems like
$movement->cost can also be of type Illuminate\Database\Eloq...uent\Relations\Relation and Illuminate\Database\Eloquent\Relations\Relation ; however, parameter $cost of Ronmrcdo\Inventory\Traits\HasItemStocks::setCost() does only seem to accept double|integer|string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
496 | |||||||
497 | $this->reverseCost(); |
||||||
498 | } |
||||||
499 | |||||||
500 | DB::beginTransaction(); |
||||||
501 | |||||||
502 | try { |
||||||
503 | if ($this->save()) { |
||||||
504 | DB::commit(); |
||||||
505 | |||||||
506 | $this->fireModelEvent('inventory.stock.rollback', [ |
||||||
507 | 'stock' => $this, |
||||||
508 | ]); |
||||||
509 | |||||||
510 | return $this; |
||||||
511 | } |
||||||
512 | } catch (\Exception $e) { |
||||||
513 | DB::rollBack(); |
||||||
514 | } |
||||||
515 | |||||||
516 | return false; |
||||||
517 | } |
||||||
518 | |||||||
519 | /** |
||||||
520 | * Processes a recursive rollback operation. |
||||||
521 | * |
||||||
522 | * @param mixed $movement |
||||||
523 | * |
||||||
524 | * @return array |
||||||
525 | */ |
||||||
526 | private function processRecursiveRollbackOperation(Model $movement) |
||||||
527 | { |
||||||
528 | /* |
||||||
529 | * Retrieve movements that were created after |
||||||
530 | * the specified movement, and order them descending |
||||||
531 | */ |
||||||
532 | $movements = $this |
||||||
533 | ->movements() |
||||||
534 | ->where('created_at', '>=', $movement->getOriginal('created_at')) |
||||||
535 | ->orderBy('created_at', 'DESC') |
||||||
536 | ->get(); |
||||||
537 | |||||||
538 | $rollbacks = []; |
||||||
539 | |||||||
540 | if ($movements->count() > 0) { |
||||||
541 | foreach ($movements as $movement) { |
||||||
542 | $rollbacks = $this->processRollbackOperation($movement); |
||||||
543 | } |
||||||
544 | } |
||||||
545 | |||||||
546 | return $rollbacks; |
||||||
0 ignored issues
–
show
|
|||||||
547 | } |
||||||
548 | |||||||
549 | /** |
||||||
550 | * Creates a new stock movement record. |
||||||
551 | * |
||||||
552 | * @param int|float|string $before |
||||||
553 | * @param int|float|string $after |
||||||
554 | * @param string $reason |
||||||
555 | * @param int|float|string $cost |
||||||
556 | * |
||||||
557 | * @return \Illuminate\Database\Eloquent\Model |
||||||
558 | */ |
||||||
559 | private function generateStockMovement($before, $after, $reason = '', $cost = 0) |
||||||
560 | { |
||||||
561 | $insert = [ |
||||||
562 | 'stock_id' => $this->getKey(), |
||||||
563 | 'before' => $before, |
||||||
564 | 'after' => $after, |
||||||
565 | 'reason' => $reason, |
||||||
566 | 'cost' => $cost, |
||||||
567 | ]; |
||||||
568 | |||||||
569 | return $this->movements()->create($insert); |
||||||
570 | } |
||||||
571 | |||||||
572 | /** |
||||||
573 | * Sets the cost attribute. |
||||||
574 | * |
||||||
575 | * @param int|float|string $cost |
||||||
576 | */ |
||||||
577 | private function setCost($cost = 0) |
||||||
578 | { |
||||||
579 | $this->cost = $cost; |
||||||
580 | } |
||||||
581 | |||||||
582 | /** |
||||||
583 | * Reverses the cost of a movement. |
||||||
584 | */ |
||||||
585 | private function reverseCost() |
||||||
586 | { |
||||||
587 | if ($this->isPositive($this->cost)) { |
||||||
0 ignored issues
–
show
It seems like
isPositive() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
588 | $this->setCost(-abs($this->cost)); |
||||||
589 | } else { |
||||||
590 | $this->setCost(abs($this->cost)); |
||||||
591 | } |
||||||
592 | } |
||||||
593 | |||||||
594 | /** |
||||||
595 | * Sets the reason attribute. |
||||||
596 | * |
||||||
597 | * @param string $reason |
||||||
598 | */ |
||||||
599 | private function setReason($reason = '') |
||||||
600 | { |
||||||
601 | $this->reason = $reason; |
||||||
602 | } |
||||||
603 | |||||||
604 | /** |
||||||
605 | * Returns true/false from the configuration file determining |
||||||
606 | * whether or not stock movements can have the same before and after |
||||||
607 | * quantities. |
||||||
608 | * |
||||||
609 | * @return bool |
||||||
610 | */ |
||||||
611 | private function allowDuplicateMovementsEnabled() |
||||||
612 | { |
||||||
613 | return false; |
||||||
614 | } |
||||||
615 | |||||||
616 | /** |
||||||
617 | * Returns true/false from the configuration file determining |
||||||
618 | * whether or not to rollback costs when a rollback occurs on |
||||||
619 | * a stock. |
||||||
620 | * |
||||||
621 | * @return bool |
||||||
622 | */ |
||||||
623 | private function rollbackCostEnabled() |
||||||
624 | { |
||||||
625 | return true; |
||||||
626 | } |
||||||
627 | |||||||
628 | } |
||||||
629 |