Skip to content

Commit 72385f6

Browse files
committed
chore(api) add discount enpoint
1 parent 6049c52 commit 72385f6

2 files changed

Lines changed: 268 additions & 0 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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 license@prestashop.com so we can send you a copy immediately.
15+
*
16+
* @author PrestaShop SA and Contributors <contact@prestashop.com>
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\Decimal\DecimalNumber;
26+
use PrestaShop\PrestaShop\Core\Domain\Discount\Command\AddDiscountCommand;
27+
use PrestaShop\PrestaShop\Core\Domain\Discount\Exception\DiscountConstraintException;
28+
use PrestaShop\PrestaShop\Core\Domain\Discount\Exception\DiscountNotFoundException;
29+
use PrestaShop\PrestaShop\Core\Domain\Discount\Query\GetDiscountForEditing;
30+
use PrestaShopBundle\ApiPlatform\Metadata\CQRSCreate;
31+
use PrestaShopBundle\ApiPlatform\Metadata\CQRSGet;
32+
use PrestaShopBundle\ApiPlatform\Metadata\LocalizedValue;
33+
use Symfony\Component\HttpFoundation\Response;
34+
35+
#[ApiResource(
36+
operations: [
37+
new CQRSGet(
38+
uriTemplate: '/discount/{discountId}',
39+
requirements: ['discountId' => '\d+'],
40+
CQRSQuery: GetDiscountForEditing::class,
41+
scopes: ['discount_read']
42+
),
43+
new CQRSCreate(
44+
uriTemplate: '/discount',
45+
validationContext: ['groups' => ['Default', 'Create']],
46+
CQRSCommand: AddDiscountCommand::class,
47+
CQRSQuery: GetDiscountForEditing::class,
48+
scopes: ['discount_write'],
49+
CQRSCommandMapping: [
50+
'[names]' => '[localizedNames]',
51+
],
52+
),
53+
],
54+
exceptionToStatus: [
55+
DiscountNotFoundException::class => Response::HTTP_NOT_FOUND,
56+
DiscountConstraintException::class => Response::HTTP_UNPROCESSABLE_ENTITY,
57+
],
58+
)]
59+
class Discount
60+
{
61+
#[ApiProperty(identifier: true)]
62+
public int $discountId;
63+
#[Assert\NotBlank(groups: ['Create'])]
64+
#[LocalizedValue]
65+
public array $names;
66+
public int $priority;
67+
public bool $active;
68+
public \DateTimeImmutable $validFrom;
69+
public \DateTimeImmutable $validTo;
70+
public int $totalQuantity;
71+
public int $quantityPerUser;
72+
public string $description;
73+
public string $code;
74+
public int $customerId;
75+
public bool $highlightInCart;
76+
public bool $allowPartialUse;
77+
#[Assert\NotBlank(groups: ['Create'])]
78+
public string $type;
79+
public ?DecimalNumber $percentDiscount;
80+
public ?DecimalNumber $amountDiscount;
81+
public int $currencyId;
82+
public bool $isTaxIncluded;
83+
public int $productId;
84+
public array $combinations;
85+
public int $reductionProduct;
86+
}
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
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 license@prestashop.com so we can send you a copy immediately.
15+
*
16+
* @author PrestaShop SA and Contributors <contact@prestashop.com>
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+
declare(strict_types=1);
22+
23+
namespace PsApiResourcesTest\Integration\ApiPlatform;
24+
25+
use PrestaShop\PrestaShop\Core\Domain\Discount\Command\AddDiscountCommand;
26+
use PrestaShop\PrestaShop\Core\Domain\Discount\Query\GetDiscountForEditing;
27+
use PrestaShop\PrestaShop\Core\Domain\Discount\ValueObject\DiscountType;
28+
use Tests\Resources\Resetter\LanguageResetter;
29+
30+
class DiscountEndpointTest extends ApiTestCase
31+
{
32+
public static function setUpBeforeClass(): void
33+
{
34+
parent::setUpBeforeClass();
35+
36+
LanguageResetter::resetLanguages();
37+
self::addLanguageByLocale('fr-FR');
38+
self::createApiClient(['discount_write', 'discount_read']);
39+
}
40+
41+
public static function tearDownAfterClass(): void
42+
{
43+
parent::tearDownAfterClass();
44+
45+
LanguageResetter::resetLanguages();
46+
}
47+
48+
/**
49+
* @dataProvider discountTypesDataProvider
50+
*
51+
* @param string $type
52+
* @param array $names
53+
*
54+
* @return int
55+
*/
56+
public function testAddDiscount(string $type, array $names, ?array $data): int
57+
{
58+
// skip test if class does not exist
59+
if (!class_exists(AddDiscountCommand::class)) {
60+
$this->markTestSkipped('AddDiscountCommand class does not exist');
61+
}
62+
63+
$bearerToken = $this->getBearerToken(['discount_write']);
64+
$json = [
65+
'type' => $type,
66+
'names' => $names,
67+
];
68+
if ($data !== null) {
69+
$json = array_merge($json, $data);
70+
}
71+
$response = static::createClient()->request('POST', '/discount', [
72+
'auth_bearer' => $bearerToken,
73+
'json' => $json,
74+
]);
75+
self::assertResponseStatusCodeSame(201);
76+
77+
$decodedResponse = json_decode($response->getContent(), true);
78+
$this->assertNotFalse($decodedResponse);
79+
$this->assertArrayHasKey('discountId', $decodedResponse);
80+
$discountId = $decodedResponse['discountId'];
81+
$this->assertArrayHasKey(
82+
'type',
83+
$decodedResponse
84+
);
85+
$this->assertEquals($type, $decodedResponse['type']);
86+
87+
return $discountId;
88+
}
89+
90+
public function discountTypesDataProvider(): array
91+
{
92+
return [
93+
[
94+
DiscountType::CART_LEVEL,
95+
[
96+
'en-US' => 'new cart level discount',
97+
'fr-FR' => 'nouveau discount panier',
98+
],
99+
null,
100+
],
101+
[
102+
DiscountType::PRODUCT_LEVEL,
103+
[
104+
'en-US' => 'new product level discount',
105+
'fr-FR' => 'nouveau discount produit',
106+
],
107+
[
108+
'reductionProduct' => -1,
109+
'percentDiscount' => 20.0,
110+
],
111+
],
112+
[
113+
DiscountType::FREE_GIFT,
114+
[
115+
'en-US' => 'new free gift discount',
116+
'fr-FR' => 'nouveau discount produit offert',
117+
],
118+
[
119+
'productId' => 1,
120+
],
121+
],
122+
[
123+
DiscountType::FREE_SHIPPING,
124+
[
125+
'en-US' => 'new free shipping discount',
126+
'fr-FR' => 'nouveau discount frais de port offert',
127+
],
128+
null,
129+
],
130+
[
131+
DiscountType::ORDER_LEVEL,
132+
[
133+
'en-US' => 'new order level discount',
134+
'fr-FR' => 'nouveau discount commande',
135+
],
136+
null,
137+
],
138+
];
139+
}
140+
141+
/**
142+
* @depends testAddDiscount
143+
*
144+
* @return int
145+
*/
146+
public function testGetDiscount(): void
147+
{
148+
// skip test if class does not exist
149+
if (!class_exists(GetDiscountForEditing::class)) {
150+
$this->markTestSkipped('GetDiscountForEditing class does not exist');
151+
}
152+
153+
$bearerToken = $this->getBearerToken(['discount_read']);
154+
$response = static::createClient()->request('GET', '/discount/1', [
155+
'auth_bearer' => $bearerToken,
156+
]);
157+
self::assertResponseStatusCodeSame(200);
158+
159+
$decodedResponse = json_decode($response->getContent(), true);
160+
161+
$this->assertNotFalse($decodedResponse);
162+
$this->assertArrayHasKey('discountId', $decodedResponse);
163+
$this->assertArrayHasKey(
164+
'type',
165+
$decodedResponse
166+
);
167+
$this->assertEquals('cart_level', $decodedResponse['type']);
168+
}
169+
170+
public function getProtectedEndpoints(): iterable
171+
{
172+
yield 'get endpoint' => [
173+
'GET',
174+
'/discount/1',
175+
];
176+
177+
yield 'create endpoint' => [
178+
'POST',
179+
'/discount',
180+
];
181+
}
182+
}

0 commit comments

Comments
 (0)