Passed
Branch master (350f1b)
by Jan
04:53
created

Pricedetail::getIDString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
/**
3
 * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
4
 *
5
 * Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics)
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as published
9
 * by the Free Software Foundation, either version 3 of the License, or
10
 * (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 Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 */
20
21
declare(strict_types=1);
22
23
/**
24
 * part-db version 0.1
25
 * Copyright (C) 2005 Christoph Lechner
26
 * http://www.cl-projects.de/.
27
 *
28
 * part-db version 0.2+
29
 * Copyright (C) 2009 K. Jacobs and others (see authors.php)
30
 * http://code.google.com/p/part-db/
31
 *
32
 * Part-DB Version 0.4+
33
 * Copyright (C) 2016 - 2019 Jan Böhmer
34
 * https://github.com/jbtronics
35
 *
36
 * This program is free software; you can redistribute it and/or
37
 * modify it under the terms of the GNU General Public License
38
 * as published by the Free Software Foundation; either version 2
39
 * of the License, or (at your option) any later version.
40
 *
41
 * This program is distributed in the hope that it will be useful,
42
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
43
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44
 * GNU General Public License for more details.
45
 *
46
 * You should have received a copy of the GNU General Public License
47
 * along with this program; if not, write to the Free Software
48
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
49
 */
50
51
namespace App\Entity\PriceInformations;
52
53
use App\Entity\Base\AbstractDBElement;
54
use App\Entity\Base\TimestampTrait;
55
use App\Entity\Contracts\TimeStampableInterface;
56
use App\Validator\Constraints\Selectable;
57
use Doctrine\ORM\Mapping as ORM;
58
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
59
use Symfony\Component\Validator\Constraints as Assert;
60
61
/**
62
 * Class Pricedetail.
63
 *
64
 * @ORM\Entity()
65
 * @ORM\Table("`pricedetails`")
66
 * @ORM\HasLifecycleCallbacks()
67
 * @UniqueEntity(fields={"min_discount_quantity", "orderdetail"})
68
 */
