Skip to content

Commit 8d952ec

Browse files
authored
✨ Adds functions on prices (#48)
* ✨ Adds functions on prices * Adds percentages functions * rounding prices to cent precision * add precision to Price
1 parent f1c9693 commit 8d952ec

File tree

2 files changed

+106
-4
lines changed

2 files changed

+106
-4
lines changed

component/Money/Price.php

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,66 @@ class Price
99
public function __construct(
1010
public readonly float $amount,
1111
public readonly ?Currency $currency,
12-
public readonly ?string $unit
12+
public readonly ?string $unit,
13+
public readonly ?int $precision = 2
1314
) {
1415
}
1516

17+
public function add(self $price): self
18+
{
19+
if ($this->currency !== $price->currency) {
20+
throw new \InvalidArgumentException('Cannot add prices with different currencies.');
21+
}
22+
23+
if ($this->unit !== $price->unit) {
24+
throw new \InvalidArgumentException('Cannot add prices with different units.');
25+
}
26+
27+
return new self(
28+
amount: round($this->amount + $price->amount, $this->precision),
29+
currency: $this->currency,
30+
unit: $this->unit,
31+
precision: $this->precision
32+
);
33+
}
34+
35+
public function subtract(self $price): self
36+
{
37+
if ($this->currency !== $price->currency) {
38+
throw new \InvalidArgumentException('Cannot subtract prices with different currencies.');
39+
}
40+
41+
if ($this->unit !== $price->unit) {
42+
throw new \InvalidArgumentException('Cannot subtract prices with different units.');
43+
}
44+
45+
return new self(
46+
amount: round($this->amount - $price->amount, $this->precision),
47+
currency: $this->currency,
48+
unit: $this->unit,
49+
precision: $this->precision
50+
);
51+
}
52+
53+
public function multiply(float $factor): self
54+
{
55+
return new self(
56+
amount: round($this->amount * $factor, $this->precision),
57+
currency: $this->currency,
58+
unit: $this->unit,
59+
precision: $this->precision
60+
);
61+
}
62+
63+
public function applyPercentage(float $percentage): self
64+
{
65+
return $this->multiply(1 + $percentage / 100);
66+
}
67+
1668
public function getFormatted(
1769
bool $espaceInsecable = true
1870
): string {
19-
$price = number_format($this->amount, 2, ',', ' ');
71+
$price = number_format($this->amount, $this->precision, ',', ' ');
2072

2173
if ($this->currency) {
2274
$price .= ' ' . $this->currency->getLabel();

test/Money/PriceTest.php

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public function testInterface(): void
1313
{
1414
$price = new Price(1234.56, Currency::EUR, 'kg');
1515

16-
$this->assertEquals('1 234,56 €/kg', (string)$price);
16+
$this->assertEquals('1 234,56 €/kg', (string) $price);
1717

1818
$this->assertIsFloat($price->amount);
1919
$this->assertEquals(1234.56, $price->amount);
@@ -22,6 +22,56 @@ public function testInterface(): void
2222
$this->assertEquals(Currency::EUR, $price->currency);
2323

2424
$this->assertIsString($price->unit);
25-
$this->assertEquals('kg', (string)$price->unit);
25+
$this->assertEquals('kg', (string) $price->unit);
26+
}
27+
28+
public function testAdd(): void
29+
{
30+
$price1 = new Price(100, Currency::EUR, 'Mwh');
31+
$price2 = new Price(50, Currency::EUR, 'Mwh');
32+
33+
$result = $price1->add($price2);
34+
35+
$this->assertEquals(150, $result->amount);
36+
$this->assertEquals(Currency::EUR, $result->currency);
37+
$this->assertEquals('Mwh', $result->unit);
38+
}
39+
40+
public function testsubtract(): void
41+
{
42+
$price1 = new Price(100, Currency::EUR, 'Mwh');
43+
$price2 = new Price(50, Currency::EUR, 'Mwh');
44+
45+
$result = $price1->subtract($price2);
46+
47+
$this->assertEquals(50, $result->amount);
48+
$this->assertEquals(Currency::EUR, $result->currency);
49+
$this->assertEquals('Mwh', $result->unit);
50+
}
51+
52+
public function testMultiply(): void
53+
{
54+
$price = new Price(100, Currency::EUR, 'Mwh');
55+
56+
$result = $price->multiply(2);
57+
58+
$this->assertEquals(200, $result->amount);
59+
$this->assertEquals(Currency::EUR, $result->currency);
60+
$this->assertEquals('Mwh', $result->unit);
61+
}
62+
63+
public function testApplyPercentage(): void
64+
{
65+
$price = new Price(100, Currency::EUR, 'Mwh');
66+
67+
$result = $price->applyPercentage(10);
68+
$this->assertEquals(110.00, $result->amount);
69+
$this->assertEquals(Currency::EUR, $result->currency);
70+
$this->assertEquals('Mwh', $result->unit);
71+
72+
$result = $price->applyPercentage(-10);
73+
$this->assertEquals(90.00, $result->amount);
74+
$this->assertEquals(Currency::EUR, $result->currency);
75+
$this->assertEquals('Mwh', $result->unit);
2676
}
2777
}

0 commit comments

Comments
 (0)