Passed
Push — master ( 6a0ada...813e7d )
by Jan
03:50
created

Part::getPrices()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 3
dl 0
loc 9
rs 10
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", cascade={"persist", "remove"}, orphanRemoval=true)
183
     * @Assert\Valid()
184
     */
185
    protected $partLots;
186
187
    /**
188
     * @var float
189
     * @ORM\Column(type="float")
190
     * @Assert\PositiveOrZero()
191
     *
192
     * @ColumnSecurity(prefix="mininstock", type="integer")
193
     */
194
    protected $minamount = 0;
195
196
    /**
197
     * @var string
198
     * @ORM\Column(type="text")
199
     * @ColumnSecurity(prefix="comment")
200
     */
201
    protected $comment = '';
202
203
    /**
204
     * @var bool
205
     * @ORM\Column(type="boolean")
206
     */
207
    protected $visible = true;
208
209
    /**
210
     * @var bool
211
     * @ORM\Column(type="boolean")
212
     * @ColumnSecurity(type="boolean")
213
     */
214
    protected $favorite = false;
215
216
    /**
217
     * @var int
218
     * @ORM\Column(type="integer")
219
     * @ColumnSecurity(prefix="order", type="integer")
220
     */
221
    protected $order_quantity = 0;
222
223
    /**
224
     * @var bool
225
     * @ORM\Column(type="boolean")
226
     * @ColumnSecurity(prefix="order", type="boolean")
227
     */
228
    protected $manual_order = false;
229
230
    /**
231
     * @var string
232
     * @ORM\Column(type="string")
233
     * @ColumnSecurity(prefix="manufacturer", type="string", placeholder="")
234
     */
235
    protected $manufacturer_product_url = '';
236
237
    /**
238
     * @var string
239
     * @ORM\Column(type="string")
240
     * @ColumnSecurity(prefix="manufacturer", type="string", placeholder="")
241
     */
242
    protected $manufacturer_product_number;
243
244
    /**
245
     * @var bool Determines if this part entry needs review (for example, because it is work in progress)
246
     * @ORM\Column(type="boolean")
247
     */
248
    protected $needs_review = false;
249
250
    /**
251
     * @var ?MeasurementUnit The unit in which the part's amount is measured.
252
     * @ORM\ManyToOne(targetEntity="MeasurementUnit")
253
     * @ORM\JoinColumn(name="id_part_unit", referencedColumnName="id", nullable=true)
254
     */
255
    protected $partUnit;
256
257
    /**
258
     * @var string A comma seperated list of tags, assocciated with the part.
259
     * @ORM\Column(type="text")
260
     */
261
    protected $tags;
262
263
    /**
264
     * @var float|null How much a single part unit weighs in gramms.
265
     * @ORM\Column(type="float", nullable=true)
266
     * @Assert\Positive()
267
     */
268
    protected $mass;
269
270
    /**
271
     * Returns the ID as an string, defined by the element class.
272
     * This should have a form like P000014, for a part with ID 14.
273
     *
274
     * @return string The ID as a string;
275
     */
276
    public function getIDString(): string
277
    {
278
        return 'P' . sprintf('%06d', $this->getID());
279
    }
280
281
    /*********************************************************************************
282
     * Getters
283
     ********************************************************************************/
284
285
    /**
286
     * Get the description string like it is saved in the database.
287
     * This can contain BBCode, it is not parsed yet.
288
     *
289
     * @return string the description
290
     */
291
    public function getDescription(): string
292
    {
293
        return  htmlspecialchars($this->description);
294
    }
295
296
    /**
297
     *  Get the count of parts which must be in stock at least.
298
     *
299
     * @return int count of parts which must be in stock at least
300
     */
301
    public function getMinAmount(): float
302
    {
303
        return $this->minamount;
304
    }
305
306
    /**
307
     *  Get the comment associated with this part.
308
     *
309
     * @return string The raw/unparsed comment
310
     */
311
    public function getComment(): string
312
    {
313
        return htmlspecialchars($this->comment);
314
    }
315
316
    /**
317
     *  Get if this part is obsolete.
318
     *
319
     *     A Part is marked as "obsolete" if all their orderdetails are marked as "obsolete".
320
     *          If a part has no orderdetails, the part isn't marked as obsolete.
321
     *
322
     * @return bool true, if this part is obsolete. false, if this part isn't obsolete
323
     */
