[Api][Admin] Add recursively return adjustments for order item

This commit is contained in:
Wojdylak 2024-02-21 12:31:19 +01:00
parent e6b3789477
commit 0146289e2b
No known key found for this signature in database
GPG key ID: 7509E560A6821ABE
6 changed files with 209 additions and 26 deletions

View file

@ -920,31 +920,6 @@ parameters:
count: 1
path: src/Sylius/Bundle/ApiBundle/DataProvider/OrderAdjustmentsSubresourceDataProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataProvider\\\\OrderItemAdjustmentsSubresourceDataProvider\\:\\:__construct\\(\\) has parameter \\$orderItemRepository with generic interface Sylius\\\\Component\\\\Order\\\\Repository\\\\OrderItemRepositoryInterface but does not specify its types\\: T$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataProvider/OrderItemAdjustmentsSubresourceDataProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataProvider\\\\OrderItemAdjustmentsSubresourceDataProvider\\:\\:getSubresource\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataProvider/OrderItemAdjustmentsSubresourceDataProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataProvider\\\\OrderItemAdjustmentsSubresourceDataProvider\\:\\:getSubresource\\(\\) has parameter \\$identifiers with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataProvider/OrderItemAdjustmentsSubresourceDataProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataProvider\\\\OrderItemAdjustmentsSubresourceDataProvider\\:\\:getSubresource\\(\\) return type has no value type specified in iterable type iterable\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataProvider/OrderItemAdjustmentsSubresourceDataProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataProvider\\\\OrderItemAdjustmentsSubresourceDataProvider\\:\\:supports\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
count: 1
path: src/Sylius/Bundle/ApiBundle/DataProvider/OrderItemAdjustmentsSubresourceDataProvider.php
-
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\DataProvider\\\\OrderItemItemDataProvider\\:\\:__construct\\(\\) has parameter \\$orderItemRepository with generic interface Sylius\\\\Component\\\\Core\\\\Repository\\\\OrderItemRepositoryInterface but does not specify its types\\: T$#"
count: 1

View file

@ -0,0 +1,60 @@
<?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\DataProvider;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface;
use Sylius\Bundle\ApiBundle\SectionResolver\AdminApiSection;
use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Order\Model\AdjustmentInterface;
use Sylius\Component\Order\Repository\OrderItemRepositoryInterface;
use Webmozart\Assert\Assert;
/** @experimental */
final class AdminOrderItemAdjustmentsSubresourceDataProvider implements RestrictedDataProviderInterface, SubresourceDataProviderInterface
{
/** @param OrderItemRepositoryInterface<OrderItemInterface> $orderItemRepository */
public function __construct(
private readonly OrderItemRepositoryInterface $orderItemRepository,
private readonly SectionProviderInterface $sectionProvider,
) {
}
/** @param array<array-key, mixed> $context */
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return
is_a($resourceClass, AdjustmentInterface::class, true) &&
$this->sectionProvider->getSection() instanceof AdminApiSection &&
is_a(array_key_first($context['subresource_resources']), OrderItemInterface::class, true)
;
}
/**
* @param array<array-key, mixed> $identifiers
* @param array<array-key, mixed> $context
*
* @return iterable<AdjustmentInterface>
*/
public function getSubresource(string $resourceClass, array $identifiers, array $context, string $operationName = null): iterable
{
$orderItem = $this->orderItemRepository->find(reset($context['subresource_identifiers']));
if (null === $orderItem) {
return [];
}
return $orderItem->getAdjustmentsRecursively();
}
}

View file

@ -110,5 +110,11 @@
<service id="Sylius\Bundle\ApiBundle\DataProvider\VerifyCustomerAccountItemDataProvider">
<tag name="api_platform.item_data_provider" priority="10" />
</service>
<service id="Sylius\Bundle\ApiBundle\DataProvider\AdminOrderItemAdjustmentsSubresourceDataProvider">
<argument type="service" id="sylius.repository.order_item" />
<argument type="service" id="sylius.section_resolver.uri_based_section_resolver" />
<tag name="api_platform.subresource_data_provider" priority="10" />
</service>
</services>
</container>

View file

