Skip to content

Commit

Permalink
Add negate method to money and calculator
Browse files Browse the repository at this point in the history
  • Loading branch information
PostScripton committed Mar 7, 2023
1 parent 35e1b97 commit ef6ae76
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ After all, the config file at `config/money.php` should be modified for your own
- [`floor()`](/docs/04_money/object/floor.md)
- [`ceil()`](/docs/04_money/object/ceil.md)
- [`absolute()`](/docs/04_money/object/absolute.md)
- [`negate()`](/docs/04_money/object/negate.md)
- [`clone()`](/docs/04_money/object/clone.md)
- Logical operations
- [Comparing currencies](/docs/04_money/object/comparing_currencies.md)
Expand Down
1 change: 1 addition & 0 deletions docs/04_money/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ There are *static* methods as well as *object* ones.
- [`floor()`](/docs/04_money/object/floor.md)
- [`ceil()`](/docs/04_money/object/ceil.md)
- [`absolute()`](/docs/04_money/object/absolute.md)
- [`negate()`](/docs/04_money/object/negate.md)
- [`clone()`](/docs/04_money/object/clone.md)
- Logical operations
- [Comparing currencies](/docs/04_money/object/comparing_currencies.md)
Expand Down
20 changes: 20 additions & 0 deletions docs/04_money/object/negate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# `negate()`

negates the monetary value. `$ 10.25 -> $ -10.25`

## Methods

### `negate()`

**Returns**: `Money`

## Usage

```php
$money = money('102500'); // $ 10.3
$money->negate(); // $ -10.3
```

---

📌 Back to the [contents](/docs/04_money/README.md).
13 changes: 13 additions & 0 deletions src/Calculators/BcMathCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ public function absolute(string $amount): string
return ltrim($amount, '-');
}

public function negate(string $amount): string
{
if ($this->isZero($amount)) {
return '0';
}

if (str_starts_with(haystack: $amount, needle: '-')) {
return $this->absolute($amount);
}

return '-' . $amount;
}

private function isZero(string $amount): bool
{
return static::compare($amount, '0') === 0;
Expand Down
2 changes: 2 additions & 0 deletions src/Calculators/Calculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ public function ceil(string $amount): string;
public function floor(string $amount): string;

public function absolute(string $amount): string;

public function negate(string $amount): string;
}
7 changes: 7 additions & 0 deletions src/Calculators/NativeCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ public function absolute(string $amount): string
return $this->trimZeros($this->format($result));
}

public function negate(string $amount): string
{
$result = ((float) $amount) * -1;

return $this->trimZeros($this->format($result));
}

private function isZero(string $amount): bool
{
return static::compare($amount, '0') === 0;
Expand Down
7 changes: 7 additions & 0 deletions src/Money.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ public function absolute(): self
return $this;
}

public function negate(): self
{
$this->amount = app(Calculator::class)->negate($this->amount);

return $this;
}

public function isSameCurrency(Money $money): bool
{
return Currencies::same($this->getCurrency(), $money->getCurrency());
Expand Down
7 changes: 7 additions & 0 deletions src/PHPDocs/MoneyInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ public function ceil(): self;
*/
public function absolute(): self;

/**
* Negates the monetary value <p>
* `$ 10.25 -> $ -10.25` </p>
* @return self
*/
public function negate(): self;

/**
* Checks whether two monetary objects have the same currency
* @param Money $money
Expand Down
21 changes: 21 additions & 0 deletions tests/Unit/Calculators/CalculatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,27 @@ public function providerAbsolute(): array
];
}

/** @dataProvider providerNegate */
public function testNegate(string $amount, string $expected): void
{
$this->runTestsForCalculators(
callback: fn(Calculator $calculator) => $calculator->negate($amount),
expected: $expected,
);
}

public function providerNegate(): array
{
return [
['amount' => '-0', 'expected' => '0'],
['amount' => '0', 'expected' => '0'],
['amount' => '10', 'expected' => '-10'],
['amount' => '-10', 'expected' => '10'],
['amount' => '0.25', 'expected' => '-0.25'],
['amount' => '-0.25', 'expected' => '0.25'],
];
}

private function runTestsForCalculators(Closure $callback, mixed $expected): void
{
foreach (self::CALCULATORS as $name => $class) {
Expand Down
19 changes: 19 additions & 0 deletions tests/Unit/MoneyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,25 @@ public function testMoneyAbsoluteAmount(string $negative, string $absolute): voi
$this->assertEquals($absolute, $money->getAmount());
}

/** @dataProvider providerNegate */
public function testNegate(string $amount, string $expected): void
{
$money = money($amount);

$money->negate();

$this->assertMoneyEquals(money($expected), $money);
}

public function providerNegate(): array
{
return [
['amount' => '12345', 'expected' => '-12345'],
['amount' => '-12345', 'expected' => '12345'],
['amount' => '-0', 'expected' => '0'],
];
}

public function testCorrectWayToHandleImmutableMoneyObjects(): void
{
$m1 = money_parse('100');
Expand Down

0 comments on commit ef6ae76

Please sign in to comment.