Completed
Push — master ( c2b43f...7517d8 )
by Jan
03:46
created

Part::getAmountSum()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 6
nop 0
dl 0
loc 18
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 *
4
 * part-db version 0.1
5
 * Copyright (C) 2005 Christoph Lechner
6
 * http://www.cl-projects.de/
7
 *
8
 * part-db version 0.2+
9
 * Copyright (C) 2009 K. Jacobs and others (see authors.php)
10
 * http://code.google.com/p/part-db/
11
 *
12
 * Part-DB Version 0.4+
13
 * Copyright (C) 2016 - 2019 Jan Böhmer
14
 * https://github.com/jbtronics
15
 *
16
 * This program is free software; you can redistribute it and/or
17
 * modify it under the terms of the GNU General Public License
18
 * as published by the Free Software Foundation; either version 2
19
 * of the License, or (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program; if not, write to the Free Software
28
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
29
 *
30
 */
31
32
declare(strict_types=1);
33
34
/**
35
 * part-db version 0.1
36
 * Copyright (C) 2005 Christoph Lechner
37
 * http://www.cl-projects.de/.
38
 *
39
 * part-db version 0.2+
40
 * Copyright (C) 2009 K. Jacobs and others (see authors.php)
41
 * http://code.google.com/p/part-db/
42
 *
43
 * Part-DB Version 0.4+
44
 * Copyright (C) 2016 - 2019 Jan Böhmer
45
 * https://github.com/jbtronics
46
 *
47
 * This program is free software; you can redistribute it and/or
48
 * modify it under the terms of the GNU General Public License
49
 * as published by the Free Software Foundation; either version 2
50
 * of the License, or (at your option) any later version.
51
 *
52
 * This program is distributed in the hope that it will be useful,
53
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
54
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
55
 * GNU General Public License for more details.
56
 *
57
 * You should have received a copy of the GNU General Public License
58
 * along with this program; if not, write to the Free Software
59
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
60
 */
61
62
namespace App\Entity\Parts;
63
64
use App\Entity\Attachments\Attachment;
65
use App\Entity\Attachments\AttachmentContainingDBElement;
66
use App\Entity\Devices\Device;
67
use App\Entity\PriceInformations\Orderdetail;
68
use App\Security\Annotations\ColumnSecurity;
69
use App\Validator\Constraints\Selectable;
70
use Doctrine\ORM\Mapping as ORM;
71
72
use Doctrine\ORM\PersistentCollection;
73
use Symfony\Component\Validator\Constraints as Assert;
74
75
/**
76
 * Class Part.
77
 *
78
 * @ORM\Entity(repositoryClass="App\Repository\PartRepository")
79
 * @ORM\Table("`parts`")
80
 */
81
class Part extends AttachmentContainingDBElement
82
{
83
    public const INSTOCK_UNKNOWN = -2;
84
85
    /**
86
     * @ORM\OneToMany(targetEntity="App\Entity\Attachments\PartAttachment", mappedBy="element")
87
     */
88
    protected $attachments;
89
90
    /**
91
     * @var Category
92
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="parts")
93
     * @ORM\JoinColumn(name="id_category", referencedColumnName="id")
94
     * @Selectable()
95
     */
96
    protected $category;
97
98
    /**
99
     * @var Footprint|null
100
     * @ORM\ManyToOne(targetEntity="Footprint", inversedBy="parts")
101
     * @ORM\JoinColumn(name="id_footprint", referencedColumnName="id")
102
     *
103
     * @ColumnSecurity(prefix="footprint", type="object")
104
     * @Selectable()
105
     */
106
    protected $footprint;
107
108
    /**
109
     * @var Manufacturer|null
110
     * @ORM\ManyToOne(targetEntity="Manufacturer", inversedBy="parts")
111
     * @ORM\JoinColumn(name="id_manufacturer", referencedColumnName="id")
112
     *
113
     * @ColumnSecurity(prefix="manufacturer", type="object")
114
     * @Selectable()
115
     */
116
    protected $manufacturer;
117
118
    /**
119
     * @var Attachment
120
     * @ORM\ManyToOne(targetEntity="App\Entity\Attachments\Attachment")
121
     * @ORM\JoinColumn(name="id_master_picture_attachement", referencedColumnName="id")
122
     *
123
     * @ColumnSecurity(prefix="attachments", type="object")
124
     */
125
    protected $master_picture_attachment;
126
127
    /**
128
     * @var Orderdetail[]
129
     * @ORM\OneToMany(targetEntity="App\Entity\PriceInformations\Orderdetail", mappedBy="part")
130
     *
131
     * @ColumnSecurity(prefix="orderdetails", type="object")
132
     */
133
    protected $orderdetails;
134
135
    /**
136
     * @var Orderdetail
137
     * @ORM\OneToOne(targetEntity="App\Entity\PriceInformations\Orderdetail")
138
     * @ORM\JoinColumn(name="order_orderdetails_id", referencedColumnName="id")
139
     *
140
     * @ColumnSecurity(prefix="order", type="object")
141
     */
142
    protected $order_orderdetail;
143
144
    //TODO
145
    protected $devices;
146
147
    /**
148
     *  @ColumnSecurity(type="datetime")
149
     *  @ORM\Column(type="datetimetz", name="datetime_added")
150
     */
151
    protected $addedDate;
152
153
    /**
154
     * @var \DateTime The date when this element was modified the last time.
155
     * @ORM\Column(type="datetimetz", name="last_modified")
156
     * @ColumnSecurity(type="datetime")
157
     */
158
    protected $lastModified;
159
160
    /**********************
161
     * Propertys
162
     ***********************/
163
164
    /**
165
     * @var string
166
     * @ORM\Column(type="string")
167
     *
168
     * @ColumnSecurity(prefix="name")
169
     */
170
    protected $name;
171
172
    /**
173
     * @var string
174
     * @ORM\Column(type="text")
175
     *
176
     * @ColumnSecurity(prefix="description")
177
     */
178
    protected $description = '';
179
180
    /**
181
     * @var ?PartLot[]
182
     * @ORM\OneToMany(targetEntity="PartLot", mappedBy="part")
183
     */
184
    protected $partLots;
185
186
    /**
187
     * @var float
188
     * @ORM\Column(type="float")
189
     * @Assert\PositiveOrZero()
190
     *
191
     * @ColumnSecurity(prefix="mininstock", type="integer")
192
     */
193
    protected $minamount = 0;
194
195
    /**
196
     * @var string
197
     * @ORM\Column(type="text")
198
     * @ColumnSecurity(prefix="comment")
199
     */
200
    protected $comment = '';
201
202
    /**
203
     * @var bool
204
     * @ORM\Column(type="boolean")
205
     */
206
    protected $visible = true;
207
208
    /**
209
     * @var bool
210
     * @ORM\Column(type="boolean")
211
     * @ColumnSecurity(type="boolean")
212
     */
213
    protected $favorite = false;
214
215
    /**
216
     * @var int
217
     * @ORM\Column(type="integer")
218
     * @ColumnSecurity(prefix="order", type="integer")
219
     */
220
    protected $order_quantity = 0;
221
222
    /**
223
     * @var bool
224
     * @ORM\Column(type="boolean")
225
     * @ColumnSecurity(prefix="order", type="boolean")
226
     */
227
    protected $manual_order = false;
228
229
    /**
230
     * @var string
231
     * @ORM\Column(type="string")
232
     * @ColumnSecurity(prefix="manufacturer", type="string", placeholder="")
233
     */
234
    protected $manufacturer_product_url = '';
235
236
    /**
237
     * @var string
238
     * @ORM\Column(type="string")
239
     * @ColumnSecurity(prefix="manufacturer", type="string", placeholder="")
240
     */
241
    protected $manufacturer_product_number;
242
243
    /**
244
     * @var bool Determines if this part entry needs review (for example, because it is work in progress)
245
     * @ORM\Column(type="boolean")
246
     */
247
    protected $needs_review = false;
248
249
    /**
250
     * @var ?MeasurementUnit The unit in which the part's amount is measured.
251
     * @ORM\ManyToOne(targetEntity="MeasurementUnit")
252
     * @ORM\JoinColumn(name="id_part_unit", referencedColumnName="id", nullable=true)
253
     */
254
    protected $partUnit;
255
256
    /**
257
     * @var string A comma seperated list of tags, assocciated with the part.
258
     * @ORM\Column(type="text")
259
     */
260
    protected $tags;
261
262
    /**
263
     * @var float|null How much a single part unit weighs in gramms.
264
     * @ORM\Column(type="float", nullable=true)
265
     * @Assert\Positive()
266
     */
267
    protected $mass;
268
269
    /**
270
     * Returns the ID as an string, defined by the element class.
271
     * This should have a form like P000014, for a part with ID 14.
272
     *
273
     * @return string The ID as a string;
274
     */
275
    public function getIDString(): string
276
    {
277
        return 'P' . sprintf('%06d', $this->getID());
278
    }
279
280
    /*********************************************************************************
281
     * Getters
282
     ********************************************************************************/
283
284
    /**
285
     * Get the description string like it is saved in the database.
286
     * This can contain BBCode, it is not parsed yet.
287
     *
288
     * @return string the description
289
     */
290
    public function getDescription(): string
291
    {
292
        return  htmlspecialchars($this->description);
293
    }
294
295
    /**
296
     *  Get the count of parts which must be in stock at least.
297
     *
298
     * @return int count of parts which must be in stock at least
299
     */
300
    public function getMinAmount(): float
301
    {
302
        return $this->minamount;
303
    }
304
305
    /**
306
     *  Get the comment associated with this part.
307
     *
308
     * @return string The raw/unparsed comment
309
     */
310
    public function getComment(): string
311
    {
312
        return htmlspecialchars($this->comment);
313
    }
314
315
    /**
316
     *  Get if this part is obsolete.
317
     *
318
     *     A Part is marked as "obsolete" if all their orderdetails are marked as "obsolete".
319
     *          If a part has no orderdetails, the part isn't marked as obsolete.
320
     *
321
     * @return bool true, if this part is obsolete. false, if this part isn't obsolete
322
     */
323
    public function isObsolete(): bool
324
    {
325
        $all_orderdetails = $this->getOrderdetails();
326
327
        if (0 === count($all_orderdetails)) {
328
            return false;
329
        }
330
331
        foreach ($all_orderdetails as $orderdetails) {
332
            if (!$orderdetails->getObsolete()) {
333
                return false;
334
            }
335
        }
336
337
        return true;
338
    }
339
340
    /**
341
     *  Get if this part is visible.
342
     *
343
     * @return bool true if this part is visible
344
     *              false if this part isn't visible
345
     */
346
    public function isVisible(): bool
347
    {
348
        return $this->visible;
349
    }
350
351
    /**
352
     * Get if this part is a favorite.
353
     *
354
     * @return bool * true if this part is a favorite
355
     *              * false if this part is not a favorite.
356
     */
357
    public function isFavorite(): bool
358
    {
359
        return $this->favorite;
360
    }
361
362
    /**
363
     *  Get the selected order orderdetails of this part.
364
     * @return Orderdetail the selected order orderdetails
365
     */
366
    public function getOrderOrderdetails(): ?Orderdetail
367
    {
368
        return $this->order_orderdetail;
369
    }
370
371
    /**
372
     *  Get the order quantity of this part.
373
     *
374
     * @return int the order quantity
375
     */
376
    public function getOrderQuantity(): int
377
    {
378
        return $this->order_quantity;
379
    }
380
381
    /**
382
     *  Check if this part is marked for manual ordering.
383
     *
384
     * @return bool the "manual_order" attribute
385
     */
386
    public function isMarkedForManualOrder(): bool
387
    {
388
        return $this->manual_order;
389
    }
390
391
    /**
392
     *  Get the link to the website of the article on the manufacturers website
393
     *  When no this part has no explicit url set, then it is tried to generate one from the Manufacturer of this part
394
     *  automatically.
395
     *
396
     * @param
397
     *
398
     * @return string the link to the article
399
     */
400
    public function getManufacturerProductUrl(): string
401
    {
402
        if ('' !== $this->manufacturer_product_url) {
403
            return $this->manufacturer_product_url;
404
        }
405
406
        if (null !== $this->getManufacturer()) {
407
            return $this->getManufacturer()->getAutoProductUrl($this->name);
408
        }
409
410
        return ''; // no url is available
411
    }
412
413
    /**
414
     * Similar to getManufacturerProductUrl, but here only the database value is returned.
415
     *
416
     * @return string The manufacturer url saved in DB for this part.
417
     */
418
    public function getCustomProductURL(): string
419
    {
420
        return $this->manufacturer_product_url;
421
    }
422
423
    /**
424
     *  Get the category of this part.
425
     *
426
     * There is always a category, for each part!
427
     *
428
     * @return Category the category of this part
429
     */
430
    public function getCategory(): Category
431
    {
432
        return $this->category;
433
    }
434
435
    /**
436
     *  Get the footprint of this part (if there is one).
437
     *
438
     * @return Footprint the footprint of this part (if there is one)
439
     */
440
    public function getFootprint(): ?Footprint
441
    {
442
        return $this->footprint;
443
    }
444
445
    /**
446
     *  Get the manufacturer of this part (if there is one).
447
     *
448
     * @return Manufacturer the manufacturer of this part (if there is one)
449
     */
450
    public function getManufacturer(): ?Manufacturer
451
    {
452
        return $this->manufacturer;
453
    }
454
455
    /**
456
     *  Get the master picture "Attachement"-object of this part (if there is one).
457
     *
458
     * @return Attachment the master picture Attachement of this part (if there is one)
459
     */
460
    public function getMasterPictureAttachement(): ?Attachment
461
    {
462
        return $this->master_picture_attachment;
463
    }
464
465
    /**
466
     *  Get all orderdetails of this part.
467
     *
468
     * @param bool $hide_obsolete If true, obsolete orderdetails will NOT be returned
469
     *
470
     * @return Orderdetail[] * all orderdetails as a one-dimensional array of Orderdetails objects
471
     *                        (empty array if there are no ones)
472
     *                        * the array is sorted by the suppliers names / minimum order quantity
473
     *
474
     */
475
    public function getOrderdetails(bool $hide_obsolete = false) : PersistentCollection
476
    {
477
        //If needed hide the obsolete entries
478
        if ($hide_obsolete) {
479
            $orderdetails = $this->orderdetails;
480
            foreach ($orderdetails as $key => $details) {
481
                if ($details->getObsolete()) {
482
                    unset($orderdetails[$key]);
483
                }
484
            }
485
486
            return $orderdetails;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $orderdetails returns the type App\Entity\PriceInformations\Orderdetail[] which is incompatible with the type-hinted return Doctrine\ORM\PersistentCollection.
Loading history...
487
        }
488
489
        return $this->orderdetails;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->orderdetails returns the type App\Entity\PriceInformations\Orderdetail[] which is incompatible with the type-hinted return Doctrine\ORM\PersistentCollection.
Loading history...
490
    }
491
492
    /**
493
     *  Get all devices which uses this part.
494
     *
495
     * @return Device[] * all devices which uses this part as a one-dimensional array of Device objects
496
     *                  (empty array if there are no ones)
497
     *                  * the array is sorted by the devices names
498
     *
499
     */
500
    public function getDevices(): array
501
    {
502
        return $this->devices;
503
    }
504
505
    /**
506
     *  Get all prices of this part.
507
     *
508
     * This method simply gets the prices of the orderdetails and prepare them.\n
509
     * In the returned array/string there is a price for every supplier.
510
     * @param int $quantity this is the quantity to choose the correct priceinformation
511
     * @param int|null $multiplier * This is the multiplier which will be applied to every single price
512
     *                                   * If you pass NULL, the number from $quantity will be used
513
     * @param bool $hide_obsolete If true, prices from obsolete orderdetails will NOT be returned
514
     *
515
     * @return float[]  all prices as an array of floats (if "$delimeter == NULL" & "$float_array == true")
516
     *
517
     * @throws \Exception if there was an error
518
     */
519
    public function getPrices(int $quantity = 1, $multiplier = null, bool $hide_obsolete = false) : array
520
    {
521
        $prices = array();
522
523
        foreach ($this->getOrderdetails($hide_obsolete) as $details) {
524
            $prices[] = $details->getPrice($quantity, $multiplier);
525
        }
526
527
        return $prices;
528
    }
529
530
    /**
531
     *  Get the average price of all orderdetails.
532
     *
533
     * With the $multiplier you're able to multiply the price before it will be returned.
534
     * This is useful if you want to have the price as a string with currency, but multiplied with a factor.
535
     *
536
     * @param int      $quantity        this is the quantity to choose the correct priceinformations
537
     * @param int|null $multiplier      * This is the multiplier which will be applied to every single price
538
     *                                  * If you pass NULL, the number from $quantity will be used
539
     *
540
     * @return float  price (if "$as_money_string == false")
541
     *
542
     * @throws \Exception if there was an error
543
     */
544
    public function getAveragePrice(int $quantity = 1, $multiplier = null) : ?float
545
    {
546
        $prices = $this->getPrices($quantity, $multiplier, true);
0 ignored issues
show
Unused Code introduced by
The assignment to $prices is dead and can be removed.
Loading history...
547
        //Findout out
548
549
        $average_price = null;
550
551
        $count = 0;
552
        foreach ($this->getOrderdetails() as $orderdetail) {
553
            $price = $orderdetail->getPrice(1, null);
554
            if (null !== $price) {
555
                $average_price += $price;
556
                ++$count;
557
            }
558
        }
559
560
        if ($count > 0) {
561
            $average_price /= $count;
562
        }
563
564
        return $average_price;
565
    }
566
567
    /**
568
     * Checks if this part is marked, for that it needs further review.
569
     * @return bool
570
     */
571
    public function isNeedsReview(): bool
572
    {
573
        return $this->needs_review;
574
    }
575
576
    /**
577
     * Sets the "needs review" status of this part.
578
     * @param bool $needs_review
579
     * @return Part
580
     */
581
    public function setNeedsReview(bool $needs_review): Part
582
    {
583
        $this->needs_review = $needs_review;
584
        return $this;
585
    }
586
587
    /**
588
     * Get all part lots where this part is stored.
589
     * @return PartLot[]|PersistentCollection
590
     */
591
    public function getPartLots() : PersistentCollection
592
    {
593
        return $this->partLots;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->partLots returns the type App\Entity\Parts\PartLot[]|null which is incompatible with the type-hinted return Doctrine\ORM\PersistentCollection.
Loading history...
594
    }
595
596
597
    /**
598
     * Returns the assigned manufacturer product number (MPN) for this part.
599
     * @return string
600
     */
601
    public function getManufacturerProductNumber(): string
602
    {
603
        return $this->manufacturer_product_number;
604
    }
605
606
    /**
607
     * Sets the manufacturer product number (MPN) for this part.
608
     * @param string $manufacturer_product_number
609
     * @return Part
610
     */
611
    public function setManufacturerProductNumber(string $manufacturer_product_number): Part
612
    {
613
        $this->manufacturer_product_number = $manufacturer_product_number;
614
        return $this;
615
    }
616
617
    /**
618
     * Gets the measurement unit in which the part's amount should be measured.
619
     * Returns null if no specific unit was that. That means the parts are measured simply in quantity numbers.
620
     * @return ?MeasurementUnit
621
     */
622
    public function getPartUnit(): ?MeasurementUnit
623
    {
624
        return $this->partUnit;
625
    }
626
627
    /**
628
     * Sets the measurement unit in which the part's amount should be measured.
629
     * Set to null, if the part should be measured in quantities.
630
     * @param ?MeasurementUnit $partUnit
631
     * @return Part
632
     */
633
    public function setPartUnit(?MeasurementUnit $partUnit): Part
634
    {
635
        $this->partUnit = $partUnit;
636
        return $this;
637
    }
638
639
    /**
640
     * Gets a comma separated list, of tags, that are assigned to this part
641
     * @return string
642
     */
643
    public function getTags(): string
644
    {
645
        return $this->tags;
646
    }
647
648
    /**
649
     * Sets a comma separated list of tags, that are assigned to this part.
650
     * @param string $tags
651
     * @return Part
652
     */
653
    public function setTags(string $tags): Part
654
    {
655
        $this->tags = $tags;
656
        return $this;
657
    }
658
659
    /**
660
     * Returns the mass of a single part unit.
661
     * Returns null, if the mass is unknown/not set yet
662
     * @return float|null
663
     */
664
    public function getMass(): ?float
665
    {
666
        return $this->mass;
667
    }
668
669
    /**
670
     * Sets the mass of a single part unit.
671
     * Sett to null, if the mass is unknown.
672
     * @param float|null $mass
673
     * @return Part
674
     */
675
    public function setMass(?float $mass): Part
676
    {
677
        $this->mass = $mass;
678
        return $this;
679
    }
680
681
    /**
682
     * Checks if this part uses the float amount .
683
     * This setting is based on the part unit (see MeasurementUnit->isInteger()).
684
     * @return bool True if the float amount field should be used. False if the integer instock field should be used.
685
     */
686
    public function useFloatAmount(): bool
687
    {
688
        if ($this->partUnit instanceof MeasurementUnit) {
689
            return $this->partUnit->isInteger();
690
        }
691
692
        //When no part unit is set, treat it as part count, and so use the integer value.
693
        return false;
694
    }
695
696
    /**
697
     * Returns the summed amount of this part (over all part lots)
698
     * @return float
699
     */
700
    public function getAmountSum() : float
701
    {
702
        //TODO: Find a method to do this natively in SQL, the current method could be a bit slow
703
        $sum = 0;
704
        foreach($this->getPartLots() as $lot) {
705
            //Dont use the instock value, if it is unkown
706
            if ($lot->isInstockUnknown()) {
707
                continue;
708
            }
709
710
            $sum += $lot->getAmount();
711
        }
712
713
        if(!$this->useFloatAmount()) {
714
            return $sum;
715
        }
716
717
        return round($sum);
718
    }
719
720
    /********************************************************************************
721
     *
722
     *   Setters
723
     *
724
     *********************************************************************************/
725
726
    /**
727
     *  Set the description.
728
     *
729
     * @param string $new_description the new description
730
     *
731
     * @return self
732
     */
733
    public function setDescription(?string $new_description): self
734
    {
735
        $this->description = $new_description;
736
737
        return $this;
738
    }
739
740
    /**
741
     *  Set the minimum amount of parts that have to be instock.
742
     *  See getPartUnit() for the associated unit.
743
     *
744
     * @param int $new_mininstock the new count of parts which should be in stock at least
745
     *
746
     * @return self
747
     */
748
    public function setMinAmount(float $new_mininstock): self
0 ignored issues
show
Unused Code introduced by
The parameter $new_mininstock is not used and could be removed. ( Ignorable by Annotation )

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

748
    public function setMinAmount(/** @scrutinizer ignore-unused */ float $new_mininstock): self

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
749
    {
750
        //Assert::natural($new_mininstock, 'The new minimum instock value must be positive! Got %s.');
751
752
        $this->minamount = $new_minamount;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $new_minamount seems to be never defined.
Loading history...
753
754
        return $this;
755
    }
756
757
    /**
758
     *  Set the comment.
759
     *
760
     * @param string $new_comment the new comment
761
     *
762
     * @return self
763
     */
764
    public function setComment(string $new_comment): self
765
    {
766
        $this->comment = $new_comment;
767
768
        return $this;
769
    }
770
771
    /**
772
     *  Set the "manual_order" attribute.
773
     *
774
     * @param bool     $new_manual_order          the new "manual_order" attribute
775
     * @param int      $new_order_quantity        the new order quantity
776
     * @param int|null $new_order_orderdetails_id * the ID of the new order orderdetails
777
     *                                            * or Zero for "no order orderdetails"
778
     *                                            * or NULL for automatic order orderdetails
779
     *                                            (if the part has exactly one orderdetails,
780
     *                                            set this orderdetails as order orderdetails.
781
     *                                            Otherwise, set "no order orderdetails")
782
     *
783
     * @return self
784
     */
785
    public function setManualOrder(bool $new_manual_order, int $new_order_quantity = 1, ?Orderdetail $new_order_orderdetail = null): Part
786
    {
787
        //Assert::greaterThan($new_order_quantity, 0, 'The new order quantity must be greater zero. Got %s!');
788
789
        $this->manual_order = $new_manual_order;
790
791
        //TODO;
792
        $this->order_orderdetail = $new_order_orderdetail;
793
        $this->order_quantity = $new_order_quantity;
794
795
        return $this;
796
    }
797
798
    /**
799
     *  Set the category of this Part.
800
     *
801
     *     Every part must have a valid category (in contrast to the
802
     *          attributes "footprint", "storelocation", ...)!
803
     *
804
     * @param Category $category The new category of this part
805
     *
806
     * @return self
807
     */
808
    public function setCategory(Category $category): Part
809
    {
810
        $this->category = $category;
811
812
        return $this;
813
    }
814
815
    /**
816
     * Set the new Footprint of this Part.
817
     *
818
     * @param Footprint|null $new_footprint The new footprint of this part. Set to null, if this part should not have
819
     *                                      a footprint.
820
     *
821
     * @return self
822
     */
823
    public function setFootprint(?Footprint $new_footprint): Part
824
    {
825
        $this->footprint = $new_footprint;
826
827
        return $this;
828
    }
829
830
    /**
831
     * Sets the new manufacturer of this part.
832
     *
833
     * @param Manufacturer|null $new_manufacturer The new Manufacturer of this part. Set to null, if this part should
834
     *                                            not have a manufacturer.
835
     *
836
     * @return Part
837
     */
838
    public function setManufacturer(?Manufacturer $new_manufacturer): self
839
    {
840
        $this->manufacturer = $new_manufacturer;
841
842
        return $this;
843
    }
844
845
    /**
846
     * Set the favorite status for this part.
847
     *
848
     * @param $new_favorite_status bool The new favorite status, that should be applied on this part.
849
     *      Set this to true, when the part should be a favorite.
850
     *
851
     * @return self
852
     */
853
    public function setFavorite(bool $new_favorite_status): self
854
    {
855
        $this->favorite = $new_favorite_status;
856
857
        return $this;
858
    }
859
860
    /**
861
     * Sets the URL to the manufacturer site about this Part. Set to "" if this part should use the automatically URL based on its manufacturer.
862
     *
863
     * @param string $new_url The new url
864
     *
865
     * @return self
866
     */
867
    public function setManufacturerProductURL(string $new_url): self
868
    {
869
        $this->manufacturer_product_url = $new_url;
870
871
        return $this;
872
    }
873
}
874