Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
23 changes: 3 additions & 20 deletions src/product/Application/BillingRegistryService.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,15 @@ public function getRepresentationsByType(string $representationClass): array
return $representations;
}

public function getTariffDefinitionByName(string $tariffName): ?TariffTypeDefinitionInterface
public function getTariffTypeDefinitionByName(string $tariffName): TariffTypeDefinitionInterface
{
foreach ($this->registry->getTariffTypeDefinitions() as $tariffTypeDefinition) {
if ($tariffName === $tariffTypeDefinition->tariffType()->name) {
if ($tariffTypeDefinition->tariffType()->equalsName($tariffName)) {
return $tariffTypeDefinition;
}
}
return null;
}

public function hasBehaviour(TariffTypeDefinitionInterface $tariffTypeDefinition, string $behaviorClassWrapper): bool
{
return $tariffTypeDefinition->hasBehavior($behaviorClassWrapper);
throw new TariffTypeDefinitionNotFoundException('Tariff type definition was not found');
}

public function createQuantityFormatter(string $type, FractionQuantityData $data): QuantityFormatterInterface {
Expand Down Expand Up @@ -157,19 +153,6 @@ public function getAggregate(string $type): AggregateInterface
throw new AggregateNotFoundException('Aggregate was not found');
}

public function findTariffTypeDefinitionByBehavior(BehaviorInterface $behavior): TariffTypeDefinitionInterface
{
$tariffType = $behavior->getTariffType();

foreach ($this->registry->getTariffTypeDefinitions() as $tariffTypeDefinition) {
if ($tariffTypeDefinition->belongToTariffType($tariffType)) {
return $tariffTypeDefinition;
}
}

throw new TariffTypeDefinitionNotFoundException('Tariff type definition was not found');
}

public function findPriceTypeDefinitionsByBehavior(string $behaviorClassWrapper): \Generator
{
foreach ($this->registry->priceTypes() as $priceTypeDefinition) {
Expand Down
9 changes: 1 addition & 8 deletions src/product/Application/BillingRegistryServiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@

namespace hiqdev\php\billing\product\Application;

use Generator;
use hiqdev\php\billing\product\AggregateInterface;
use hiqdev\php\billing\product\behavior\BehaviorInterface;
use hiqdev\php\billing\product\behavior\BehaviorNotFoundException;
use hiqdev\php\billing\product\behavior\InvalidBehaviorException;
use hiqdev\php\billing\product\invoice\RepresentationInterface;
use hiqdev\php\billing\product\price\PriceTypeDefinitionInterface;
use hiqdev\php\billing\product\quantity\FractionQuantityData;
use hiqdev\php\billing\product\quantity\QuantityFormatterInterface;
use hiqdev\php\billing\product\TariffTypeDefinitionInterface;

interface BillingRegistryServiceInterface extends BillingRegistryTariffServiseInterface, BillingRegistryBehaviorServiceInterface
interface BillingRegistryServiceInterface extends BillingRegistryTariffServiceInterface, BillingRegistryBehaviorServiceInterface
{
/**
* @param string $representationClass
Expand All @@ -24,5 +18,4 @@ public function getRepresentationsByType(string $representationClass): array;
public function createQuantityFormatter(string $type, FractionQuantityData $data): QuantityFormatterInterface;

public function getAggregate(string $type): AggregateInterface;

}
16 changes: 16 additions & 0 deletions src/product/Application/BillingRegistryTariffServiceInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php declare(strict_types=1);

namespace hiqdev\php\billing\product\Application;

use hiqdev\php\billing\product\Exception\TariffTypeDefinitionNotFoundException;
use hiqdev\php\billing\product\TariffTypeDefinitionInterface;

interface BillingRegistryTariffServiceInterface
{
/**
* @param string $tariffName
* @return TariffTypeDefinitionInterface
* @throws TariffTypeDefinitionNotFoundException
*/
public function getTariffTypeDefinitionByName(string $tariffName): TariffTypeDefinitionInterface;
}
18 changes: 0 additions & 18 deletions src/product/Application/BillingRegistryTariffServiseInterface.php

This file was deleted.

39 changes: 39 additions & 0 deletions src/product/invoice/Representation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php declare(strict_types=1);

namespace hiqdev\php\billing\product\invoice;

use hiqdev\php\billing\type\TypeInterface;

/**
* This class is made abstract intentionally.
* Because you can attach multiple representations, and thus you should distinguish them somehow.
* So, please implement you own representation.
*/
abstract class Representation implements RepresentationInterface
{
private TypeInterface $type;

public function __construct(private readonly string $sql)
{
if (trim($this->sql) === '') {
throw new InvalidRepresentationException('Representation SQL cannot be empty.');
}
}

public function getSql(): string
{
return $this->sql;
}

public function setType(TypeInterface $type): RepresentationInterface
{
$this->type = $type;

return $this;
}

public function getType(): TypeInterface
{
return $this->type;
}
}
7 changes: 3 additions & 4 deletions tests/unit/product/Application/BillingRegistryServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace hiqdev\php\billing\tests\unit\product\Application;

use hiqdev\billing\registry\invoice\InvoiceRepresentation;
use hiqdev\billing\registry\invoice\PaymentRequestRepresentation;
use hiqdev\php\billing\product\Application\BillingRegistryService;
use hiqdev\php\billing\product\behavior\BehaviorNotFoundException;
use hiqdev\php\billing\product\BillingRegistry;
Expand All @@ -15,6 +13,7 @@
use hiqdev\php\billing\tests\unit\product\behavior\TestBehavior;
use hiqdev\php\billing\tests\unit\product\Domain\Model\DummyTariffType;
use hiqdev\php\billing\tests\unit\product\Domain\Model\FakeTariffType;
use hiqdev\php\billing\tests\unit\product\invoice\TestRepresentation;
use hiqdev\php\billing\type\Type;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -51,8 +50,8 @@ public function testGetRepresentationsByInterfaceReturnsAllRepresentations(): vo
->withPrices()
->priceType(Type::anyId('dummy'))
->documentRepresentation()
->attach(new InvoiceRepresentation("Invoice"))
->attach(new PaymentRequestRepresentation("Payment Request"))
->attach(new TestRepresentation("Invoice"))
->attach(new TestRepresentation("Payment Request"))
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.

💡 Verification agent

🧩 Analysis chain

Fix the duplicate representation issue causing test failure.

The pipeline failure indicates a DuplicateRepresentationException with "TestRepresentation:dummy", but the test creates instances with different parameters ("Invoice" and "Payment Request"). This suggests the representation identification mechanism doesn't use the constructor parameter as expected.

Please investigate how representations are identified internally. Run this script to examine the TestRepresentation implementation and related identification logic:


🏁 Script executed:

#!/bin/bash
# Description: Examine TestRepresentation implementation and representation identification mechanism

# Check TestRepresentation implementation
echo "=== TestRepresentation class implementation ==="
cat tests/unit/product/invoice/TestRepresentation.php

# Look for any identification or registry mechanisms
echo -e "\n=== Searching for representation identification logic ==="
rg -A 10 -B 5 "attach.*Representation" src/

# Check for any default identification in parent classes
echo -e "\n=== Searching for representation identification patterns ==="
rg -A 5 -B 5 "representation.*dummy|dummy.*representation" src/ tests/

Length of output: 1975


🏁 Script executed:

#!/bin/bash
# Inspect core representation logic and uniqueness enforcement

echo "=== Representation implementation ==="
rg -n "class Representation" -A200 src/product/invoice/Representation.php

echo -e "\n=== UniquenessGuard implementation ==="
rg -n "class UniquenessGuard" -A200 src/product/invoice/UniquenessGuard.php

Length of output: 1116


🏁 Script executed:

#!/bin/bash
# 1. Find where uniqueness is enforced in the codebase
echo "=== ensureUnique occurrences ==="
rg -n "ensureUnique" -A5 src

# 2. Locate the DuplicateRepresentationException class
echo -e "\n=== DuplicateRepresentationException declaration ==="
rg -n "class DuplicateRepresentationException" -A20 src

# 3. List all guard-like classes to find UniquenessGuard equivalent
echo -e "\n=== Guard-like classes in src ==="
rg -n "class .*Guard" -n src

# 4. Inspect the test around the failing lines
echo -e "\n=== BillingRegistryServiceTest (first 200 lines) ==="
sed -n '1,200p' tests/unit/product/Application/BillingRegistryServiceTest.php

Length of output: 8781


Include SQL in representation key to avoid false duplicates

The uniqueness guard currently generates keys using only the representation class and type, so both new TestRepresentation("Invoice") and new TestRepresentation("Payment Request") yield the same "TestRepresentation:dummy" key. To fix this, extend the key to include the SQL string:

• File needing update:

  • src/product/invoice/RepresentationUniquenessGuard.php

• Proposed diff:

--- a/src/product/invoice/RepresentationUniquenessGuard.php
+++ b/src/product/invoice/RepresentationUniquenessGuard.php
@@ -23,7 +23,12 @@ class RepresentationUniquenessGuard
     private function generateKey(RepresentationInterface $representation): string
     {
-        return \get_class($representation) . ':' . $representation->getType()->getName();
+        // include SQL so different queries aren’t treated as duplicates
+        return \sprintf(
+            '%s:%s:%s',
+            \get_class($representation),
+            $representation->getType()->getName(),
+            $representation->getSql()
+        );
     }
 }

This change ensures each representation’s SQL is factored into uniqueness, resolving the DuplicateRepresentationException in tests.

🧰 Tools
🪛 GitHub Actions: phpunit-tests

[error] 54-54: hiqdev\php\billing\product\invoice\DuplicateRepresentationException: Duplicate 'TestRepresentation:dummy' representation causing test failure in testGetRepresentationsByInterfaceReturnsAllRepresentations.

🤖 Prompt for AI Agents
In src/product/invoice/RepresentationUniquenessGuard.php around the logic
generating uniqueness keys, the current key only includes the representation
class and type, causing different TestRepresentation instances with distinct SQL
strings to be seen as duplicates. Modify the key generation method to append the
SQL string from each representation to the uniqueness key, ensuring that
representations with different SQL are uniquely identified and preventing
DuplicateRepresentationException in tests.

->end()
->end()
->end();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,8 @@ public function testGetTariffDefinitionByName(): void

$this->registry->addTariffType($tariffTypeDefinition);

$tariff = $this->registryService->getTariffDefinitionByName('dummy');
$tariff = $this->registryService->getTariffTypeDefinitionByName('dummy');

$this->assertSame($tariffType->name(), $tariff->tariffType()->name());
}

public function testCheckBehaviorInTariff(): void
{
$tariffType = new DummyTariffType();
$tariffTypeDefinition = new TariffTypeDefinition($tariffType);
$dummyBehavior = new TestBehavior('dummy');
$tariffTypeDefinition
->withBehaviors()
->attach($dummyBehavior);

$this->registry->addTariffType($tariffTypeDefinition);

$tariff = $this->registryService->getTariffDefinitionByName('dummy');
$this->assertTrue($this->registryService->hasBehaviour($tariff, TestBehavior::class));
}

}
9 changes: 9 additions & 0 deletions tests/unit/product/invoice/TestRepresentation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php declare(strict_types=1);

namespace hiqdev\php\billing\tests\unit\product\invoice;

use hiqdev\php\billing\product\invoice\Representation;

class TestRepresentation extends Representation
{
}
Loading