324
    public function isObsolete(): bool
325
    {
326
        $all_orderdetails = $this->getOrderdetails();
327
328
        if (0 === count($all_orderdetails)) {
329
            return false;
330
        }
331
332
        foreach ($all_orderdetails as $orderdetails) {
333
            if (!$orderdetails->getObsolete()) {
334
                return false;
335
            }
336
        }
337
338
        return true;
339
    }
340
341
    /**
342
     *  Get if this part is visible.
343
     *
344
     * @return bool true if this part is visible
345
     *              false if this part isn't visible
346
     */
347
    public function isVisible(): bool
348
    {
349
        return $this->visible;
350
    }
351
352
    /**
353
     * Get if this part is a favorite.
354
     *
355
     * @return bool * true if this part is a favorite
356
     *              * false if this part is not a favorite.
357
     */
358
    public function isFavorite(): bool
359
    {
360
        return $this->favorite;
361
    }
362
363
    /**
364
     *  Get the selected order orderdetails of this part.
365
     * @return Orderdetail the selected order orderdetails
366
     */
367
    public function getOrderOrderdetails(): ?Orderdetail
368
    {
369
        return $this->order_orderdetail;
370
    }
371
372
    /**
373
     *  Get the order quantity of this part.
374
     *
375
     * @return int the order quantity
376
     */
377
    public function getOrderQuantity(): int
378
    {
379
        return $this->order_quantity;
380
    }
381
382
    /**
383
     *  Check if this part is marked for manual ordering.
384
     *
385
     * @return bool the "manual_order" attribute
386
     */
387
    public function isMarkedForManualOrder(): bool
388
    {
389
        return $this->manual_order;
390
    }
391
392
    /**
393
     *  Get the link to the website of the article on the manufacturers website
394
     *  When no this part has no explicit url set, then it is tried to generate one from the Manufacturer of this part
395
     *  automatically.
396
     *
397
     * @param
398
     *
399
     * @return string the link to the article
400
     */
401
    public function getManufacturerProductUrl(): string
402
    {
403
        if ('' !== $this->manufacturer_product_url) {
404
            return $this->manufacturer_product_url;
405
        }
406
407
        if (null !== $this->getManufacturer()) {
408
            return $this->getManufacturer()->getAutoProductUrl($this->name);
409
        }
410
411
        return ''; // no url is available
412
    }
413
414
    /**
415
     * Similar to getManufacturerProductUrl, but here only the database value is returned.
416
     *
417
     * @return string The manufacturer url saved in DB for this part.
418
     */
419
    public function getCustomProductURL(): string
420
    {
421
        return $this->manufacturer_product_url;
422
    }
423
424
    /**
425
     *  Get the category of this part.
426
     *
427
     * There is always a category, for each part!
428
     *
429
     * @return Category the category of this part
430
     */
431
    public function getCategory(): Category
432
    {
433
        return $this->category;
434
    }
435
436
    /**
437
     *  Get the footprint of this part (if there is one).
438
     *
439
     * @return Footprint the footprint of this part (if there is one)
440
     */
441
    public function getFootprint(): ?Footprint
442
    {
443
        return $this->footprint;
444
    }
445
446
    /**
447
     *  Get the manufacturer of this part (if there is one).
448
     *
449
     * @return Manufacturer the manufacturer of this part (if there is one)
450
     */
451
    public function getManufacturer(): ?Manufacturer
452
    {
453
        return $this->manufacturer;
454
    }
455
456
    /**
457
     *  Get the master picture "Attachement"-object of this part (if there is one).
458
     *
459
     * @return Attachment the master picture Attachement of this part (if there is one)
460
     */
461
    public function getMasterPictureAttachement(): ?Attachment
462
    {
463
        return $this->master_picture_attachment;
464
    }
465
466
    /**
467
     *  Get all orderdetails of this part.
468
     *
469
     * @param bool $hide_obsolete If true, obsolete orderdetails will NOT be returned
470
     *
471
     * @return Orderdetail[] * all orderdetails as a one-dimensional array of Orderdetails objects
472
     *                        (empty array if there are no ones)
473
     *                        * the array is sorted by the suppliers names / minimum order quantity
474
     *
475
     */
