Skip to content

Commit 928a7de

Browse files
authored
Merge pull request #130 from mattgoud/bulk-enable-disable-delete-discount
Bulk enable disable delete discount
2 parents 9b22f4e + 5788128 commit 928a7de

File tree

3 files changed

+280
-0
lines changed

3 files changed

+280
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
/**
3+
* Copyright since 2007 PrestaShop SA and Contributors
4+
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
5+
*
6+
* NOTICE OF LICENSE
7+
*
8+
* This source file is subject to the Academic Free License version 3.0
9+
* that is bundled with this package in the file LICENSE.md.
10+
* It is also available through the world-wide-web at this URL:
11+
* https://opensource.org/licenses/AFL-3.0
12+
* If you did not receive a copy of the license and are unable to
13+
* obtain it through the world-wide-web, please send an email
14+
* to [email protected] so we can send you a copy immediately.
15+
*
16+
* @author PrestaShop SA and Contributors <[email protected]>
17+
* @copyright Since 2007 PrestaShop SA and Contributors
18+
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
19+
*/
20+
21+
namespace PrestaShop\Module\APIResources\ApiPlatform\Resources\Discount;
22+
23+
use ApiPlatform\Metadata\ApiProperty;
24+
use ApiPlatform\Metadata\ApiResource;
25+
use PrestaShop\PrestaShop\Core\Domain\Discount\Command\BulkDeleteDiscountsCommand;
26+
use PrestaShop\PrestaShop\Core\Domain\Discount\Exception\BulkDiscountException;
27+
use PrestaShop\PrestaShop\Core\Domain\Discount\Exception\DiscountConstraintException;
28+
use PrestaShop\PrestaShop\Core\Domain\Discount\Exception\DiscountNotFoundException;
29+
use PrestaShopBundle\ApiPlatform\Metadata\CQRSDelete;
30+
use Symfony\Component\HttpFoundation\Response;
31+
use Symfony\Component\Validator\Constraints as Assert;
32+
33+
#[ApiResource(
34+
operations: [
35+
new CQRSDelete(
36+
uriTemplate: '/discounts/bulk-delete',
37+
CQRSCommand: BulkDeleteDiscountsCommand::class,
38+
scopes: [
39+
'discount_write',
40+
],
41+
allowEmptyBody: false,
42+
openapiContext: [
43+
'requestBody' => [
44+
'content' => [
45+
'application/json' => [
46+
'schema' => [
47+
'type' => 'object',
48+
'properties' => [
49+
'discountIds' => [
50+
'type' => 'array',
51+
'items' => ['type' => 'integer'],
52+
],
53+
],
54+
],
55+
'example' => [
56+
'discountIds' => [1, 3],
57+
],
58+
],
59+
],
60+
],
61+
],
62+
),
63+
],
64+
exceptionToStatus: [
65+
DiscountNotFoundException::class => Response::HTTP_NOT_FOUND,
66+
DiscountConstraintException::class => Response::HTTP_UNPROCESSABLE_ENTITY,
67+
BulkDiscountException::class => Response::HTTP_UNPROCESSABLE_ENTITY,
68+
],
69+
)]
70+
class BulkDeleteDiscounts
71+
{
72+
/**
73+
* @var int[]
74+
*/
75+
#[ApiProperty(openapiContext: ['type' => 'array', 'items' => ['type' => 'integer'], 'example' => [1, 3]])]
76+
#[Assert\NotBlank]
77+
public array $discountIds;
78+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
/**
3+
* Copyright since 2007 PrestaShop SA and Contributors
4+
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
5+
*
6+
* NOTICE OF LICENSE
7+
*
8+
* This source file is subject to the Academic Free License version 3.0
9+
* that is bundled with this package in the file LICENSE.md.
10+
* It is also available through the world-wide-web at this URL:
11+
* https://opensource.org/licenses/AFL-3.0
12+
* If you did not receive a copy of the license and are unable to
13+
* obtain it through the world-wide-web, please send an email
14+
* to [email protected] so we can send you a copy immediately.
15+
*
16+
* @author PrestaShop SA and Contributors <[email protected]>
17+
* @copyright Since 2007 PrestaShop SA and Contributors
18+
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
19+
*/
20+
21+
namespace PrestaShop\Module\APIResources\ApiPlatform\Resources\Discount;
22+
23+
use ApiPlatform\Metadata\ApiProperty;
24+
use ApiPlatform\Metadata\ApiResource;
25+
use PrestaShop\PrestaShop\Core\Domain\Discount\Command\BulkUpdateDiscountsStatusCommand;
26+
use PrestaShop\PrestaShop\Core\Domain\Discount\Exception\BulkDiscountException;
27+
use PrestaShop\PrestaShop\Core\Domain\Discount\Exception\DiscountNotFoundException;
28+
use PrestaShopBundle\ApiPlatform\Metadata\CQRSPartialUpdate;
29+
use Symfony\Component\HttpFoundation\Response;
30+
use Symfony\Component\Validator\Constraints as Assert;
31+
32+
#[ApiResource(
33+
operations: [
34+
new CQRSPartialUpdate(
35+
uriTemplate: '/discounts/bulk-update-status',
36+
output: false,
37+
CQRSCommand: BulkUpdateDiscountsStatusCommand::class,
38+
CQRSCommandMapping: [
39+
'[enabled]' => '[newStatus]',
40+
],
41+
scopes: [
42+
'discount_write',
43+
],
44+
),
45+
],
46+
exceptionToStatus: [
47+
DiscountNotFoundException::class => Response::HTTP_NOT_FOUND,
48+
BulkDiscountException::class => Response::HTTP_UNPROCESSABLE_ENTITY,
49+
],
50+
)]
51+
class BulkUpdateStatusDiscounts
52+
{
53+
/**
54+
* @var int[]
55+
*/
56+
#[ApiProperty(openapiContext: ['type' => 'array', 'items' => ['type' => 'integer'], 'example' => [1, 3]])]
57+
#[Assert\NotBlank]
58+
public array $discountIds;
59+
60+
public bool $enabled;
61+
}