69
class Pricedetail extends AbstractDBElement implements TimeStampableInterface
70
{
71
    use TimestampTrait;
72
73
    public const PRICE_PRECISION = 5;
74
75
    /**
76
     * @var string The price related to the detail. (Given in the selected currency)
77
     * @ORM\Column(type="decimal", precision=11, scale=5)
78
     * @Assert\Positive()
79
     */
80
    protected $price = '0.0';
81
82
    /**
83
     * @var ?Currency The currency used for the current price information.
84
     *                If this is null, the global base unit is assumed.
85
     * @ORM\ManyToOne(targetEntity="Currency")
86
     * @ORM\JoinColumn(name="id_currency", referencedColumnName="id", nullable=true)
87
     * @Selectable()
88
     */
89
    protected $currency;
90
91
    /**
92
     * @var float
93
     * @ORM\Column(type="float")
94
     * @Assert\Positive()
95
     */
96
    protected $price_related_quantity = 1.0;
97
98
    /**
99
     * @var float
100
     * @ORM\Column(type="float")
101
     * @Assert\Positive()
102
     */
103
    protected $min_discount_quantity = 1.0;
104
105
    /**
106
     * @var bool
107
     * @ORM\Column(type="boolean")
108
     */
109
    protected $manual_input = true;
110
111
    /**
112
     * @var Orderdetail|null
113
     * @ORM\ManyToOne(targetEntity="Orderdetail", inversedBy="pricedetails")
114
     * @ORM\JoinColumn(name="orderdetails_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
115
     * @Assert\NotNull()
116
     */
117
    protected $orderdetail;
118
119
    public function __construct()
120
    {
121
        bcscale(static::PRICE_PRECISION);
122
    }
123
124
    public function __clone()
125
    {
126
        if ($this->id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->id of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
127
            $this->addedDate = null;
128
        }
129
        parent::__clone();
130
    }
131
132
    /********************************************************************************
133
     *
134
     *   Getters
135
     *
136
     *********************************************************************************/
137
138
    /**
139
     *  Get the orderdetail to which this pricedetail belongs to this pricedetails.
140
     *
141
     * @return Orderdetail|null the orderdetail this price belongs to
142
     */
143
    public function getOrderdetail(): ?Orderdetail
144
    {
145
        return $this->orderdetail;
146
    }
147
148
    /**
149
     * Returns the price associated with this pricedetail.
150
     * It is given in current currency and for the price related quantity.
151
     *
152
     * @return string the price as string, like returned raw from DB
153
     */
154
    public function getPrice(): string
155
    {
156
        return $this->price;
157
    }
158
159
    /**
160
     *  Get the price for a single unit in the currency associated with this price detail.
161
     *
162
     *  @param float|string $multiplier The returned price (float or string) will be multiplied
163
     *                                  with this multiplier.
164
     *
165
     *      You will get the price for $multiplier parts. If you want the price which is stored
166
     *           in the database, you have to pass the "price_related_quantity" count as $multiplier.
167
     * @param float|string $multiplier The returned price (float or string) will be multiplied
168
     *                                 with this multiplier.
169
     *
170
     * @return string|null the price as a bcmath string
171
     */
172
    public function getPricePerUnit($multiplier = 1.0): ?string
173
    {
174
        $multiplier = (string) $multiplier;
175
        $tmp = bcmul($this->price, $multiplier, static::PRICE_PRECISION);
176
177
        return bcdiv($tmp, (string) $this->price_related_quantity, static::PRICE_PRECISION);
178
        //return ($this->price * $multiplier) / $this->price_related_quantity;
179
    }
180
181
    /**
182
     *  Get the price related quantity.
183
     *
184
     * This is the quantity, for which the price is valid.
185
     * The amount is measured in part unit.
186
     *
187
     * @return float the price related quantity
188
     *
189
     * @see Pricedetail::setPriceRelatedQuantity()
190
     */
191
    public function getPriceRelatedQuantity(): float
192
    {
193
        if ($this->orderdetail && $this->orderdetail->getPart() && ! $this->orderdetail->getPart()->useFloatAmount()) {
194
            $tmp = round($this->price_related_quantity);
195
196
            return $tmp < 1 ? 1 : $tmp;
197
        }
198
199
        return $this->price_related_quantity;
200
    }
201
202
    /**
203
     *  Get the minimum discount quantity.
204
     *
205
     * "Minimum discount quantity" means the minimum order quantity for which the price
206
     * of this orderdetails is valid.
207
     *
208
     * The amount is measured in part unit.
209
     *
210
     * @return float the minimum discount quantity
211
     *
212
     * @see Pricedetail::setMinDiscountQuantity()
213
     */
214
    public function getMinDiscountQuantity(): float
215
    {
216
        if ($this->orderdetail && $this->orderdetail->getPart() && ! $this->orderdetail->getPart()->useFloatAmount()) {
217
            $tmp = round($this->min_discount_quantity);
218
219
            return $tmp < 1 ? 1 : $tmp;
220
        }
221
222
        return $this->min_discount_quantity;
223
    }
224
225
    /**
226
     * Returns the currency associated with this price information.
227
     * Returns null, if no specific currency is selected and the global base currency should be assumed.
228
     */
229
    public function getCurrency(): ?Currency
230
    {
231
        return $this->currency;
232
    }
233
234
    /********************************************************************************
235
     *
236
     *   Setters
237
     *
238
     *********************************************************************************/
239
240
    /**
241
     * Sets the orderdetail to which this pricedetail belongs to.
242
     *
243
     * @return $this
244
     */
245
    public function setOrderdetail(Orderdetail $orderdetail): self
246
    {
247
        $this->orderdetail = $orderdetail;
248
249
        return $this;
250
    }
251
252
    /**
253
     * Sets the currency associated with the price informations.
254
     * Set to null, to use the global base currency.
255
     *
256
     * @return Pricedetail
257
     */
258
    public function setCurrency(?Currency $currency): self
259
    {
260
        $this->currency = $currency;
261
262
        return $this;
263
    }
264
265
    /**
266
     *  Set the price.
267
     *
268
     * @param string $new_price the new price as a float number
269
     *
270
     *      * This is the price for "price_related_quantity" parts!!
271
     *              * Example: if "price_related_quantity" is '10',
272
     *                  you have to set here the price for 10 parts!
273
     *
274
     * @return $this
275
     */
276
    public function setPrice(string $new_price): self
277
    {
278
        //Assert::natural($new_price, 'The new price must be positive! Got %s!');
279
280
        /* Just a little hack to ensure that price has 5 digits after decimal point,
281
        so that DB does not detect changes, when something like 0.4 is passed
282
        Third parameter must have the scale value of decimal column. */
283
        $this->price = bcmul($new_price, '1.0', static::PRICE_PRECISION);
284
285
        return $this;
286
    }
287
288
    /**
289
     *  Set the price related quantity.
290
     *
291
     * This is the quantity, for which the price is valid.
292
     *
293
     * Example:
294
     * If 100pcs costs 20$, you have to set the price to 20$ and the price related
295
     * quantity to 100. The single price (20$/100 = 0.2$) will be calculated automatically.
296
     *
297
     * @param float $new_price_related_quantity the price related quantity
298
     *
299
     * @return $this
300
     */
301
    public function setPriceRelatedQuantity(float $new_price_related_quantity): self
302
    {
303
        $this->price_related_quantity = $new_price_related_quantity;
304
305
        return $this;
306
    }
307
308
    /**
309
     *  Set the minimum discount quantity.
310
     *
311
     * "Minimum discount quantity" means the minimum order quantity for which the price
312
     * of this orderdetails is valid. This way, you're able to use different prices
313
     * for different order quantities (quantity discount!).
314
     *
315
     *  Example:
316
     *      - 1-9pcs costs 10$: set price to 10$/pcs and minimum discount quantity to 1
317
     *      - 10-99pcs costs 9$: set price to 9$/pcs and minimum discount quantity to 10
318
     *      - 100pcs or more costs 8$: set price/pcs to 8$ and minimum discount quantity to 100
319
     *
320
     * (Each of this examples would be an own Pricedetails-object.
321
     * So the orderdetails would have three Pricedetails for one supplier.)
322
     *
323
     * @param float $new_min_discount_quantity the minimum discount quantity
324
     *
325
     * @return $this
326
     */
327
    public function setMinDiscountQuantity(float $new_min_discount_quantity): self
328
    {
329
        $this->min_discount_quantity = $new_min_discount_quantity;
330
331
        return $this;
332
    }
333
}
334