476
    public function getOrderdetails(bool $hide_obsolete = false) : PersistentCollection
477
    {
478
        //If needed hide the obsolete entries
479
        if ($hide_obsolete) {
480
            $orderdetails = $this->orderdetails;
481
            foreach ($orderdetails as $key => $details) {
482
                if ($details->getObsolete()) {
483
                    unset($orderdetails[$key]);
484
                }
485
            }
486
487
            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...
488
        }
489
490
        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...
491
    }
492
493
    /**
494
     *  Get all devices which uses this part.
495
     *
496
     * @return Device[] * all devices which uses this part as a one-dimensional array of Device objects
497
     *                  (empty array if there are no ones)
498
     *                  * the array is sorted by the devices names
499
     *
500
     */
501
    public function getDevices(): array
502
    {
503
        return $this->devices;
504
    }
505
506
    /**
507
     *  Get all prices of this part.
508
     *
509
     * This method simply gets the prices of the orderdetails and prepare them.\n
510
     * In the returned array/string there is a price for every supplier.
511
     * @param int $quantity this is the quantity to choose the correct priceinformation
512
     * @param int|null $multiplier * This is the multiplier which will be applied to every single price
513
     *                                   * If you pass NULL, the number from $quantity will be used
514
     * @param bool $hide_obsolete If true, prices from obsolete orderdetails will NOT be returned
515
     *
516
     * @return float[]  all prices as an array of floats (if "$delimeter == NULL" & "$float_array == true")
517
     *
518
     * @throws \Exception if there was an error
519
     */
520
    public function getPrices(int $quantity = 1, $multiplier = null, bool $hide_obsolete = false) : array
521
    {
522
        $prices = array();
523
524
        foreach ($this->getOrderdetails($hide_obsolete) as $details) {
525
            $prices[] = $details->getPrice($quantity, $multiplier);
526
        }
527
528
        return $prices;
529
    }
530
531
    /**
532
     *  Get the average price of all orderdetails.
533
     *
534
     * With the $multiplier you're able to multiply the price before it will be returned.
535
     * This is useful if you want to have the price as a string with currency, but multiplied with a factor.
536
     *
537
     * @param int      $quantity        this is the quantity to choose the correct priceinformations
538
     * @param int|null $multiplier      * This is the multiplier which will be applied to every single price
539
     *                                  * If you pass NULL, the number from $quantity will be used
540
     *
541
     * @return float  price (if "$as_money_string == false")
542
     *
543
     * @throws \Exception if there was an error
544
     */
545
    public function getAveragePrice(int $quantity = 1, $multiplier = null) : ?float
546
    {
547
        $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...
548
        //Findout out
549
550
        $average_price = null;
551
552
        $count = 0;
553
        foreach ($this->getOrderdetails() as $orderdetail) {
554
            $price = $orderdetail->getPrice(1, null);
555
            if (null !== $price) {
556
                $average_price += $price;
557
                ++$count;
558
            }
559
        }
560
561
        if ($count > 0) {
562
            $average_price /= $count;
563
        }
564
565
        return $average_price;
566
    }
567
568
    /**
569
     * Checks if this part is marked, for that it needs further review.
570
     * @return bool
571
     */
572
    public function isNeedsReview(): bool
573
    {
574
        return $this->needs_review;
575
    }
576
577
    /**
578
     * Sets the "needs review" status of this part.
579
     * @param bool $needs_review
580
     * @return Part
581
     */
582
    public function setNeedsReview(bool $needs_review): Part
583
    {
584
        $this->needs_review = $needs_review;
585
        return $this;
586
    }
587
588
    /**
589
     * Get all part lots where this part is stored.
590
     * @return PartLot[]|PersistentCollection
591
     */
592
    public function getPartLots() : PersistentCollection
593
    {
594
        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...
595
    }
596
597
    public function addPartLot(PartLot $lot): Part
