Passed
Push — master ( 0663a0...89258b )
by Jan
04:32
created

Pricedetail   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 256
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 35
dl 0
loc 256
rs 10
c 0
b 0
f 0
wmc 21

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getPrice() 0 3 1
A __construct() 0 3 1
A getPricePerUnit() 0 5 1
A setOrderdetail() 0 4 1
A setPrice() 0 7 1
A getMinDiscountQuantity() 0 8 5
A getCurrency() 0 3 1
A getIDString() 0 3 1
A getPriceRelatedQuantity() 0 7 5
A setMinDiscountQuantity() 0 5 1
A getOrderdetail() 0 3 1
A setPriceRelatedQuantity() 0 5 1
A setCurrency() 0 4 1
1
<?php
2
/**
3
 * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony)
4
 *
5
 * Copyright (C) 2019 Jan Böhmer (https://github.com/jbtronics)
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * as published by the Free Software Foundation; either version 2
10
 * of the License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
20
 *
21
 */
22
23
declare(strict_types=1);
24
25
/**
26
 * part-db version 0.1
27
 * Copyright (C) 2005 Christoph Lechner
28
 * http://www.cl-projects.de/.
29
 *
30
 * part-db version 0.2+
31
 * Copyright (C) 2009 K. Jacobs and others (see authors.php)
32
 * http://code.google.com/p/part-db/
33
 *
34
 * Part-DB Version 0.4+
35
 * Copyright (C) 2016 - 2019 Jan Böhmer
36
 * https://github.com/jbtronics
37
 *
38
 * This program is free software; you can redistribute it and/or
39
 * modify it under the terms of the GNU General Public License
40
 * as published by the Free Software Foundation; either version 2
41
 * of the License, or (at your option) any later version.
42
 *
43
 * This program is distributed in the hope that it will be useful,
44
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
45
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
46
 * GNU General Public License for more details.
47
 *
48
 * You should have received a copy of the GNU General Public License
49
 * along with this program; if not, write to the Free Software
50
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
51
 */
52
53
namespace App\Entity\PriceInformations;
54
55
use App\Entity\Base\DBElement;
56
use App\Entity\Base\TimestampTrait;
57
use App\Validator\Constraints\Selectable;
58
use Doctrine\ORM\Mapping as ORM;
59
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
60
use Symfony\Component\Validator\Constraints as Assert;
61
62
/**
63
 * Class Pricedetail.
64
 *
65
 * @ORM\Entity()
66
 * @ORM\Table("`pricedetails`")
67
 * @ORM\HasLifecycleCallbacks()
68
 * @UniqueEntity(fields={"orderdetail", "min_discount_quantity"})
69
 */
