Allow promotion coupon to be filtered by promotion code (#16646)

| Q               | A
|-----------------|-----
| Branch?         | api-platform-3 <!-- see the comment below -->
| Bug fix?        | no
| New feature?    | no
| BC breaks?      | no
| License         | MIT

<!--
 - Bug fixes must be submitted against the 1.13 branch
 - Features and deprecations must be submitted against the 1.14 branch
- Features, removing deprecations and BC breaks must be submitted
against the 2.0 branch
 - Make sure that the correct base branch is set

To be sure you are not breaking any Backward Compatibilities, check the
documentation:

https://docs.sylius.com/en/latest/book/organization/backward-compatibility-promise.html
-->
This commit is contained in:
Michał Pysiak 2024-07-30 13:36:47 +02:00 committed by GitHub
commit bd4e576b23
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 66 additions and 101 deletions

View file

@ -19,7 +19,7 @@ Feature: Filtering coupons
And this coupon expires on "20-02-2023"
And I am logged in as an administrator
@ui @todo-api
@api @ui
Scenario: Filtering coupons by code
Given I am browsing coupons of this promotion
When I filter by code containing "X"

View file

@ -49,8 +49,21 @@ final class ManagingPromotionCouponsContext implements Context
{
$this->client->index(Resources::PROMOTION_COUPONS);
$this->client->addFilter(
'promotion',
$this->iriConverter->getIriFromResourceInSection($promotion, 'admin'),
'promotion.code',
$promotion->getCode(),
);
$this->client->filter();
}
/**
* @When I filter by code containing :phrase
*/
public function iFilterByCodeContaining(string $phrase): void
{
$this->client->index(Resources::PROMOTION_COUPONS);
$this->client->addFilter(
'code',
$phrase,
);
$this->client->filter();
}
@ -632,6 +645,26 @@ final class ManagingPromotionCouponsContext implements Context
);
}
/**
* @Then I should see a single promotion coupon in the list
*/
public function iShouldSeeASinglePromotionCouponInTheList(): void
{
Assert::same($this->responseChecker->countCollectionItems($this->client->getLastResponse()), 1);
}
/**
* @Then I should see the promotion coupon :coupon in the list
*/
public function iShouldSeeThePromotionCouponInTheList(PromotionCouponInterface $coupon): void
{
Assert::true($this->responseChecker->hasItemWithValue(
$this->client->getLastResponse(),
'code',
$coupon->getCode(),
));
}
private function sortBy(string $order, string $field): void
{
$this->client->sort([$field => str_starts_with($order, 'de') ? 'desc' : 'asc']);

View file

@ -1,88 +0,0 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Sylius Sp. z o.o.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Sylius\Bundle\ApiBundle\Doctrine\ORM\Filters;
use ApiPlatform\Api\IriConverterInterface;
use ApiPlatform\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
final class PromotionCouponPromotionFilter extends AbstractFilter
{
public const PROPERTY = 'promotion';
/** @param array<array-key, mixed> $properties */
public function __construct(
private IriConverterInterface $iriConverter,
ManagerRegistry $managerRegistry,
?RequestStack $requestStack = null,
?LoggerInterface $logger = null,
?array $properties = null,
?NameConverterInterface $nameConverter = null,
) {
parent::__construct($managerRegistry, $requestStack, $logger, $properties, $nameConverter);
}
protected function filterProperty(
string $property,
$value,
QueryBuilder $queryBuilder,
QueryNameGeneratorInterface $queryNameGenerator,
string $resourceClass,
?Operation $operation = null,
array $context = [],
): void {
if (self::PROPERTY !== $property) {
return;
}
$promotion = $this->iriConverter->getResourceFromIri($value);
$parameterName = $queryNameGenerator->generateParameterName(':promotion');
$promotionJoinAlias = $queryNameGenerator->generateJoinAlias('promotion');
$rootAlias = $queryBuilder->getRootAliases()[0];
$queryBuilder
->innerJoin(
sprintf('%s.promotion', $rootAlias),
$promotionJoinAlias,
Join::WITH,
$queryBuilder->expr()->eq(sprintf('%s.id', $promotionJoinAlias), $parameterName),
)
->setParameter($parameterName, $promotion)
;
}
/** @return array<string, mixed> */
public function getDescription(string $resourceClass): array
{
return [
self::PROPERTY => [
'type' => 'string',
'required' => false,
'property' => null,
'description' => 'Get a collection of promotion coupons for promotion',
'schema' => [
'type' => 'string',
],
],
];
}
}

View file

@ -21,7 +21,7 @@
<operation class="ApiPlatform\Metadata\GetCollection" uriTemplate="/admin/promotion-coupons">
<filters>
<filter>sylius.api.order_filter.promotion_coupon</filter>
<filter>sylius_api.doctrine.orm.filter.promotion_coupon_promotion</filter>
<filter>sylius_api.search_filter.promotion_coupon</filter>
</filters>
<order>

View file

@ -314,6 +314,14 @@
<!-- <tag name="api_platform.filter" />-->
<!-- </service>-->
<service id="sylius_api.search_filter.promotion_coupon" parent="api_platform.doctrine.orm.search_filter" public="true">
<argument type="collection">
<argument key="code">exact</argument>
<argument key="promotion.code">exact</argument>
</argument>
<tag name="api_platform.filter" />
</service>
<service id="sylius_api.search_filter.promotion" parent="api_platform.doctrine.orm.search_filter" public="true">
<argument type="collection">
<argument key="coupons.code">exact</argument>
@ -339,12 +347,6 @@
<tag name="api_platform.filter" />
</service>
<service id="sylius_api.doctrine.orm.filter.promotion_coupon_promotion" class="Sylius\Bundle\ApiBundle\Doctrine\ORM\Filters\PromotionCouponPromotionFilter" public="true">
<argument type="service" id="api_platform.symfony.iri_converter" />
<argument type="service" id="doctrine" />
<tag name="api_platform.filter" />
</service>
<service id="sylius.api.search_filter.product.code" parent="api_platform.doctrine.orm.search_filter" public="true">
<argument type="collection">
<argument key="product.code">exact</argument>

View file

@ -33,7 +33,7 @@
"hydra:totalItems": 2,
"hydra:search": {
"@type": "hydra:IriTemplate",
"hydra:template": "\/api\/v2\/admin\/promotion-coupons{?order[code],order[expiresAt],order[usageLimit],order[perCustomerUsageLimit],order[used],promotion}",
"hydra:template": "\/api\/v2\/admin\/promotion-coupons{?order[code],order[expiresAt],order[usageLimit],order[perCustomerUsageLimit],order[used],code,code[],promotion.code,promotion.code[]}",
"hydra:variableRepresentation": "BasicRepresentation",
"hydra:mapping": [
{
@ -68,8 +68,26 @@
},
{
"@type": "IriTemplateMapping",
"variable": "promotion",
"property": null,
"variable": "code",
"property": "code",
"required": false
},
{
"@type": "IriTemplateMapping",
"variable": "code[]",
"property": "code",
"required": false
},
{
"@type": "IriTemplateMapping",
"variable": "promotion.code",
"property": "promotion.code",
"required": false
},
{
"@type": "IriTemplateMapping",
"variable": "promotion.code[]",
"property": "promotion.code",
"required": false
}
]