-
Notifications
You must be signed in to change notification settings - Fork 11
HP-2419 extended functional of BillingRegistry for easier use #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
HP-2419 extended functional of BillingRegistry for easier use #99
Conversation
WalkthroughThis change refactors the billing product registry by removing behavior, representation, quantity formatter, and aggregate logic from Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant BillingRegistryService
participant BillingRegistry
participant PriceTypeDefinition
Client->>BillingRegistryService: getBehavior(type, behaviorClass)
BillingRegistryService->>BillingRegistry: priceTypes()
loop for each PriceTypeDefinition
BillingRegistryService->>PriceTypeDefinition: getBehaviors()
alt behavior found
BillingRegistryService-->>Client: return Behavior
end
end
BillingRegistryService-->>Client: throw BehaviorNotFoundException (if not found)
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (5)
src/product/BillingRegistryService.php (1)
113-133
: Fix typo in PHPDoc annotation.There's a typo in the PHPDoc annotation for the
getBehaviors
method.- * @inerhitDoc + * @inheritDocOtherwise, the method implementation is correct, efficiently yielding behaviors from both tariff type definitions and price types that match the specified class.
src/product/BillingRegistry.php (4)
19-25
: Constructor OK but missing explicit import for the serviceThe delegation pattern looks good; however, to improve readability and IDE support consider adding an explicit
use
statement forBillingRegistryService
above rather than relying on the same-namespace resolution.+use hiqdev\php\billing\product\BillingRegistryService;
33-36
: Add PHPDoc for new public getterPublic API should be documented for consumers. A short
@return TariffTypeDefinitionInterface[]
doc-block will help./** * @return TariffTypeDefinitionInterface[] */ public function getTariffTypeDefinitions(): array
64-66
: Typo in annotation tag
@inerhitDoc
→@inheritDoc
- * @inerhitDoc + * @inheritDoc
77-84
: Consistent explicit imports for domain interfaces
TariffTypeDefinitionInterface
(and the price-related interfaces) are referenced multiple times but not imported.
While same-namespace resolution works, adding explicituse
statements increases clarity and avoids errors when classes move.Consider:
+use hiqdev\php\billing\product\TariffTypeDefinitionInterface;
(and the corresponding price interface if it lives in another sub-namespace).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
src/product/BillingRegistry.php
(2 hunks)src/product/BillingRegistryInterface.php
(2 hunks)src/product/BillingRegistryService.php
(1 hunks)src/product/Domain/Model/TariffTypeInterface.php
(1 hunks)src/product/Domain/Model/Unit/UnitInterface.php
(1 hunks)src/product/TariffTypeDefinition.php
(2 hunks)src/product/TariffTypeDefinitionInterface.php
(1 hunks)src/product/behavior/BehaviorCollectionInterface.php
(1 hunks)src/product/invoice/RepresentationCollection.php
(2 hunks)src/product/price/PriceTypeDefinition.php
(2 hunks)src/product/price/PriceTypeDefinitionCollection.php
(1 hunks)src/product/price/PriceTypeDefinitionCollectionInterface.php
(1 hunks)src/product/price/PriceTypeDefinitionInterface.php
(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (10)
src/product/price/PriceTypeDefinitionCollection.php (3)
src/product/price/PriceTypeDefinitionCollectionInterface.php (1)
getTariffTypeDefinition
(32-32)src/product/price/PriceTypeDefinition.php (1)
getTariffTypeDefinition
(203-206)src/product/price/PriceTypeDefinitionInterface.php (1)
getTariffTypeDefinition
(56-56)
src/product/Domain/Model/Unit/UnitInterface.php (1)
src/product/Domain/Model/TariffTypeInterface.php (1)
name
(7-7)
src/product/price/PriceTypeDefinitionInterface.php (3)
src/product/price/PriceTypeDefinitionCollectionInterface.php (1)
getTariffTypeDefinition
(32-32)src/product/price/PriceTypeDefinitionCollection.php (1)
getTariffTypeDefinition
(59-62)src/product/price/PriceTypeDefinition.php (1)
getTariffTypeDefinition
(203-206)
src/product/invoice/RepresentationCollection.php (3)
src/product/behavior/BehaviorCollectionInterface.php (1)
getIterator
(15-15)src/product/price/PriceTypeDefinitionCollectionInterface.php (1)
getIterator
(15-15)src/product/price/PriceTypeDefinitionCollection.php (1)
getIterator
(34-37)
src/product/behavior/BehaviorCollectionInterface.php (1)
src/product/behavior/BehaviorCollection.php (1)
getIterator
(19-22)
src/product/Domain/Model/TariffTypeInterface.php (2)
src/product/TariffTypeDefinitionInterface.php (1)
tariffType
(15-15)src/product/TariffTypeDefinition.php (1)
tariffType
(32-35)
src/product/TariffTypeDefinition.php (2)
src/product/TariffTypeDefinitionInterface.php (2)
belongToTariffType
(23-23)tariffType
(15-15)src/product/Domain/Model/TariffTypeInterface.php (1)
equals
(11-11)
src/product/TariffTypeDefinitionInterface.php (1)
src/product/TariffTypeDefinition.php (2)
belongToTariffType
(37-40)tariffType
(32-35)
src/product/BillingRegistryService.php (10)
src/product/behavior/BehaviorNotFoundException.php (1)
BehaviorNotFoundException
(7-9)src/product/behavior/InvalidBehaviorException.php (1)
InvalidBehaviorException
(7-9)src/product/Exception/AggregateNotFoundException.php (1)
AggregateNotFoundException
(7-9)src/product/Exception/TariffTypeDefinitionNotFoundException.php (1)
TariffTypeDefinitionNotFoundException
(7-10)src/product/invoice/InvalidRepresentationException.php (1)
InvalidRepresentationException
(7-10)src/product/price/PriceTypeDefinition.php (9)
PriceTypeDefinition
(25-212)type
(139-142)__construct
(41-53)documentRepresentation
(125-130)createQuantityFormatter
(102-111)hasType
(144-147)withBehaviors
(154-159)getAggregate
(188-195)hasBehavior
(161-170)src/product/quantity/FractionQuantityData.php (1)
FractionQuantityData
(7-14)src/product/quantity/QuantityFormatterNotFoundException.php (1)
QuantityFormatterNotFoundException
(7-9)src/type/Type.php (2)
Type
(18-103)anyId
(99-102)src/product/BillingRegistry.php (11)
__construct
(21-24)BillingRegistry
(10-91)getRepresentationsByType
(47-50)priceTypes
(38-45)createQuantityFormatter
(52-57)getBehavior
(59-62)getBehaviors
(67-70)getTariffTypeDefinitions
(33-36)getAggregate
(72-75)findTariffTypeDefinitionByBehavior
(77-80)findPriceTypeDefinitionsByBehavior
(82-85)
src/product/price/PriceTypeDefinitionCollectionInterface.php (7)
src/product/behavior/BehaviorCollectionInterface.php (2)
getIterator
(15-15)end
(22-22)src/product/price/PriceTypeDefinitionCollection.php (4)
getIterator
(34-37)priceType
(39-47)end
(49-52)getTariffTypeDefinition
(59-62)src/product/price/PriceTypeDefinition.php (3)
type
(139-142)end
(116-120)getTariffTypeDefinition
(203-206)src/product/TariffTypeDefinitionInterface.php (1)
end
(37-37)src/product/TariffTypeDefinition.php (1)
end
(91-101)src/product/behavior/BehaviorPriceTypeDefinitionCollection.php (1)
end
(15-18)src/product/behavior/BehaviorTariffTypeCollection.php (1)
end
(15-18)
🪛 GitHub Check: PHP 8.3
src/product/behavior/BehaviorCollectionInterface.php
[failure] 10-10: MissingTemplateParam
src/product/behavior/BehaviorCollectionInterface.php:10:47: MissingTemplateParam: hiqdev\php\billing\product\behavior\BehaviorCollectionInterface has missing template params when extending IteratorAggregate, expecting 2 (see https://psalm.dev/182)
src/product/price/PriceTypeDefinitionCollectionInterface.php
[failure] 10-10: MissingTemplateParam
src/product/price/PriceTypeDefinitionCollectionInterface.php:10:58: MissingTemplateParam: hiqdev\php\billing\product\price\PriceTypeDefinitionCollectionInterface has missing template params when extending IteratorAggregate, expecting 2 (see https://psalm.dev/182)
🪛 GitHub Actions: Psalm Static Analysis
src/product/behavior/BehaviorCollectionInterface.php
[error] 10-10: Psalm error: MissingTemplateParam - hiqdev\php\billing\product\behavior\BehaviorCollectionInterface has missing template params when extending IteratorAggregate, expecting 2 (see https://psalm.dev/182)
🔇 Additional comments (36)
src/product/Domain/Model/Unit/UnitInterface.php (1)
9-10
: Method addition is appropriate and consistent with domain modelThe addition of the
name()
method provides a standard way to retrieve the unit name, following the same pattern used in other domain interfaces likeTariffTypeInterface
. This enhances the interface's usability and maintains consistency across domain objects.src/product/price/PriceTypeDefinitionCollection.php (1)
59-62
: Improves semantic clarity of the relationshipAdding
getTariffTypeDefinition()
provides a more explicit and intention-revealing method for accessing the parent tariff type definition compared to the existingend()
method. This enhancement clarifies the relationship between price type collections and tariff type definitions, making the code more readable and easier to understand.src/product/TariffTypeDefinitionInterface.php (1)
17-24
: Well-documented method enhances domain relationship modelingThe addition of
belongToTariffType()
with comprehensive PHPDoc provides a clear, type-safe way to check if a tariff type definition belongs to a specific tariff type. This enhances the ability to enforce and verify relationships between domain objects in the billing system.src/product/price/PriceTypeDefinitionInterface.php (2)
11-11
: Appropriate import for new method return typeThe import of
TariffTypeDefinitionInterface
is necessary for the new method's return type and follows proper PHP coding practices.
51-56
: Well-documented method establishes clear domain relationshipThe new
getTariffTypeDefinition()
method explicitly defines the relationship between price type definitions and tariff type definitions. The comprehensive PHPDoc clearly explains the purpose, making the code more maintainable and the domain model relationships more transparent.src/product/invoice/RepresentationCollection.php (2)
8-8
: Consistent use of imported Traversable interface.Good addition of the Traversable import, which aligns with the best practice of using imported classes rather than relying on fully qualified names.
27-29
: Improved type safety with generic return type.The update from
RepresentationInterface[]
toTraversable<RepresentationInterface>
in the PHPDoc and changing the method signature from\Traversable
to the importedTraversable
interface improves type safety and makes the code more consistent with other collection interfaces in the codebase.src/product/behavior/BehaviorCollectionInterface.php (2)
8-8
: Good addition of imported Traversable interface.Using the imported Traversable interface rather than the fully qualified name improves readability and consistency.
13-15
: Improved type clarity with generic Traversable.The update from a simple array return type to
Traversable<BehaviorInterface>
in the PHPDoc improves type safety and makes the code more consistent with other collection interfaces.src/product/TariffTypeDefinition.php (2)
13-15
: Explicit generic type implementation.Good addition of the PHPDoc that explicitly states the generic type parameter being used when implementing the interface. This improves type safety and code clarity.
37-40
: Well-implemented tariff type equality check.The new
belongToTariffType
method provides a clear way to check if this definition belongs to a specific tariff type by leveraging theequals
method of the tariff type interface. This implementation aligns well with the related interface changes.src/product/Domain/Model/TariffTypeInterface.php (1)
11-13
: Enhanced comparison capabilities.The addition of
equals
andequalsName
methods provides useful functionality for comparing tariff types both by reference and by name. These methods support the enhanced relationship management between tariff types and price types throughout the codebase.src/product/price/PriceTypeDefinition.php (3)
17-17
: Good addition of the required import.The import for
TariffTypeDefinitionInterface
is correctly added to support the new methods being implemented.
203-206
: Well-implemented delegation method.Good implementation of the
getTariffTypeDefinition()
method that delegates to the parent collection. This maintains a clean hierarchy and follows the principle of single responsibility by letting each level of the hierarchy handle its own concerns.
208-211
: Effective implementation of tariff type relationship check.The
belongsToTariffType
method provides a convenient way to check if a price type belongs to a specific tariff type, improving usability of the API. The method correctly uses the tariff type definition'sequalsName
method for comparison.src/product/price/PriceTypeDefinitionCollectionInterface.php (4)
8-8
: Good import of the Traversable interface.Explicitly importing the
Traversable
interface instead of using the fully qualified name improves code readability.
13-15
: Improved return type documentation and implementation.The return type of
getIterator()
has been correctly updated to useTraversable<PriceTypeDefinitionInterface>
in the PHPDoc and the method signature now returnsTraversable
instead of\Traversable
, which is more consistent with the imported interface.
19-24
: Good addition of the end() method with appropriate PHPDoc.The
end()
method provides a fluent interface to return to the parent tariff type definition, following the builder pattern. The PHPDoc correctly specifies the return type with template parameter annotation.
25-32
: Well-documented relationship method.The
getTariffTypeDefinition()
method with explanatory PHPDoc clarifies the relationship betweenPriceTypeDefinitionCollection
andTariffTypeDefinition
, making the code more maintainable and easier to understand.src/product/BillingRegistryInterface.php (6)
18-19
: Improved PHPDoc for priceTypes() method.The PHPDoc has been enhanced to specify the return type as
Generator<PriceTypeDefinitionInterface>
, which improves type safety and code understanding.
22-22
: Changed return type specification for getTariffTypeDefinitions().The return type has been changed from
Generator
toarray
, which is more appropriate since the method returns a collection of all tariff type definitions at once rather than yielding them one by one.
44-49
: Enhanced PHPDoc for getBehaviors method.The documentation for the
getBehaviors
method has been improved with a clearer description of its purpose and a more specific return type annotation.
51-51
: Added method to find tariff type definition by behavior.This new method provides a convenient way to locate a tariff type definition based on a behavior instance, enhancing the API's functionality.
53-59
: Well-documented method for finding price type definitions by behavior.The new
findPriceTypeDefinitionsByBehavior
method with its descriptive PHPDoc improves the API by adding the ability to search for price type definitions based on behavior class, making the system more flexible.
61-61
: Repositioned method without signature changes.The
getAggregate
method was moved to the end of the interface without changes to its signature, maintaining backward compatibility while organizing the interface methods more logically.src/product/BillingRegistryService.php (9)
1-24
: Well-structured service class implementation.The new
BillingRegistryService
class is correctly implemented with proper namespace, imports, and constructor injection. This follows good practices for service classes by accepting the dependency (BillingRegistry
) through the constructor.
25-47
: Comprehensive implementation of representation retrieval.The
getRepresentationsByType
method includes proper validation of the representation class existence and interface implementation before proceeding with the search. The method effectively collects all matching representations from price types.
49-62
: Well-implemented quantity formatter creation.The
createQuantityFormatter
method correctly converts the string type to aTypeInterface
and searches through price types to find and return the appropriate formatter, throwing an exception if not found.
64-67
: Simple helper method for type conversion.The
convertStringTypeToType
method encapsulates the conversion logic from string toTypeInterface
, promoting code reuse and maintainability.
69-98
: Thorough implementation of behavior retrieval with validation.The
getBehavior
method includes comprehensive validation of the behavior class existence and interface implementation, and efficiently searches through price types to find the matching behavior.
100-111
: Useful helper method for finding behaviors in price types.The
findBehaviorInPriceType
method extracts the behavior search logic into a reusable method, which improves code organization and readability.
135-146
: Well-implemented aggregate retrieval.The
getAggregate
method effectively converts the type string, searches for a matching price type, and returns its aggregate or throws an appropriate exception if not found.
148-159
: Effective implementation of tariff type definition lookup by behavior.The
findTariffTypeDefinitionByBehavior
method efficiently extracts the tariff type from the behavior and searches for a matching tariff type definition, throwing an appropriate exception if not found.
161-168
: Efficient generator implementation for finding price types by behavior.The
findPriceTypeDefinitionsByBehavior
method uses a generator to yield price type definitions with the specified behavior class, which is memory-efficient for potentially large collections.src/product/BillingRegistry.php (2)
40-40
: Nice substitution of direct property access with accessorUsing the accessor improves encapsulation and keeps future refactors safer.
72-75
: Missing import forAggregateInterface
Unless
AggregateInterface
is in the same namespace, calls will fail withClass "hiqdev\php\billing\product\AggregateInterface" not found
.+use hiqdev\php\billing\product\aggregate\AggregateInterface;
Validate the correct FQN/path and add the import accordingly.
@@ -5,15 +5,29 @@ | |||
use hiqdev\php\billing\product\TariffTypeDefinitionInterface; | |||
use hiqdev\php\billing\product\trait\HasLockInterface; | |||
use hiqdev\php\billing\type\TypeInterface; | |||
use Traversable; | |||
|
|||
interface PriceTypeDefinitionCollectionInterface extends \IteratorAggregate, \Countable, HasLockInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the missing template parameter in interface definition.
The interface is extending IteratorAggregate
without specifying the required template parameters.
#!/bin/bash
# Check how IteratorAggregate is typically used in PHP 8.x
rg -A 3 'implements\s+\\\?IteratorAggregate.+<' --type php
Apply this fix:
-interface PriceTypeDefinitionCollectionInterface extends \IteratorAggregate, \Countable, HasLockInterface
+interface PriceTypeDefinitionCollectionInterface extends \IteratorAggregate<int, PriceTypeDefinitionInterface>, \Countable, HasLockInterface
🧰 Tools
🪛 GitHub Check: PHP 8.3
[failure] 10-10: MissingTemplateParam
src/product/price/PriceTypeDefinitionCollectionInterface.php:10:58: MissingTemplateParam: hiqdev\php\billing\product\price\PriceTypeDefinitionCollectionInterface has missing template params when extending IteratorAggregate, expecting 2 (see https://psalm.dev/182)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/product/price/PriceTypeDefinitionCollectionInterface.php (1)
10-10
: Fix the missing template parameter in interface definition.The interface is extending
IteratorAggregate
without specifying the required template parameters.Apply this fix:
-interface PriceTypeDefinitionCollectionInterface extends \IteratorAggregate, \Countable, HasLockInterface +interface PriceTypeDefinitionCollectionInterface extends \IteratorAggregate<int, PriceTypeDefinitionInterface>, \Countable, HasLockInterface🧰 Tools
🪛 GitHub Check: PHP 8.3
[failure] 10-10: MissingTemplateParam
src/product/price/PriceTypeDefinitionCollectionInterface.php:10:58: MissingTemplateParam: hiqdev\php\billing\product\price\PriceTypeDefinitionCollectionInterface has missing template params when extending IteratorAggregate, expecting 2 (see https://psalm.dev/182)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/product/price/PriceTypeDefinition.php
(3 hunks)src/product/price/PriceTypeDefinitionCollectionInterface.php
(1 hunks)src/product/price/PriceTypeDefinitionInterface.php
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/product/price/PriceTypeDefinitionInterface.php
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/product/price/PriceTypeDefinition.php (4)
src/type/Type.php (1)
Type
(18-103)src/product/price/PriceTypeDefinitionInterface.php (4)
getTariffTypeDefinition
(56-56)belongsToTariffType
(58-58)belongsToPriceType
(60-60)type
(34-34)src/product/TariffTypeDefinitionInterface.php (1)
tariffType
(15-15)src/product/Domain/Model/TariffTypeInterface.php (2)
equalsName
(13-13)name
(7-7)
src/product/price/PriceTypeDefinitionCollectionInterface.php (9)
src/product/behavior/BehaviorCollectionInterface.php (2)
getIterator
(15-15)end
(22-22)src/product/price/PriceTypeDefinitionCollection.php (3)
getIterator
(34-37)end
(49-52)getTariffTypeDefinition
(59-62)src/product/behavior/BehaviorCollection.php (1)
getIterator
(19-22)src/product/price/PriceTypeDefinitionInterface.php (3)
type
(34-34)end
(27-27)getTariffTypeDefinition
(56-56)src/product/price/PriceTypeDefinition.php (3)
type
(140-143)end
(117-121)getTariffTypeDefinition
(204-207)src/product/TariffTypeDefinitionInterface.php (1)
end
(37-37)src/product/TariffTypeDefinition.php (1)
end
(91-101)src/product/behavior/BehaviorPriceTypeDefinitionCollection.php (1)
end
(15-18)src/product/behavior/BehaviorTariffTypeCollection.php (1)
end
(15-18)
🪛 GitHub Check: PHP 8.3
src/product/price/PriceTypeDefinition.php
[failure] 216-216: UndefinedClass
src/product/price/PriceTypeDefinition.php:216:30: UndefinedClass: Class, interface or enum named hiqdev\billing\registry\Type\TypeSemantics does not exist (see https://psalm.dev/019)
src/product/price/PriceTypeDefinitionCollectionInterface.php
[failure] 10-10: MissingTemplateParam
src/product/price/PriceTypeDefinitionCollectionInterface.php:10:58: MissingTemplateParam: hiqdev\php\billing\product\price\PriceTypeDefinitionCollectionInterface has missing template params when extending IteratorAggregate, expecting 2 (see https://psalm.dev/182)
🔇 Additional comments (5)
src/product/price/PriceTypeDefinition.php (2)
204-207
: LGTM! Good method implementation.The
getTariffTypeDefinition()
method correctly delegates to the parent collection's corresponding method, establishing a proper relationship hierarchy between price type and tariff type definitions.
209-212
: LGTM! Useful relationship check.The
belongsToTariffType
method provides a convenient way to determine if a price type belongs to a specific tariff type by name, utilizing the existingequalsName
method from the tariff type interface.src/product/price/PriceTypeDefinitionCollectionInterface.php (3)
8-8
: LGTM! Improved type safety.The explicit import of
Traversable
and updating the return type annotation forgetIterator()
with proper generic types enhances type safety and better communicates the interface's behavior.Also applies to: 13-15
19-23
: LGTM! Clear method documentation.The added PHPDoc for the
end()
method clearly specifies the return type and includes template parameter information for improved type checking.
25-32
: LGTM! Well-documented relationship method.The new
getTariffTypeDefinition()
method with comprehensive documentation clearly establishes the relationship betweenPriceTypeDefinitionCollection
andTariffTypeDefinition
, making the code more maintainable and self-explanatory.This addition complements the new method in
PriceTypeDefinition
that delegates to this method, creating a consistent way to navigate the relationship hierarchy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/product/BillingRegistry.php (2)
19-22
: Bidirectional dependency between BillingRegistry and BillingRegistryServiceThe BillingRegistry class creates an instance of BillingRegistryService and passes itself to it, forming a bidirectional dependency. While this pattern can work, it may lead to tight coupling that could make testing more difficult.
Consider using dependency injection instead:
- private BillingRegistryService $service; + private BillingRegistryServiceInterface $service; - public function __construct() + public function __construct(BillingRegistryServiceInterface $service = null) { - $this->service = new BillingRegistryService($this); + $this->service = $service ?? new BillingRegistryService($this); }This would allow for easier mocking in tests and more flexible configuration.
62-64
: Fix typo in PHPDoc tagThere's a typo in the
@inheritDoc
tag.- /** - * @inerhitDoc - */ + /** + * @inheritDoc + */
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/product/BillingRegistry.php
(3 hunks)
🔇 Additional comments (2)
src/product/BillingRegistry.php (2)
16-83
: Good implementation of the Facade patternThe refactoring to delegate core logic to a dedicated service class is a good architectural decision. This separation of concerns:
- Makes the code more maintainable by centralizing complex logic in the service
- Allows BillingRegistry to focus on its role as a registry
- Improves testability by allowing the service to be potentially mocked
The implementation consistently delegates method calls to the service while preserving the public API.
31-34
:✅ Verification successful
Return type change from Generator to array
The return type of
getTariffTypeDefinitions()
has been changed from Generator to array. This is a breaking change that might affect code relying on lazy evaluation.
🏁 Script executed:
#!/bin/bash # Check if there are any clients that might be affected by this return type change rg -A 2 -B 2 "getTariffTypeDefinitions\(\)" --glob="!src/product/BillingRegistry.php"Length of output: 1456
Document interface return type update for getTariffTypeDefinitions()
The
getTariffTypeDefinitions()
method’s signature has been changed from returning aGenerator
to returning anarray
. All existing internal consumers (notably in src/product/BillingRegistryService.php) useforeach
, which works identically on arrays, so there are no runtime errors introduced by this change.Please ensure:
- The PHPDoc blocks on
getTariffTypeDefinitions()
in src/product/BillingRegistry.php and src/product/BillingRegistryInterface.php are updated to@return TariffTypeDefinitionInterface[]
.- A note is added to your CHANGELOG (or release notes) to record this breaking change at the interface level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
src/product/measure/TrafCollectorInterface.php (2)
5-15
: Improve documentation to focus on interface contract rather than implementations.The current DocBlock focuses heavily on specific implementation files rather than clearly defining the contract this interface represents. Consider restructuring to:
- Explain what a traffic collector is and its purpose
- Define the expected behavior of implementations
- Move implementation examples to a separate
@see
or@example
section/** - - Websa Metering Service - The counters are in a Websa Metering Service - Set references to classes in - {@see vendor/advancedhosters/hiapi-metering-collector/src/Collectors/CdnTrafMaxCollector.php} - - - RCP Traf collector - {@see vendor/advancedhosters/hiapi-rcp-traf/src/collectors/ServerDuCollector.php} - - - PeriodicDbQuery - Support Time (stored in our DB) - Pass a DBMS function name that handles this price type measurement + * Interface for traffic collection mechanisms used in billing measurements. + * + * Traffic collectors are responsible for retrieving traffic usage data from + * various sources to be used in billing calculations. + * + * @see vendor/advancedhosters/hiapi-metering-collector/src/Collectors/CdnTrafMaxCollector.php Websa Metering Service implementation + * @see vendor/advancedhosters/hiapi-rcp-traf/src/collectors/ServerDuCollector.php RCP Traf collector implementation + * @see PeriodicDbQuery Support Time (stored in our DB) - - This interface is not completed this is only a scratch */
20-20
: Add documentation for the getClassName() method.The purpose of the
getClassName()
method isn't clear. Consider adding a DocBlock to explain why this method is needed and what it should return.interface TrafCollectorInterface { + /** + * Returns the fully qualified class name of the collector implementation. + * + * This is used for identification and registry purposes within the billing system. + * + * @return string Fully qualified class name + */ public function getClassName(): string; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/product/behavior/BehaviorCollectionInterface.php
(1 hunks)src/product/invoice/RepresentationCollection.php
(2 hunks)src/product/measure/TrafCollectorInterface.php
(1 hunks)src/product/price/PriceTypeDefinition.php
(4 hunks)src/product/price/PriceTypeDefinitionCollectionInterface.php
(1 hunks)src/product/price/PriceTypeDefinitionInterface.php
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- src/product/behavior/BehaviorCollectionInterface.php
- src/product/invoice/RepresentationCollection.php
- src/product/price/PriceTypeDefinitionCollectionInterface.php
- src/product/price/PriceTypeDefinitionInterface.php
- src/product/price/PriceTypeDefinition.php
interface TrafCollectorInterface | ||
{ | ||
public function getClassName(): string; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider expanding this minimal interface definition.
While the interface definition is syntactically correct, it currently only contains a single method getClassName()
that appears to be for identification purposes. Since this interface is intended to abstract traffic collection mechanisms (as indicated in the AI summary), consider:
- Adding methods that actually define traffic collection behavior
- Including method docblocks to explain the purpose of each method
- Removing the "scratch" status before using in production code
interface TrafCollectorInterface
{
public function getClassName(): string;
+
+ /**
+ * Collects traffic data for the specified resource within the given timeframe
+ *
+ * @param string $resourceId Identifier of the resource to measure
+ * @param \DateTimeInterface $startTime Start of the collection period
+ * @param \DateTimeInterface $endTime End of the collection period
+ * @return mixed The collected traffic data
+ */
+ public function collectTraffic(string $resourceId, \DateTimeInterface $startTime, \DateTimeInterface $endTime);
}
📝 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.
interface TrafCollectorInterface | |
{ | |
public function getClassName(): string; | |
} | |
interface TrafCollectorInterface | |
{ | |
public function getClassName(): string; | |
/** | |
* Collects traffic data for the specified resource within the given timeframe | |
* | |
* @param string $resourceId Identifier of the resource to measure | |
* @param \DateTimeInterface $startTime Start of the collection period | |
* @param \DateTimeInterface $endTime End of the collection period | |
* @return mixed The collected traffic data | |
*/ | |
public function collectTraffic(string $resourceId, \DateTimeInterface $startTime, \DateTimeInterface $endTime); | |
} |
* This interface is not completed this is only a scratch | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Remove draft status indication before using in production.
The DocBlock explicitly states "This interface is not completed this is only a scratch". Based on the AI summary, this interface is already being integrated into the codebase by replacing specific type hints in the PriceTypeDefinition
classes. Draft/incomplete interfaces should be properly completed before being used in production code.
Let's check where this interface is being used:
🏁 Script executed:
#!/bin/bash
# Check where TrafCollectorInterface is being used in the codebase
grep -r "TrafCollectorInterface" --include="*.php" .
Length of output: 603
🏁 Script executed:
#!/bin/bash
# Display the contents of TrafCollectorInterface.php for review
sed -n '1,200p' src/product/measure/TrafCollectorInterface.php
Length of output: 735
Remove draft status in TrafCollectorInterface docblock
The interface is already referenced by PriceTypeDefinition
and PriceTypeDefinitionInterface
, yet its docblock still marks it as “not completed… scratch.” Before shipping, please remove or replace that draft note with a clear description of the interface’s purpose.
- File:
src/product/measure/TrafCollectorInterface.php
, docblock (lines 5–12)
• Remove the “This interface is not completed this is only a scratch” sentence
• Update the summary to explain whatgetClassName()
returns and how implementations should behave
Example diff:
/**
* - Websa Metering Service - The counters are in a Websa Metering Service
* Set references to classes in
* {@see vendor/advancedhosters/hiapi-metering-collector/src/Collectors/CdnTrafMaxCollector.php}
*
* - RCP Traf collector
* {@see vendor/advancedhosters/hiapi-rcp-traf/src/collectors/ServerDuCollector.php}
*
* - PeriodicDbQuery - Support Time (stored in our DB)
* Pass a DBMS function name that handles this price type measurement
- * This interface is not completed this is only a scratch
+ * Returns the fully qualified class name of a traffic collector implementation.
*/
interface TrafCollectorInterface
{
public function getClassName(): string;
}
… to communicate only through it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (5)
src/product/BillingRegistryInterface.php (1)
16-18
: Add PHPDoc to keep interface self-documenting and consistent
getTariffTypeDefinitions()
andaddTariffType()
miss PHPDoc blocks, whilepriceTypes()
already provides one. Adding them helps IDEs/static-analysis and keeps the public contract explicit.@@ - public function getTariffTypeDefinitions(): array; + /** + * Return **all** tariff-type definitions registered in the system. + * + * @return TariffTypeDefinitionInterface[] + */ + public function getTariffTypeDefinitions(): array; @@ - public function addTariffType(TariffTypeDefinitionInterface $tariffTypeDefinition): void; + /** + * Register a new tariff-type definition. + */ + public function addTariffType(TariffTypeDefinitionInterface $tariffTypeDefinition): void;src/product/Application/BillingRegistryServiceInterface.php (1)
5-5
: Redundantuse Generator;
importBecause
\Generator
is a built-in global class, it’s available without importing. The extrause
isn’t harmful but adds noise. You can safely drop it:-use Generator;
src/product/BillingRegistry.php (2)
21-24
: Add return-type PHPDoc for static analysersReturning a plain
array
hides the element type. A one-liner keeps tools happy:- public function getTariffTypeDefinitions(): array + /** + * @return TariffTypeDefinitionInterface[] + */ + public function getTariffTypeDefinitions(): array
26-33
: Useyield from
for a more idiomatic generatorNestled
foreach
loops work, butyield from
both flattens the code and signals intent:- foreach ($this->getTariffTypeDefinitions() as $tariffTypeDefinition) { - foreach ($tariffTypeDefinition->withPrices() as $priceTypeDefinition) { - yield $priceTypeDefinition; - } - } + foreach ($this->getTariffTypeDefinitions() as $tariffTypeDefinition) { + yield from $tariffTypeDefinition->withPrices(); + }The behaviour and memory profile stay identical while improving readability.
src/product/Application/BillingRegistryService.php (1)
41-47
: Possible duplicate / order-dependent collection
$representations
may end up with duplicate objects when several price-type definitions share the same representation instance.
If uniqueness matters (e.g. JSON-serialisation, UI listing), consider usingSplObjectStorage
orarray_unique()
keyed byspl_object_id()
/ class name.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/product/Application/BillingRegistryService.php
(1 hunks)src/product/Application/BillingRegistryServiceInterface.php
(1 hunks)src/product/BillingRegistry.php
(1 hunks)src/product/BillingRegistryInterface.php
(1 hunks)tests/unit/product/Domain/Model/DummyTariffType.php
(1 hunks)tests/unit/product/Domain/Model/FakeTariffType.php
(1 hunks)tests/unit/product/Domain/Model/MockTariffType.php
(1 hunks)tests/unit/product/Domain/Model/TariffType.php
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
tests/unit/product/Domain/Model/DummyTariffType.php (1)
tests/unit/product/Domain/Model/TariffType.php (1)
TariffType
(7-18)
tests/unit/product/Domain/Model/MockTariffType.php (1)
tests/unit/product/Domain/Model/TariffType.php (1)
TariffType
(7-18)
tests/unit/product/Domain/Model/FakeTariffType.php (1)
tests/unit/product/Domain/Model/TariffType.php (1)
TariffType
(7-18)
src/product/BillingRegistryInterface.php (1)
src/product/BillingRegistry.php (3)
priceTypes
(26-33)getTariffTypeDefinitions
(21-24)addTariffType
(14-19)
tests/unit/product/Domain/Model/TariffType.php (3)
tests/unit/product/Domain/Model/DummyTariffType.php (1)
name
(7-10)tests/unit/product/Domain/Model/FakeTariffType.php (1)
name
(7-10)tests/unit/product/Domain/Model/MockTariffType.php (1)
name
(7-10)
🔇 Additional comments (8)
tests/unit/product/Domain/Model/TariffType.php (1)
7-18
: Well-designed abstract class for comparison functionality!This new abstract class efficiently centralizes the equality comparison logic for tariff types:
equals()
method allows comparison between tariff type instancesequalsName()
method enables direct string name comparison- Both methods use the
name()
method that concrete classes must implementThis approach follows good OO design principles by:
- Eliminating code duplication across implementations
- Providing a consistent comparison mechanism
- Maintaining a clear separation of concerns
tests/unit/product/Domain/Model/DummyTariffType.php (1)
5-5
: Good refactoring to use the abstract class.The change from directly implementing
TariffTypeInterface
to extending the abstractTariffType
class is a good refactoring approach. This leverages the shared implementation ofequals
andequalsName
methods provided by the abstract class, promoting code reuse and consistency across tariff type implementations.tests/unit/product/Domain/Model/FakeTariffType.php (1)
5-5
: Good inheritance structure change.Changing from direct interface implementation to extending the abstract
TariffType
class follows good OOP practices by reusing the common equality comparison logic. This maintains consistent behavior across all tariff type test classes while reducing code duplication.tests/unit/product/Domain/Model/MockTariffType.php (1)
5-5
: Appropriate use of inheritance for shared behavior.The change to extend the abstract
TariffType
class rather than directly implementing the interface is appropriate. This allowsMockTariffType
to inherit the standard implementations ofequals
andequalsName
methods while retaining its specific implementations ofname()
andlabel()
. This approach ensures consistency in comparison behavior across all tariff type implementations.src/product/Application/BillingRegistryServiceInterface.php (1)
26-34
: Consider documenting (or typing) possible “not found” outcomes
getBehavior()
specifies two exception types, but other look-ups (getAggregate
,findTariffTypeDefinitionByBehavior
, etc.) don’t advertise failure modes. If they can legitimately “miss”, choose one of:• Return
null
and reflect it in the return type (?AggregateInterface
)
• Throw a domain-specific exception and add@throws
to the PHPDocMaking the contract explicit prevents unexpected
TypeError
s or hiddennull
usage.src/product/BillingRegistry.php (1)
35-38
: Locking only protects definitions, not contained mutability
afterLock()
forwards the lock to eachTariffTypeDefinition
, which is great. Ensure that:
- Every definition’s own
withPrices()
returns price definitions already locked (or immutable).- Down-stream code doesn’t mutate price definitions post-lock.
Otherwise, external callers could still alter objects retrieved via
priceTypes()
. If that’s already covered, feel free to ignore.src/product/Application/BillingRegistryService.php (2)
52-62
: Missing fallback whencreateQuantityFormatter()
returns nullThe loop assumes that the first price-type that “has the type” will always be able to create a formatter.
If an implementation returnsnull
(or throws) the service will bubble the exception instead of probing the remaining definitions.- return $priceTypeDefinition->createQuantityFormatter($data); + $formatter = $priceTypeDefinition->createQuantityFormatter($data); + if ($formatter !== null) { + return $formatter; + }Alternatively, check the interface contract and document the expectation.
132-143
: Ambiguous aggregate resolution when multiple price-types share a type
getAggregate()
returns the aggregate of the first matching price-type.
If the registry can legally contain several definitions for the same billing type, results become order-dependent.
Consider:• Clarifying the expectation in PHPDoc, or
• Enforcing uniqueness inBillingRegistryInterface
, or
• Returning all aggregates (\Generator
) so the caller decides.
public function getBehaviors(string $behaviorClassWrapper): \Generator | ||
{ | ||
foreach ($this->registry->getTariffTypeDefinitions() as $tariffTypeDefinition) { | ||
foreach ($tariffTypeDefinition->withBehaviors() as $behavior) { | ||
if ($behavior instanceof $behaviorClassWrapper) { | ||
yield $behavior; | ||
} | ||
} | ||
} | ||
|
||
foreach ($this->registry->priceTypes() as $priceTypeDefinition) { | ||
foreach ($priceTypeDefinition->withBehaviors() as $behavior) { | ||
if ($behavior instanceof $behaviorClassWrapper) { | ||
yield $behavior; | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add class existence / interface checks to prevent fatal errors
See previous comment. Before the two nested loops, add:
if (!class_exists($behaviorClassWrapper) ||
!is_subclass_of($behaviorClassWrapper, BehaviorInterface::class)) {
throw new InvalidBehaviorException(
sprintf('Behavior class "%s" is invalid or does not implement %s',
$behaviorClassWrapper,
BehaviorInterface::class
)
);
}
if (!class_exists($behaviorClassWrapper)) { | ||
throw new InvalidBehaviorException( | ||
sprintf('Behavior class "%s" does not exist', $behaviorClassWrapper) | ||
); | ||
} | ||
|
||
if (!is_subclass_of($behaviorClassWrapper, BehaviorInterface::class)) { | ||
throw new InvalidBehaviorException( | ||
sprintf('Behavior class "%s" does not implement BehaviorInterface', $behaviorClassWrapper) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Validation logic duplicated & missing in sibling methods
Excellent job validating $behaviorClassWrapper
here.
However, the same guard clauses are absent in getBehaviors()
and findPriceTypeDefinitionsByBehavior()
.
Calling those methods with an unknown class string will raise a fatal Error: Class "<name>" not found
.
Extract the validation into a small private helper and reuse it.
public function findPriceTypeDefinitionsByBehavior(string $behaviorClassWrapper): \Generator | ||
{ | ||
foreach ($this->registry->priceTypes() as $priceTypeDefinition) { | ||
if ($priceTypeDefinition->hasBehavior($behaviorClassWrapper)) { | ||
yield $priceTypeDefinition; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Same validation gap as in getBehaviors()
Add the class_exists
/is_subclass_of
guard here as well to avoid runtime fatals.
if (!class_exists($representationClass)) { | ||
throw new InvalidRepresentationException("Class '$representationClass' does not exist"); | ||
} | ||
|
||
if (!is_subclass_of($representationClass, RepresentationInterface::class)) { | ||
throw new InvalidBehaviorException( | ||
sprintf('Representation class "%s" does not implement RepresentationInterface', $representationClass) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect exception type for representation-interface validation
When the provided class is not a RepresentationInterface
, InvalidBehaviorException
is thrown.
That is confusing, because the error is about representation misuse, not behavior misuse, and clients relying on the more specific InvalidRepresentationException
will silently miss it.
- throw new InvalidBehaviorException(
- sprintf('Representation class "%s" does not implement RepresentationInterface', $representationClass)
- );
+ throw new InvalidRepresentationException(
+ sprintf('Representation class "%s" does not implement %s', $representationClass, RepresentationInterface::class)
+ );
📝 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.
if (!class_exists($representationClass)) { | |
throw new InvalidRepresentationException("Class '$representationClass' does not exist"); | |
} | |
if (!is_subclass_of($representationClass, RepresentationInterface::class)) { | |
throw new InvalidBehaviorException( | |
sprintf('Representation class "%s" does not implement RepresentationInterface', $representationClass) | |
); | |
} | |
if (!class_exists($representationClass)) { | |
throw new InvalidRepresentationException("Class '$representationClass' does not exist"); | |
} | |
if (!is_subclass_of($representationClass, RepresentationInterface::class)) { | |
- throw new InvalidBehaviorException( | |
- sprintf('Representation class "%s" does not implement RepresentationInterface', $representationClass) | |
- ); | |
+ throw new InvalidRepresentationException( | |
+ sprintf('Representation class "%s" does not implement %s', $representationClass, RepresentationInterface::class) | |
+ ); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
tests/unit/product/Application/BillingRegistryServiceTest.php (4)
61-96
: Test method naming is inconsistent with PHP conventions.The method name uses snake_case (
testGetBehavior_WithMultipleTariffTypeDefinitions
) which is inconsistent with PHP's PSR-1/PSR-2 coding standards that recommend camelCase for method names.Otherwise, the test logic is solid, effectively testing behavior retrieval across multiple tariff type definitions.
- public function testGetBehavior_WithMultipleTariffTypeDefinitions(): void + public function testGetBehaviorWithMultipleTariffTypeDefinitions(): void
71-85
: Complex builder chain could be simplified for better readability.The nested builder chain makes the test setup complex and harder to follow. Consider extracting this configuration into a helper method to improve test readability.
+ private function createTariffTypeDefinitionWithBehaviors(DummyTariffType $tariffType, array $typeAndBehaviors): TariffTypeDefinition + { + $definition = new TariffTypeDefinition($tariffType); + $builder = $definition->withPrices(); + + foreach ($typeAndBehaviors as $item) { + $builder = $builder + ->priceType($item['type']) + ->withBehaviors(); + + foreach ($item['behaviors'] as $behavior) { + $builder = $builder->attach($behavior); + } + + $builder = $builder->end()->end(); + } + + return $builder->end(); + } public function testGetBehaviorWithMultipleTariffTypeDefinitions(): void { $tariffType = new DummyTariffType(); - $tariffTypeDefinition = new TariffTypeDefinition($tariffType); $type1 = Type::anyId('type,dummy1'); $type2 = Type::anyId('type,dummy2'); $dummyBehavior1 = new TestBehavior('dummy 1'); $dummyBehavior2 = new TestBehavior('dummy 2'); $dummyBehavior3 = new FakeBehavior('dummy 3'); - $tariffTypeDefinition - ->withPrices() - ->priceType($type1) - ->withBehaviors() - ->attach($dummyBehavior1) - ->end() - ->end() - ->priceType($type2) - ->withBehaviors() - ->attach($dummyBehavior2) - ->attach($dummyBehavior3) - ->end() - ->end() - ->end(); + $tariffTypeDefinition = $this->createTariffTypeDefinitionWithBehaviors( + $tariffType, + [ + [ + 'type' => $type1, + 'behaviors' => [$dummyBehavior1] + ], + [ + 'type' => $type2, + 'behaviors' => [$dummyBehavior2, $dummyBehavior3] + ] + ] + );
98-134
: Test method naming is inconsistent with PHP conventions.Similar to the previous test method, this one also uses snake_case which is inconsistent with PHP's PSR-1/PSR-2 coding standards.
The test logic effectively verifies behavior retrieval with multiple price type definitions.
- public function testGetBehavior_WithMultiplePriceTypeDefinitions(): void + public function testGetBehaviorWithMultiplePriceTypeDefinitions(): void
142-146
: Address commented-out test.There's a commented-out test for
createQuantityFormatter
. Either implement this test if the functionality is ready, remove it if it's not needed, or add a TODO comment explaining why it's commented out and when it will be implemented.- // public function testCreateQuantityFormatterThrowsExceptionWhenNotFound(): void -// { -// $this->expectException(QuantityFormatterNotFoundException::class); -// $this->registryService->createQuantityFormatter('non-existent-type', $this->createMock(FractionQuantityData::class)); -// } + /** + * @todo Implement this test when the createQuantityFormatter functionality is ready + */ + // public function testCreateQuantityFormatterThrowsExceptionWhenNotFound(): void + // { + // $this->expectException(QuantityFormatterNotFoundException::class); + // $this->registryService->createQuantityFormatter('non-existent-type', $this->createMock(FractionQuantityData::class)); + // }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
tests/unit/product/Application/BillingRegistryServiceTest.php
(1 hunks)tests/unit/product/BillingRegistryTest.php
(0 hunks)
💤 Files with no reviewable changes (1)
- tests/unit/product/BillingRegistryTest.php
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/unit/product/Application/BillingRegistryServiceTest.php (9)
src/product/Application/BillingRegistryService.php (1)
BillingRegistryService
(22-166)src/product/behavior/BehaviorNotFoundException.php (1)
BehaviorNotFoundException
(7-9)src/product/Exception/AggregateNotFoundException.php (1)
AggregateNotFoundException
(7-9)src/product/invoice/InvalidRepresentationException.php (1)
InvalidRepresentationException
(7-10)tests/unit/product/behavior/FakeBehavior.php (1)
FakeBehavior
(5-8)tests/unit/product/behavior/TestBehavior.php (1)
TestBehavior
(7-20)tests/unit/product/Domain/Model/DummyTariffType.php (1)
DummyTariffType
(5-16)tests/unit/product/Domain/Model/FakeTariffType.php (1)
FakeTariffType
(5-16)src/type/Type.php (2)
Type
(18-103)anyId
(99-102)
🔇 Additional comments (6)
tests/unit/product/Application/BillingRegistryServiceTest.php (6)
18-29
: Good setup with proper dependency injection.The class has a clear setup with proper initialization of the
BillingRegistry
andBillingRegistryService
objects. The dependency is correctly injected into the service following the dependency injection pattern.
30-35
: Well-structured test for representation type validation.This test properly verifies that the service throws an
InvalidRepresentationException
when passed an invalid class name. The expectation is set correctly before calling the method under test.
36-41
: Good exception testing for aggregate retrieval.The test correctly verifies the exception handling behavior when attempting to retrieve a non-existent aggregate type.
42-59
: Comprehensive behavior retrieval test.The test effectively sets up a tariff type definition with behaviors and verifies that the service correctly retrieves the expected behavior. Good use of assertSame to confirm the exact instance is returned.
65-67
: Verify the Type identifiers format.The type identifiers use a comma separator (
type,dummy1
andtype,dummy2
). Make sure this format is consistent with how your application processes type identifiers elsewhere.
136-140
: Effective test for behavior not found scenario.The test properly verifies that the service throws a
BehaviorNotFoundException
when attempting to retrieve a non-existent behavior.
Summary by CodeRabbit
New Features
Improvements
Tests