70
class Pricedetail extends DBElement
71
{
72
73
    public const PRICE_PRECISION = 5;
74
75
    use TimestampTrait;
76
77
    /**
78
     * @var Orderdetail
79
     * @ORM\ManyToOne(targetEntity="Orderdetail", inversedBy="pricedetails")
80
     * @ORM\JoinColumn(name="orderdetails_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
81
     * @Assert\NotNull()
82
     */
83
    protected $orderdetail;
84
85
    /**
86
     * @var string The price related to the detail. (Given in the selected currency)
87
     * @ORM\Column(type="decimal", precision=11, scale=5)
88
     * @Assert\Positive()
89
     */
90
    protected $price = '0.0';
91
92
    /**
93
     * @var ?Currency The currency used for the current price information.
94
     * If this is null, the global base unit is assumed.
95
     * @ORM\ManyToOne(targetEntity="Currency")
96
     * @ORM\JoinColumn(name="id_currency", referencedColumnName="id", nullable=true)
97
     * @Selectable()
98
     */
99
    protected $currency;
100
101
    /**
102
     * @var float
103
     * @ORM\Column(type="float")
104
     * @Assert\Positive()
105
     */
106
    protected $price_related_quantity = 1.0;
107
108
    /**
109
     * @var float
110
     * @ORM\Column(type="float")
111
     * @Assert\Positive()
112
     */
113
    protected $min_discount_quantity = 1.0;
114
115
    /**
116
     * @var bool
117
     * @ORM\Column(type="boolean")
118
     */
119
    protected $manual_input = true;
120
121
    public function __construct()
122
    {
123
        bcscale(static::PRICE_PRECISION);
124
    }
125
126
    /********************************************************************************
127
     *
128
     *   Getters
129
     *
130
     *********************************************************************************/
131
132
    /**
133
     * Get the orderdetail to which this pricedetail belongs to this pricedetails.
134
     *
135
     * @return Orderdetail The orderdetail this price belongs to.
136
     */
137
    public function getOrderdetail(): Orderdetail
138
    {
139
        return $this->orderdetail;
140
    }
141
142
    /**
143
     * Returns the price associated with this pricedetail.
144
     * It is given in current currency and for the price related quantity.
145
     * @return string The price as string, like returned raw from DB.
146
     */
147
    public function getPrice() : string
148
    {
149
        return $this->price;
150
    }
151
152
    /**
153
     * Get the price for a single unit in the currency associated with this price detail.
154
     *
155
     * @param float|string $multiplier      The returned price (float or string) will be multiplied
156
     *                              with this multiplier.
157
     *
158
     *     You will get the price for $multiplier parts. If you want the price which is stored
159
     *          in the database, you have to pass the "price_related_quantity" count as $multiplier.
160
     *
161
     * @return string  the price as a bcmath string
162
     */
163
    public function getPricePerUnit($multiplier = 1.0) : string
164
    {
165
        $multiplier = (string) $multiplier;
166
        $tmp = bcmul($this->price, $multiplier, static::PRICE_PRECISION);
167
        return bcdiv($tmp, (string) $this->price_related_quantity, static::PRICE_PRECISION);
0 ignored issues
show
Bug Best Practice introduced by
The expression return bcdiv($tmp, (stri...tatic::PRICE_PRECISION) could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
168
        //return ($this->price * $multiplier) / $this->price_related_quantity;
169
    }
170
171
    /**
172
     *  Get the price related quantity.
173
     *
174
     * This is the quantity, for which the price is valid.
175
     * The amount is measured in part unit.
176
     *
177
     * @return float the price related quantity
178
     *
179
     * @see Pricedetail::setPriceRelatedQuantity()
180
     */
181
    public function getPriceRelatedQuantity(): float
182
    {
183
        if ($this->orderdetail  && $this->orderdetail->getPart() && !$this->orderdetail->getPart()->useFloatAmount()) {
184
            $tmp = round($this->price_related_quantity);
185
            return $tmp < 1 ? 1 : $tmp;
186
        }
187
        return $this->price_related_quantity;
188
    }
189
190
    /**
191
     *  Get the minimum discount quantity.
192
     *
193
     * "Minimum discount quantity" means the minimum order quantity for which the price
194
     * of this orderdetails is valid.
195
     *
196
     * The amount is measured in part unit.
197
     *
198
     * @return float the minimum discount quantity
199
     *
200
     * @see Pricedetail::setMinDiscountQuantity()
201
     */
202
    public function getMinDiscountQuantity(): float
203
    {
204
        if ($this->orderdetail && $this->orderdetail->getPart() && !$this->orderdetail->getPart()->useFloatAmount()) {
205
            $tmp = round($this->min_discount_quantity);
206
            return $tmp < 1 ? 1 : $tmp;
207
        }
208
209
        return $this->min_discount_quantity;
210
    }
211
212
    /**
213
     * Returns the currency associated with this price information.
214
     * Returns null, if no specific currency is selected and the global base currency should be assumed.
215
     * @return Currency|null
216
     */
217
    public function getCurrency(): ?Currency
218
    {
219
        return $this->currency;
220
    }
221
222
    /********************************************************************************
223
     *
224
     *   Setters
225
     *
226
     *********************************************************************************/
227
228
    /**
229
     * Sets the orderdetail to which this pricedetail belongs to.
230
     * @param Orderdetail $orderdetail
231
     * @return $this
232
     */
233
    public function setOrderdetail(Orderdetail $orderdetail) : self
234
    {
235
        $this->orderdetail = $orderdetail;
236
        return $this;
237
    }
238
239
    /**
240
     * Sets the currency associated with the price informations.
241
     * Set to null, to use the global base currency.
242
     * @param Currency|null $currency
243
     * @return Pricedetail
244
     */
245
    public function setCurrency(?Currency $currency): Pricedetail
246
    {
247
        $this->currency = $currency;
248
        return $this;
249
    }
250
251
    /**
252
     *  Set the price.
253
     *
254
     * @param string $new_price the new price as a float number
255
     *
256
     *      * This is the price for "price_related_quantity" parts!!
257
     *              * Example: if "price_related_quantity" is '10',
258
     *                  you have to set here the price for 10 parts!
259
     *
260
     * @return self
261
     */
262
    public function setPrice(string $new_price): Pricedetail
263
    {
264
        //Assert::natural($new_price, 'The new price must be positive! Got %s!');
265
266
        $this->price = $new_price;
267
268
        return $this;
269
    }
270
271
    /**
272
     *  Set the price related quantity.
273
     *
274
     * This is the quantity, for which the price is valid.
275
     *
276
     * Example:
277
     * If 100pcs costs 20$, you have to set the price to 20$ and the price related
278
     * quantity to 100. The single price (20$/100 = 0.2$) will be calculated automatically.
279
     *
280
     * @param float $new_price_related_quantity the price related quantity
281
     *
282
     * @return self
283
     */
284
    public function setPriceRelatedQuantity(float $new_price_related_quantity): self
285
    {
286
        $this->price_related_quantity = $new_price_related_quantity;
287
288
        return $this;
289
    }
290
291
    /**
292
     *  Set the minimum discount quantity.
293
     *
294
     * "Minimum discount quantity" means the minimum order quantity for which the price
295
     * of this orderdetails is valid. This way, you're able to use different prices
296
     * for different order quantities (quantity discount!).
297
     *
298
     *  Example:
299
     *      - 1-9pcs costs 10$: set price to 10$/pcs and minimum discount quantity to 1
300
     *      - 10-99pcs costs 9$: set price to 9$/pcs and minimum discount quantity to 10
301
     *      - 100pcs or more costs 8$: set price/pcs to 8$ and minimum discount quantity to 100
302
     *
303
     * (Each of this examples would be an own Pricedetails-object.
304
     * So the orderdetails would have three Pricedetails for one supplier.)
305
     *
306
     * @param float $new_min_discount_quantity the minimum discount quantity
307
     *
308
     * @return self
309
     */
310
    public function setMinDiscountQuantity(float $new_min_discount_quantity): self
311
    {
312
        $this->min_discount_quantity = $new_min_discount_quantity;
313
314
        return $this;
315
    }
316
317
    /**
318
     * Returns the ID as an string, defined by the element class.
319
     * This should have a form like P000014, for a part with ID 14.
320
     *
321
     * @return string The ID as a string;
322
     */
323
    public function getIDString(): string
324
    {
325
        return 'PD' . sprintf('%06d', $this->getID());
326
    }
327
}
328