598
    {
599
        $lot->setPart($this);
600
        $this->partLots->add($lot);
0 ignored issues
show
Bug introduced by
The method add() does not exist on null. ( Ignorable by Annotation )

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

600
        $this->partLots->/** @scrutinizer ignore-call */ 
601
                         add($lot);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
601
        return $this;
602
    }
603
604
    public function removePartLot(PartLot $lot): Part
605
    {
606
        $this->partLots->removeElement($lot);
607
        return $this;
608
    }
609
610
    /**
611
     * Returns the assigned manufacturer product number (MPN) for this part.
612
     * @return string
613
     */
614
    public function getManufacturerProductNumber(): string
615
    {
616
        return $this->manufacturer_product_number;
617
    }
618
619
    /**
620
     * Sets the manufacturer product number (MPN) for this part.
621
     * @param string $manufacturer_product_number
622
     * @return Part
623
     */
624
    public function setManufacturerProductNumber(string $manufacturer_product_number): Part
625
    {
626
        $this->manufacturer_product_number = $manufacturer_product_number;
627
        return $this;
628
    }
629
630
    /**
631
     * Gets the measurement unit in which the part's amount should be measured.
632
     * Returns null if no specific unit was that. That means the parts are measured simply in quantity numbers.
633
     * @return ?MeasurementUnit
634
     */
635
    public function getPartUnit(): ?MeasurementUnit
636
    {
637
        return $this->partUnit;
638
    }
639
640
    /**
641
     * Sets the measurement unit in which the part's amount should be measured.
642
     * Set to null, if the part should be measured in quantities.
643
     * @param ?MeasurementUnit $partUnit
644
     * @return Part
645
     */
646
    public function setPartUnit(?MeasurementUnit $partUnit): Part
647
    {
648
        $this->partUnit = $partUnit;
649
        return $this;
650
    }
651
652
    /**
653
     * Gets a comma separated list, of tags, that are assigned to this part
654
     * @return string
655
     */
656
    public function getTags(): string
657
    {
658
        return $this->tags;
659
    }
660
661
    /**
662
     * Sets a comma separated list of tags, that are assigned to this part.
663
     * @param string $tags
664
     * @return Part
665
     */
666
    public function setTags(string $tags): Part
667
    {
668
        $this->tags = $tags;
669
        return $this;
670
    }
671
672
    /**
673
     * Returns the mass of a single part unit.
674
     * Returns null, if the mass is unknown/not set yet
675
     * @return float|null
676
     */
677
    public function getMass(): ?float
678
    {
679
        return $this->mass;
680
    }
681
682
    /**
683
     * Sets the mass of a single part unit.
684
     * Sett to null, if the mass is unknown.
685
     * @param float|null $mass
686
     * @return Part
687
     */
688
    public function setMass(?float $mass): Part
689
    {
690
        $this->mass = $mass;
691
        return $this;
692
    }
693
694
    /**
695
     * Checks if this part uses the float amount .
696
     * This setting is based on the part unit (see MeasurementUnit->isInteger()).
697
     * @return bool True if the float amount field should be used. False if the integer instock field should be used.
698
     */
699
    public function useFloatAmount(): bool
700
    {
701
        if ($this->partUnit instanceof MeasurementUnit) {
702
            return $this->partUnit->isInteger();
703
        }
704
705
        //When no part unit is set, treat it as part count, and so use the integer value.
706
        return false;
707
    }
708
709
    /**
710
     * Returns the summed amount of this part (over all part lots)
711
     * @return float
712
     */
713
    public function getAmountSum() : float
714
    {
715
        //TODO: Find a method to do this natively in SQL, the current method could be a bit slow
716
        $sum = 0;
717
        foreach($this->getPartLots() as $lot) {
718
            //Dont use the instock value, if it is unkown
719
            if ($lot->isInstockUnknown()) {
720
                continue;
721
            }
722
723
            $sum += $lot->getAmount();
724
        }
725
726
        if(!$this->useFloatAmount()) {
727
            return $sum;
728
        }
729
730
        return round($sum);
731
    }
732
733
    /********************************************************************************
734
     *
735
     *   Setters
736
     *
737
     *********************************************************************************/
738
739
    /**
740
     *  Set the description.
741
     *
742
     * @param string $new_description the new description
743
     *
744
     * @return self
745
     */
746
    public function setDescription(?string $new_description): self
