Completed
Push — master ( 6d1c9a...5c8380 )
by Tomáš
01:28
created

src/PriceCalculator.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php declare(strict_types=1);
2
3
namespace Sunfox\PriceCalculator;
4
5
use Nette;
6
7
8
/**
9
 * @property float $basePrice
10
 * @property IDiscount $discount
11
 * @property float $price
12
 * @property float $vatRate
13
 * @property float $priceVat
14
 * @property float $decimalPoints
15
 */
16
class PriceCalculator implements IPriceCalculator
17
{
18
	use Nette\SmartObject;
19
20
	/** @var float */
21
	protected $basePrice = 0.0;
22
23
	/** @var IDiscount|NULL */
24
	protected $discount = NULL;
25
26
	/** @var float */
27
	protected $price = 0.0;
28
29
	/** @var float */
30
	protected $vatRate = 0.0;
31
32
	/** @var float */
33
	protected $priceVat = 0.0;
34
35
	/** @var int */
36
	protected $decimalPoints = 2;
37
38
	/** @var string */
39
	protected $calculateFrom = self::FROM_BASEPRICE;
40
41
42
	/**
43
	 * @param int|float VAT rate
44
	 * @param int|float Price without VAT and discount
45
	 * @param int|float Discount without VAT
46
	 */
47
	public function __construct($vatRate = 0.0, $basePrice = 0.0, IDiscount $discount = NULL)
48
	{
49
		$this->setVatRate($vatRate);
50
		$this->setBasePrice($basePrice);
51
		$this->setDiscount($discount);
52
	}
53
54
	/**
55
	 * Get price without VAT and discount.
56
	 *
57
	 * @return float
58
	 */
59
	public function getBasePrice()
60
	{
61
		return $this->basePrice;
62
	}
63
64
	/**
65
	 * Set price without VAT and discount.
66
	 *
67
	 * @param int|float
68
	 * @return IPriceCalculator
69
	 */
70
	public function setBasePrice($value)
71
	{
72
		$this->basePrice = (float) $value;
73
		$this->calculateFrom = self::FROM_BASEPRICE;
74
		return $this;
75
	}
76
77
	/**
78
	 * Get discount in percent without VAT.
79
	 *
80
	 * @return IDiscount
81
	 */
82
	public function getDiscount()
83
	{
84
		return $this->discount;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->discount; of type Sunfox\PriceCalculator\IDiscount|null adds the type Sunfox\PriceCalculator\IDiscount to the return on line 84 which is incompatible with the return type declared by the interface Sunfox\PriceCalculator\I...Calculator::getDiscount of type double.
Loading history...
85
	}
86
87
	/**
88
	 * Set discount instance.
89
	 *
90
	 * @param IDiscount
91
	 * @return IPriceCalculator
92
	 */
93
	public function setDiscount(IDiscount $discount = NULL)
94
	{
95
		$this->discount = $discount;
96
		return $this;
97
	}
98
99
	/**
100
	 * Set amount discount.
101
	 *
102
	 * @param int|float
103
	 * @return IPriceCalculator
104
	 */
105
	public function setAmountDiscount($value)
106
	{
107
		$this->discount = new Discount\AmountDiscount($value);
108
		return $this;
109
	}
110
111
	/**
112
	 * Set percent discount.
113
	 *
114
	 * @param int|float
115
	 * @return IPriceCalculator
116
	 */
117
	public function setPercentDiscount($value)
118
	{
119
		$this->discount = new Discount\PercentDiscount($value);
120
		return $this;
121
	}
122
123
	/**
124
	 * Get price after discount without VAT.
125
	 *
126
	 * @return float
127
	 */
128
	public function getPrice()
129
	{
130
		return $this->price;
131
	}
132
133
	/**
134
	 * Set price after discount without VAT.
135
	 *
136
	 * @param int|float
137
	 * @return IPriceCalculator
138
	 */
139
	public function setPrice($value)
140
	{
141
		$this->price = (float) $value;
142
		$this->calculateFrom = self::FROM_PRICE;
143
		return $this;
144
	}
145
146
	/**
147
	 * Get VAT rate in percent.
148
	 *
149
	 * @return float
150
	 */
151
	public function getVatRate()
152
	{
153
		return $this->vatRate;
154
	}
155
156
	/**
157
	 * Set VAT rate in percent.
158
	 *
159
	 * @param int|float
160
	 * @return IPriceCalculator
161
	 */
162
	public function setVatRate($value)
163
	{
164
		$this->vatRate = (float) $value;
165
		return $this;
166
	}
167
168
	/**
169
	 * Get price after discount with VAT.
170
	 *
171
	 * @return float
172
	 */
173
	public function getPriceVat()
174
	{
175
		return $this->priceVat;
176
	}
177
178
	/**
179
	 * Set price after discount with VAT.
180
	 *
181
	 * @param int|float
182
	 * @return IPriceCalculator
183
	 */
184
	public function setPriceVat($value)
185
	{
186
		$this->priceVat = (float) $value;
187
		$this->calculateFrom = self::FROM_PRICEVAT;
188
		return $this;
189
	}
190
191
	/**
192
	 * Get decimal point for rounding.
193
	 *
194
	 * @return float
195
	 */
196
	public function getDecimalPoints()
197
	{
198
		return $this->decimalPoints;
199
	}
200
201
	/**
202
	 * Set decimal point for rounding.
203
	 *
204
	 * @param int
205
	 * @return IPriceCalculator
206
	 */
207
	public function setDecimalPoints($value)
208
	{
209
		$this->decimalPoints = (int) $value;
210
		return $this;
211
	}
212
213
	/**
214
	 * Calculate prices and return result.
215
	 *
216
	 * @return PriceCalculatorResult
217
	 */
218
	public function calculate()
219
	{
220
		$basePrice = round($this->basePrice, $this->decimalPoints);
221
		$price = round($this->price, $this->decimalPoints);
222
		$priceVat = round($this->priceVat, $this->decimalPoints);
223
224
		if ($this->calculateFrom === self::FROM_BASEPRICE) {
225
			$price = round($this->discount ? $this->discount->addDiscount($basePrice) : $basePrice, $this->decimalPoints);
226
			$priceVat = round($price * ($this->vatRate / 100 + 1), $this->decimalPoints);
227
		} elseif ($this->calculateFrom === self::FROM_PRICE) {
228
			$basePrice = $this->discount ? round($this->discount->removeDiscount($price), $this->decimalPoints) : $price;
229
			$priceVat = round($price * ($this->vatRate / 100 + 1), $this->decimalPoints);
230
		} elseif ($this->calculateFrom === self::FROM_PRICEVAT) {
231
			$price = round($priceVat / ($this->vatRate / 100 + 1), $this->decimalPoints);
232
			$basePrice = $this->discount ? round($this->discount->removeDiscount($price), $this->decimalPoints) : $price;
233
		}
234
235
		$vat = $priceVat - $price;
236
237
		return new PriceCalculatorResult(
238
			$this, $basePrice, $this->discount, $price, $this->vatRate, $vat, $priceVat
239
		);
240
	}
241
242
}
243