-
Notifications
You must be signed in to change notification settings - Fork 81
Expanded the product availability section #3190
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
Changes from all commits
8b3e1f5
506f3f5
2fcdf0c
6ccb073
4ec36b7
b3ef778
4538d61
ca36bc1
3914776
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| services: | ||
| App\ProductCatalog\Availability\ProductAvailabilityPurchasableWithoutStockStrategy: | ||
| tags: | ||
| - { name: ibexa.product_catalog.availability.strategy } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\ProductCatalog\Availability; | ||
|
|
||
| use Ibexa\Contracts\ProductCatalog\ProductAvailabilityStrategyInterface; | ||
| use Ibexa\Contracts\ProductCatalog\Values\Availability\AvailabilityContextInterface; | ||
| use Ibexa\Contracts\ProductCatalog\Values\Availability\AvailabilityInterface; | ||
| use Ibexa\Contracts\ProductCatalog\Values\ProductInterface; | ||
| use Ibexa\ProductCatalog\Local\Persistence\Legacy\ProductAvailability\HandlerInterface; | ||
| use Ibexa\ProductCatalog\Local\Repository\Values\Availability; | ||
|
|
||
| final class ProductAvailabilityPurchasableWithoutStockStrategy implements ProductAvailabilityStrategyInterface | ||
| { | ||
| private HandlerInterface $handler; | ||
|
|
||
| public function __construct(HandlerInterface $handler) | ||
| { | ||
| $this->handler = $handler; | ||
| } | ||
|
|
||
| public function accept(AvailabilityContextInterface $context): bool | ||
| { | ||
| return $context instanceof PurchasableWithoutStockAvailabilityContext; | ||
| } | ||
|
|
||
| public function getProductAvailability( | ||
| ProductInterface $product, | ||
| AvailabilityContextInterface $context | ||
| ): AvailabilityInterface { | ||
| $productAvailability = $this->handler->find($product->getCode()); | ||
|
|
||
| $rawAvailableFlag = $productAvailability->isAvailable(); | ||
| $stock = $productAvailability->getStock(); | ||
| $isInfinite = $productAvailability->isInfinite(); | ||
|
|
||
| $computedAvailable = $this->calculateAvailability( | ||
| $rawAvailableFlag, | ||
| $stock, | ||
| $isInfinite, | ||
| ); | ||
|
|
||
| return new Availability( | ||
| $product, | ||
| $rawAvailableFlag, | ||
| $computedAvailable, | ||
| $isInfinite, | ||
| $stock, | ||
| ); | ||
| } | ||
|
|
||
| private function calculateAvailability( | ||
|
Check warning on line 51 in code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php
|
||
| bool $rawAvailable, | ||
| ?int $stock, | ||
| bool $isInfinite | ||
| ): bool { | ||
| if ($rawAvailable === false) { | ||
| return false; | ||
| } | ||
|
|
||
| if ($isInfinite) { | ||
| return true; | ||
| } | ||
|
|
||
| if ($stock === null) { | ||
| return true; | ||
| } | ||
|
|
||
| return $stock >= 0; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\ProductCatalog\Availability; | ||
|
|
||
| use Ibexa\Contracts\ProductCatalog\Values\Availability\AvailabilityContextInterface; | ||
|
|
||
| final class PurchasableWithoutStockAvailabilityContext implements AvailabilityContextInterface | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| --- | ||
| description: Implement custom availability strategies to handle different business scenarios, for example pre-orders or per-region availability. | ||
| --- | ||
|
|
||
| # Create custom availability strategy | ||
|
|
||
| The product catalog uses an availability strategy to calculate [computed availability](products.md#availability-and-computed-availability) for a product. | ||
| Computed availability decides whether the customers can order the product. | ||
| The default availability strategy is based on the product availability and stock amount. | ||
|
Check notice on line 9 in docs/pim/create_custom_availability_strategy.md
|
||
|
|
||
| You can replace this logic with a custom strategy to handle specific business scenarios, for example preorders, minimum order quantities, or per-region availability. | ||
|
Check failure on line 11 in docs/pim/create_custom_availability_strategy.md
|
||
|
|
||
| The following example implements an availability strategy which allows buying products when they're set as available, without taking their stock into account. | ||
| You could use it for [virtual products](products.md#product-types) or in preorder scenarios. | ||
|
Check failure on line 14 in docs/pim/create_custom_availability_strategy.md
|
||
|
|
||
| ## Create custom availability context | ||
|
|
||
| Use an availability context to pass the parameters needed by the strategy to evaluate computed availability. | ||
| To do it, create a class that implements the [`AvailabilityContextInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Availability-AvailabilityContextInterface.html) interface: | ||
|
|
||
| ``` php | ||
| [[= include_file('code_samples/pim/availability/src/PurchasableWithoutStockAvailabilityContext.php') =]] | ||
| ``` | ||
|
|
||
| ## Create custom availability strategy | ||
|
|
||
| Create a class that implements the [`ProductAvailabilityStrategyInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-ProductAvailabilityStrategyInterface.html) interface: | ||
|
|
||
| ``` php | ||
| [[= include_file('code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php') =]] | ||
| ``` | ||
|
|
||
| The strategy has two methods: | ||
|
|
||
| - `accept()` decides if the strategy can handle the provided availability context | ||
| - `getProductAvailability()` returns an [`AvailabilityInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Availability-AvailabilityInterface.html) object | ||
|
|
||
| When constructing the `AvailabilityInterface` object, provide the stock amount, the availability flag, and the result of your custom availability logic. | ||
|
|
||
| ## Register strategy as a service | ||
|
Check notice on line 40 in docs/pim/create_custom_availability_strategy.md
|
||
|
|
||
| If you're not using [autowiring]([[= symfony_doc =]]/service_container/autowiring.html), tag the strategy service with `ibexa.product_catalog.availability.strategy`: | ||
|
Check notice on line 42 in docs/pim/create_custom_availability_strategy.md
|
||
|
|
||
| ``` yaml | ||
| [[= include_file('code_samples/pim/availability/config/custom_services.yaml') =]] | ||
| ``` | ||
|
|
||
| ## Use custom context | ||
|
|
||
| To evaluate product availability using a custom strategy, pass the custom context as the second argument to [`ProductAvailabilityServiceInterface::getAvailability()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-ProductAvailabilityServiceInterface.html): | ||
|
Check notice on line 50 in docs/pim/create_custom_availability_strategy.md
|
||
|
|
||
| ```php | ||
| [[= include_code('code_samples/api/product_catalog/src/Command/ProductCommand.php', 122, 127, remove_indent=True) =]] | ||
| ``` | ||
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.