747
    {
748
        $this->description = $new_description;
749
750
        return $this;
751
    }
752
753
    /**
754
     *  Set the minimum amount of parts that have to be instock.
755
     *  See getPartUnit() for the associated unit.
756
     *
757
     * @param int $new_mininstock the new count of parts which should be in stock at least
758
     *
759
     * @return self
760
     */
761
    public function setMinAmount(float $new_minamount): self
762
    {
763
        //Assert::natural($new_mininstock, 'The new minimum instock value must be positive! Got %s.');
764
765
        $this->minamount = $new_minamount;
766
767
        return $this;
768
    }
769
770
    /**
771
     *  Set the comment.
772
     *
773
     * @param string $new_comment the new comment
774
     *
775
     * @return self
776
     */
777
    public function setComment(string $new_comment): self
778
    {
779
        $this->comment = $new_comment;
780
781
        return $this;
782
    }
783
784
    /**
785
     *  Set the "manual_order" attribute.
786
     *
787
     * @param bool     $new_manual_order          the new "manual_order" attribute
788
     * @param int      $new_order_quantity        the new order quantity
789
     * @param int|null $new_order_orderdetails_id * the ID of the new order orderdetails
790
     *                                            * or Zero for "no order orderdetails"
791
     *                                            * or NULL for automatic order orderdetails
792
     *                                            (if the part has exactly one orderdetails,
793
     *                                            set this orderdetails as order orderdetails.
794
     *                                            Otherwise, set "no order orderdetails")
795
     *
796
     * @return self
797
     */
798
    public function setManualOrder(bool $new_manual_order, int $new_order_quantity = 1, ?Orderdetail $new_order_orderdetail = null): Part
799
    {
800
        //Assert::greaterThan($new_order_quantity, 0, 'The new order quantity must be greater zero. Got %s!');
801
802
        $this->manual_order = $new_manual_order;
803
804
        //TODO;
805
        $this->order_orderdetail = $new_order_orderdetail;
806
        $this->order_quantity = $new_order_quantity;
807
808
        return $this;
809
    }
810
811
    /**
812
     *  Set the category of this Part.
813
     *
814
     *     Every part must have a valid category (in contrast to the
815
     *          attributes "footprint", "storelocation", ...)!
816
     *
817
     * @param Category $category The new category of this part
818
     *
819
     * @return self
820
     */
821
    public function setCategory(Category $category): Part
822
    {
823
        $this->category = $category;
824
825
        return $this;
826
    }
827
828
    /**
829
     * Set the new Footprint of this Part.
830
     *
831
     * @param Footprint|null $new_footprint The new footprint of this part. Set to null, if this part should not have
832
     *                                      a footprint.
833
     *
834
     * @return self
835
     */
836
    public function setFootprint(?Footprint $new_footprint): Part
837
    {
838
        $this->footprint = $new_footprint;
839
840
        return $this;
841
    }
842
843
    /**
844
     * Sets the new manufacturer of this part.
845
     *
846
     * @param Manufacturer|null $new_manufacturer The new Manufacturer of this part. Set to null, if this part should
847
     *                                            not have a manufacturer.
848
     *
849
     * @return Part
850
     */
851
    public function setManufacturer(?Manufacturer $new_manufacturer): self
852
    {
853
        $this->manufacturer = $new_manufacturer;
854
855
        return $this;
856
    }
857
858
    /**
859
     * Set the favorite status for this part.
860
     *
861
     * @param $new_favorite_status bool The new favorite status, that should be applied on this part.
862
     *      Set this to true, when the part should be a favorite.
863
     *
864
     * @return self
865
     */
866
    public function setFavorite(bool $new_favorite_status): self
867
    {
868
        $this->favorite = $new_favorite_status;
869
870
        return $this;
871
    }
872
873
    /**
874
     * Sets the URL to the manufacturer site about this Part. Set to "" if this part should use the automatically URL based on its manufacturer.
875
     *
876
     * @param string $new_url The new url
877
     *
878
     * @return self
879
     */
880
    public function setManufacturerProductURL(string $new_url): self
881
    {
882
        $this->manufacturer_product_url = $new_url;
883
884
        return $this;
885
    }
886
}
887