Passed
Push — master ( fd93c6...4910da )
by Tomáš
04:38
created

PriceCalculator::getVatRate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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