tests/Integration/ApiPlatform/DiscountEndpointTest.php

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
namespace PsApiResourcesTest\Integration\ApiPlatform;
2424

2525
use PrestaShop\PrestaShop\Core\Domain\Discount\Command\AddDiscountCommand;
26+
use Symfony\Component\HttpFoundation\Response;
2627
use Tests\Resources\DatabaseDump;
2728
use Tests\Resources\Resetter\LanguageResetter;
2829

@@ -248,6 +249,16 @@ public static function getProtectedEndpoints(): iterable
248249
'PATCH',
249250
'/discounts/1/conditions',
250251
];
252+
253+
yield 'bulk toggle status endpoint' => [
254+
'PATCH',
255+
'/discounts/bulk-update-status',
256+
];
257+
258+
yield 'bulk delete endpoint' => [
259+
'DELETE',
260+
'/discounts/bulk-delete',
261+
];
251262
}
252263

253264
/**
@@ -434,4 +445,134 @@ public function testGetUpdatedDiscountConditions(int $discountId): void
434445

435446
$this->addToAssertionCount(1);
436447
}
448+
449+
/**
450+
* Test bulk enable discounts
451+
*/
452+
public function testBulkEnableDiscounts(): array
453+
{
454+
// Create multiple discounts for bulk testing
455+
$discountIds = [];
456+
for ($i = 0; $i < 3; ++$i) {
457+
$discount = $this->createItem('/discounts', [
458+
'type' => self::CART_LEVEL,
459+
'names' => [
460+
'en-US' => 'Bulk test discount ' . $i,
461+
'fr-FR' => 'Discount test bulk ' . $i,
462+
],
463+
], ['discount_write']);
464+
$discountIds[] = $discount['discountId'];
465+
}
466+
467+
// Bulk enable all discounts
468+
$this->partialUpdateItem('/discounts/bulk-update-status', [
469+
'discountIds' => $discountIds,
470+
'enabled' => true,
471+
], ['discount_write'], Response::HTTP_NO_CONTENT);
472+
473+
// Verify all discounts are enabled
474+
foreach ($discountIds as $discountId) {
475+
$discount = $this->getItem('/discounts/' . $discountId, ['discount_read']);
476+
$this->assertTrue($discount['enabled'], "Discount {$discountId} should be enabled");
477+
}
478+
479+
return $discountIds;
480+
}
481+
482+
/**
483+
* @depends testBulkEnableDiscounts
484+
*
485+
* Test bulk disable discounts
486+
*/
487+
public function testBulkDisableDiscounts(array $discountIds): array
488+
{
489+
// Bulk disable all discounts
490+
$this->partialUpdateItem('/discounts/bulk-update-status', [
491+
'discountIds' => $discountIds,
492+
'enabled' => false,
493+
], ['discount_write'], Response::HTTP_NO_CONTENT);
494+
495+
// Verify all discounts are disabled
496+
foreach ($discountIds as $discountId) {
497+
$discount = $this->getItem('/discounts/' . $discountId, ['discount_read']);
498+
$this->assertFalse($discount['enabled'], "Discount {$discountId} should be disabled");
499+
}
500+
501+
return $discountIds;
502+
}
503+
504+
/**
505+
* @depends testBulkDisableDiscounts
506+
*
507+
* Test bulk delete discounts
508+
*/
509+
public function testBulkDeleteDiscounts(array $discountIds): void
510+
{
511+
// Bulk delete all discounts
512+
$this->bulkDeleteItems('/discounts/bulk-delete', [
513+
'discountIds' => $discountIds,
514+
], ['discount_write'], Response::HTTP_NO_CONTENT);
515+
516+
// Verify all discounts are deleted
517+
foreach ($discountIds as $discountId) {
518+
$this->getItem('/discounts/' . $discountId, ['discount_read'], 404);
519+
}
520+
}
521+
522+
/**
523+
* Test bulk enable with mixed valid and invalid IDs
524+
*/
525+
public function testBulkEnableWithInvalidIds(): void
526+
{
527+
// Create one valid discount
528+
$discount = $this->createItem('/discounts', [
529+
'type' => self::CART_LEVEL,
530+
'names' => [
531+
'en-US' => 'Valid discount',
532+
'fr-FR' => 'Discount valide',
533+
],
534+
], ['discount_write']);
535+
$validId = $discount['discountId'];
536+
537+
// Try to bulk enable with mixed valid and invalid IDs
538+
$this->partialUpdateItem('/discounts/bulk-update-status', [
539+
'discountIds' => [$validId, 999999],
540+
'enabled' => true,
541+
], ['discount_write'], 422);
542+
}
543+
544+
/**
545+
* Test bulk delete with empty array
546+
*/
547+
public function testBulkDeleteWithEmptyArray(): void
548+
{
549+
$this->bulkDeleteItems('/discounts/bulk-delete', [
550+
'discountIds' => [],
551+
], ['discount_write'], 422);
552+
}
553+
554+
/**
555+
* Test bulk toggle status with empty array
556+
*/
557+
public function testBulkToggleStatusWithEmptyArray(): void
558+
{
559+
$this->partialUpdateItem('/discounts/bulk-update-status', [
560+
'discountIds' => [],
561+
'enabled' => true,
562+
], ['discount_write'], 422);
563+
}
564+
565+
/**
566+
* Test bulk delete without providing discountIds parameter
567+
*/
568+
public function testBulkDeleteWithMissingParameter(): void
569+
{
570+
$bearerToken = $this->getBearerToken(['discount_write']);
571+
static::createClient()->request('DELETE', '/discounts/bulk-delete', [
572+
'auth_bearer' => $bearerToken,
573+
'json' => [],
574+
]);
575+
576+
self::assertResponseStatusCodeSame(422);
577+
}
437578
}

0 commit comments

Comments
 (0)