@ -0,0 +1,120 @@
<?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 spec\Sylius\Bundle\ApiBundle\DataProvider;
use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\SectionResolver\AdminApiSection;
use Sylius\Bundle\ApiBundle\SectionResolver\ShopApiSection;
use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Repository\OrderItemRepositoryInterface;
use Sylius\Component\Order\Model\AdjustmentInterface;
use Sylius\Component\Order\Model\OrderInterface;
use Symfony\Component\HttpFoundation\Request;
final class AdminOrderItemAdjustmentsSubresourceDataProviderSpec extends ObjectBehavior
{
function let(
OrderItemRepositoryInterface $orderItemRepository,
SectionProviderInterface $sectionProvider,
): void {
$this->beConstructedWith($orderItemRepository, $sectionProvider);
}
function it_does_not_support_not_adjustment_resource(): void {
$this
->supports(ProductInterface::class, Request::METHOD_GET, [])
->shouldReturn(false)
;
}
function it_does_not_support_in_shop_api_section(
SectionProviderInterface $sectionProvider,
ShopApiSection $shopApiSection
): void {
$sectionProvider->getSection()->willReturn($shopApiSection);
$this
->supports(AdjustmentInterface::class, Request::METHOD_GET, [])
->shouldReturn(false)
;
}
function it_does_not_support_not_order_item_subresource(
SectionProviderInterface $sectionProvider,
AdminApiSection $adminApiSection,
): void {
$sectionProvider->getSection()->willReturn($adminApiSection);
$context['subresource_resources'] = [
ProductInterface::class => ['id' => 2],
];
$this
->supports(AdjustmentInterface::class, Request::METHOD_GET, $context)
->shouldReturn(false)
;
}
function it_supports_order_item_adjustments_subresource_in_admin_api_section(
SectionProviderInterface $sectionProvider,
AdminApiSection $adminApiSection,
): void {
$sectionProvider->getSection()->willReturn($adminApiSection);
$context['subresource_resources'] = [
OrderItemInterface::class => ['id' => 2],
];
$this
->supports(AdjustmentInterface::class, Request::METHOD_GET, $context)
->shouldReturn(true)
;
}
function it_providers_empty_array_if_order_item_does_not_exist(
OrderItemRepositoryInterface $orderItemRepository,
): void {
$context['subresource_identifiers'] = ['id' => '11'];
$orderItemRepository->find('11')->willReturn(null);
$this
->getSubresource(AdjustmentInterface::class, [], $context, Request::METHOD_GET)
->shouldReturn([]);
}
function it_returns_order_item_adjustments(
OrderItemRepositoryInterface $orderItemRepository,
OrderItemInterface $orderItem,
AdjustmentInterface $adjustment1,
AdjustmentInterface $adjustment2,
): void
{
$context['subresource_identifiers'] = ['id' => '11'];
$orderItemRepository->find('11')->willReturn($orderItem);
$orderItem->getAdjustmentsRecursively()->willReturn(
new ArrayCollection([$adjustment1->getWrappedObject(), $adjustment2->getWrappedObject()])
);
$this
->getSubresource(
AdjustmentInterface::class,
[],
$context,
Request::METHOD_GET,
)
->shouldBeLike(new ArrayCollection([$adjustment1->getWrappedObject(), $adjustment2->getWrappedObject()]));
}
}

View file

@ -41,6 +41,12 @@ Sylius\Component\Core\Model\OrderItem:
order_item:
variant: "@product_variant"
order: "@order"
Sylius\Component\Core\Model\OrderItemUnit:
order_item_unit:
__construct: ['@order_item']
createdAt: "<(new \\DateTime())>"
updatedAt: "<(new \\DateTime())>"
Sylius\Component\Core\Model\Adjustment:
adjustment_1:
@ -51,3 +57,11 @@ Sylius\Component\Core\Model\Adjustment:
adjustable: '@order_item'
createdAt: "<(new \\DateTime())>"
updatedAt: "<(new \\DateTime())>"
adjustment_2:
type: order_promotion
label: New Year
amount: -500
neutral: false
adjustable: '@order_item_unit'
createdAt: "<(new \\DateTime())>"
updatedAt: "<(new \\DateTime())>"

View file

@ -10,7 +10,15 @@
"amount": 1000,
"neutral": false,
"locked": false
},
{
"@id": "\/api\/v2\/admin\/adjustments\/@integer@",
"@type": "Adjustment",
"type": "order_promotion",
"amount": -500,
"neutral": false,
"locked": false
}
],
"hydra:totalItems": 1
"hydra:totalItems": 2
}