Skip to content

Commit ef6ae76

Browse files
committed
Add negate method to money and calculator
1 parent 35e1b97 commit ef6ae76

File tree

10 files changed

+98
-0
lines changed

10 files changed

+98
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ After all, the config file at `config/money.php` should be modified for your own
104104
- [`floor()`](/docs/04_money/object/floor.md)
105105
- [`ceil()`](/docs/04_money/object/ceil.md)
106106
- [`absolute()`](/docs/04_money/object/absolute.md)
107+
- [`negate()`](/docs/04_money/object/negate.md)
107108
- [`clone()`](/docs/04_money/object/clone.md)
108109
- Logical operations
109110
- [Comparing currencies](/docs/04_money/object/comparing_currencies.md)

docs/04_money/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ There are *static* methods as well as *object* ones.
2727
- [`floor()`](/docs/04_money/object/floor.md)
2828
- [`ceil()`](/docs/04_money/object/ceil.md)
2929
- [`absolute()`](/docs/04_money/object/absolute.md)
30+
- [`negate()`](/docs/04_money/object/negate.md)
3031
- [`clone()`](/docs/04_money/object/clone.md)
3132
- Logical operations
3233
- [Comparing currencies](/docs/04_money/object/comparing_currencies.md)

docs/04_money/object/negate.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# `negate()`
2+
3+
negates the monetary value. `$ 10.25 -> $ -10.25`
4+
5+
## Methods
6+
7+
### `negate()`
8+
9+
**Returns**: `Money`
10+
11+
## Usage
12+
13+
```php
14+
$money = money('102500'); // $ 10.3
15+
$money->negate(); // $ -10.3
16+
```
17+
18+
---
19+
20+
📌 Back to the [contents](/docs/04_money/README.md).

src/Calculators/BcMathCalculator.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ public function absolute(string $amount): string
8282
return ltrim($amount, '-');
8383
}
8484

85+
public function negate(string $amount): string
86+
{
87+
if ($this->isZero($amount)) {
88+
return '0';
89+
}
90+
91+
if (str_starts_with(haystack: $amount, needle: '-')) {
92+
return $this->absolute($amount);
93+
}
94+
95+
return '-' . $amount;
96+
}
97+
8598
private function isZero(string $amount): bool
8699
{
87100
return static::compare($amount, '0') === 0;

src/Calculators/Calculator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ public function ceil(string $amount): string;
1919
public function floor(string $amount): string;
2020

2121
public function absolute(string $amount): string;
22+
23+
public function negate(string $amount): string;
2224
}

src/Calculators/NativeCalculator.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ public function absolute(string $amount): string
6464
return $this->trimZeros($this->format($result));
6565
}
6666

67+
public function negate(string $amount): string
68+
{
69+
$result = ((float) $amount) * -1;
70+
71+
return $this->trimZeros($this->format($result));
72+
}
73+
6774
private function isZero(string $amount): bool
6875
{
6976
return static::compare($amount, '0') === 0;

src/Money.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ public function absolute(): self
138138
return $this;
139139
}
140140

141+
public function negate(): self
142+
{
143+
$this->amount = app(Calculator::class)->negate($this->amount);
144+
145+
return $this;
146+
}
147+
141148
public function isSameCurrency(Money $money): bool
142149
{
143150
return Currencies::same($this->getCurrency(), $money->getCurrency());

src/PHPDocs/MoneyInterface.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ public function ceil(): self;
106106
*/
107107
public function absolute(): self;
108108

109+
/**
110+
* Negates the monetary value <p>
111+
* `$ 10.25 -> $ -10.25` </p>
112+
* @return self
113+
*/
114+
public function negate(): self;
115+
109116
/**
110117
* Checks whether two monetary objects have the same currency
111118
* @param Money $money

tests/Unit/Calculators/CalculatorTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,27 @@ public function providerAbsolute(): array
220220
];
221221
}
222222

223+
/** @dataProvider providerNegate */
224+
public function testNegate(string $amount, string $expected): void
225+
{
226+
$this->runTestsForCalculators(
227+
callback: fn(Calculator $calculator) => $calculator->negate($amount),
228+
expected: $expected,
229+
);
230+
}
231+
232+
public function providerNegate(): array
233+
{
234+
return [
235+
['amount' => '-0', 'expected' => '0'],
236+
['amount' => '0', 'expected' => '0'],
237+
['amount' => '10', 'expected' => '-10'],
238+
['amount' => '-10', 'expected' => '10'],
239+
['amount' => '0.25', 'expected' => '-0.25'],
240+
['amount' => '-0.25', 'expected' => '0.25'],
241+
];
242+
}
243+
223244
private function runTestsForCalculators(Closure $callback, mixed $expected): void
224245
{
225246
foreach (self::CALCULATORS as $name => $class) {

tests/Unit/MoneyTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,25 @@ public function testMoneyAbsoluteAmount(string $negative, string $absolute): voi
262262
$this->assertEquals($absolute, $money->getAmount());
263263
}
264264

265+
/** @dataProvider providerNegate */
266+
public function testNegate(string $amount, string $expected): void
267+
{
268+
$money = money($amount);
269+
270+
$money->negate();
271+
272+
$this->assertMoneyEquals(money($expected), $money);
273+
}
274+
275+
public function providerNegate(): array
276+
{
277+
return [
278+
['amount' => '12345', 'expected' => '-12345'],
279+
['amount' => '-12345', 'expected' => '12345'],
280+
['amount' => '-0', 'expected' => '0'],
281+
];
282+
}
283+
265284
public function testCorrectWayToHandleImmutableMoneyObjects(): void
266285
{
267286
$m1 = money_parse('100');

0 commit comments

Comments
 (0)