Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 26 additions & 16 deletions src/price/Sums.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,56 @@
final readonly class Sums implements \JsonSerializable
{
/**
* @param int[]|null $values quantity => total sum for the quantity
* Quantity of what?
* Sum of what?
* If you know answers please write in the comment
* @param array<int, float|int>|null $quantityToSumMap An associative array where:
* - The key represents the **quantity** of the action being charged for
* (e.g., the number of years for an SSL certificate).
* - The value represents the **total sum** or **price** for the given quantity.
*
* Example (If used to denote bulk prices):
* E.g. when you buy an SSL certificate for 1 year – it costs 10$
* But for 2 years you pay 15$.
*
* It will be is stored as
*
* [1 => 10, 2 => 15]
*/
public function __construct(private ?array $values)
public function __construct(private ?array $quantityToSumMap)
{
if (!empty($this->values)) {
$this->validate($this->values);
}
$this->validateSums($this->quantityToSumMap);
}

private function validate(array $sums): void
private function validateSums(?array $sums): void
{
if ($sums) {
if (!empty($sums)) {
foreach ($sums as $value) {
if (!is_numeric($value)) {
throw new PriceInvalidArgumentException('Invalid value for sums parameter');
throw new PriceInvalidArgumentException('All sums must be numeric values.');
}
}
}
Comment on lines +26 to 34
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Validate that the keys are integers in validateSums method

Currently, the validateSums method checks that all sums (values) are numeric but does not verify that the keys (quantities) are integers. Since $quantityToSumMap is defined as array<int, float|int>|null, it's important to ensure that all keys are integers.

Consider adding a check to validate that the keys are integers. Here's a possible modification:

 private function validateSums(?array $sums): void
 {
     if (!empty($sums)) {
         foreach ($sums as $key => $value) {
+            if (!is_int($key)) {
+                throw new PriceInvalidArgumentException('All quantities (keys) must be integers.');
+            }
             if (!is_numeric($value)) {
                 throw new PriceInvalidArgumentException('All sums must be numeric values.');
             }
         }
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private function validateSums(?array $sums): void
{
if ($sums) {
if (!empty($sums)) {
foreach ($sums as $value) {
if (!is_numeric($value)) {
throw new PriceInvalidArgumentException('Invalid value for sums parameter');
throw new PriceInvalidArgumentException('All sums must be numeric values.');
}
}
}
private function validateSums(?array $sums): void
{
if (!empty($sums)) {
foreach ($sums as $key => $value) {
if (!is_int($key)) {
throw new PriceInvalidArgumentException('All quantities (keys) must be integers.');
}
if (!is_numeric($value)) {
throw new PriceInvalidArgumentException('All sums must be numeric values.');
}
}
}

}

public function values(): ?array
{
return $this->values;
return $this->quantityToSumMap;
}

public function getSum(int $quantity)
{
return $this->values[$quantity] ?? null;
return $this->quantityToSumMap[$quantity] ?? null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add return type hint to getSum method

The getSum method lacks a return type declaration. To promote type safety and maintain consistency with strict typing, consider specifying the return type as float|int|null.

Apply this diff to add the return type hint:

-public function getSum(int $quantity)
+public function getSum(int $quantity): float|int|null

Committable suggestion was skipped due to low confidence.

}

public function getMinSum(): int|string
public function getMinSum()
{
return min($this->values);
if (empty($this->quantityToSumMap)) {
return null;
}

return min($this->quantityToSumMap);
Comment on lines +47 to +53
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add return type hint to getMinSum method

The getMinSum method lacks a return type declaration. To enhance type safety and consistency, consider specifying the return type as float|int|null.

Apply this diff to add the return type hint:

-public function getMinSum()
+public function getMinSum(): float|int|null
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public function getMinSum()
{
return min($this->values);
if (empty($this->quantityToSumMap)) {
return null;
}
return min($this->quantityToSumMap);
public function getMinSum(): float|int|null
{
if (empty($this->quantityToSumMap)) {
return null;
}
return min($this->quantityToSumMap);

}

public function jsonSerialize(): ?array
{
return $this->values;
return $this->quantityToSumMap;
}
}
96 changes: 96 additions & 0 deletions tests/unit/price/SumsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php declare(strict_types=1);

namespace hiqdev\php\billing\tests\unit\price;

use hiqdev\php\billing\price\PriceInvalidArgumentException;
use hiqdev\php\billing\price\Sums;
use JsonSerializable;
use PHPUnit\Framework\TestCase;

class SumsTest extends TestCase
{
public function testConstructorWithValidData(): void
{
$validSums = [1 => 10.5, 2 => 15.0, 3 => 20];

$sums = new Sums($validSums);

$this->assertSame($validSums, $sums->values());
}

public function testConstructorWithInvalidDataThrowsException(): void
{
$this->expectException(PriceInvalidArgumentException::class);
$this->expectExceptionMessage('All sums must be numeric values.');

$invalidSums = [1 => 10, 2 => 'abc'];

new Sums($invalidSums);
}

public function testGetSum(): void
{
$sums = new Sums([1 => 10, 2 => 15, 3 => 20]);

$this->assertSame(10, $sums->getSum(1));
$this->assertSame(15, $sums->getSum(2));
$this->assertNull($sums->getSum(4)); // Not found
}

/**
* @dataProvider minSumDataProvider
*/
public function testGetMinSum($input, $expected): void
{
$sums = new Sums($input);

$this->assertSame($expected, $sums->getMinSum());
}

public function minSumDataProvider(): array
{
return [
// Single element case
'single positive integer' => [[1 => 10], 10],
'single negative integer' => [[1 => -10], -10],
'single decimal' => [[1 => 5.5], 5.5],

// Multiple elements case
'multiple positive integers' => [[1 => 10, 2 => 20, 3 => 5], 5],
'multiple with negative integers' => [[1 => -10, 2 => 20, 3 => 0], -10],
'multiple decimals' => [[1 => 10.5, 2 => 20.7, 3 => 5.5], 5.5],
'mixed integers and decimals' => [[1 => 10, 2 => 20.7, 3 => 5], 5],

// Edge cases
'positive and negative decimals' => [[1 => -1.5, 2 => 1.5], -1.5],
'zero and positive integers' => [[1 => 0, 2 => 5], 0],
'zero and negative integers' => [[1 => 0, 2 => -5], -5],
];
}

public function testJsonSerializableBehavior(): void
{
$sums = new Sums([1 => 10, 2 => 15, 3 => 20]);

$this->assertInstanceOf(JsonSerializable::class, $sums);

$expectedJson = json_encode([1 => 10, 2 => 15, 3 => 20]);
$this->assertSame($expectedJson, json_encode($sums));
}

public function testSumsWithNullInput(): void
{
$sums = new Sums(null);

$this->assertNull($sums->values());
$this->assertNull($sums->getSum(1));
}

public function testSumsWithEmptyArray(): void
{
$sums = new Sums([]);

$this->assertSame([], $sums->values());
$this->assertNull($sums->getSum(1));
}
}