Skip to content

Commit 4686000

Browse files
mnoconadriendupuis
andcommitted
[Discounts] REST API (#2780)
* [Discounts] Described Discounts API (#2783) * [Discounts] Configuration (#2781) --------- Co-authored-by: Adrien Dupuis <[email protected]>
1 parent 4084b38 commit 4686000

22 files changed

+4426
-27
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Command;
6+
7+
use DateTimeImmutable;
8+
use Ibexa\Contracts\Core\Collection\ArrayMap;
9+
use Ibexa\Contracts\Core\Repository\PermissionResolver;
10+
use Ibexa\Contracts\Core\Repository\UserService;
11+
use Ibexa\Contracts\Discounts\DiscountServiceInterface;
12+
use Ibexa\Contracts\Discounts\Value\DiscountType;
13+
use Ibexa\Contracts\Discounts\Value\Struct\DiscountCreateStruct;
14+
use Ibexa\Contracts\Discounts\Value\Struct\DiscountTranslationStruct;
15+
use Ibexa\Contracts\DiscountsCodes\DiscountCodeServiceInterface;
16+
use Ibexa\Contracts\DiscountsCodes\Value\Struct\DiscountCodeCreateStruct;
17+
use Ibexa\Discounts\Value\DiscountCondition\IsInCurrency;
18+
use Ibexa\Discounts\Value\DiscountCondition\IsInRegions;
19+
use Ibexa\Discounts\Value\DiscountCondition\IsProductInArray;
20+
use Ibexa\Discounts\Value\DiscountRule\FixedAmount;
21+
use Ibexa\DiscountsCodes\Value\DiscountCondition\IsValidDiscountCode;
22+
use Symfony\Component\Console\Command\Command;
23+
use Symfony\Component\Console\Input\InputInterface;
24+
use Symfony\Component\Console\Output\OutputInterface;
25+
26+
final class ManageDiscountsCommand extends Command
27+
{
28+
protected static $defaultName = 'discounts:manage';
29+
30+
private DiscountServiceInterface $discountService;
31+
32+
private DiscountCodeServiceInterface $discountCodeService;
33+
34+
private PermissionResolver $permissionResolver;
35+
36+
private UserService $userService;
37+
38+
public function __construct(
39+
UserService $userSerice,
40+
PermissionResolver $permissionResolver,
41+
DiscountServiceInterface $discountService,
42+
DiscountCodeServiceInterface $discountCodeService
43+
) {
44+
$this->userService = $userSerice;
45+
$this->discountService = $discountService;
46+
$this->discountCodeService = $discountCodeService;
47+
$this->permissionResolver = $permissionResolver;
48+
49+
parent::__construct();
50+
}
51+
52+
protected function execute(InputInterface $input, OutputInterface $output): int
53+
{
54+
$this->permissionResolver->setCurrentUserReference(
55+
$this->userService->loadUserByLogin('admin')
56+
);
57+
58+
$now = new DateTimeImmutable();
59+
60+
$discountCodeCreateStruct = new DiscountCodeCreateStruct(
61+
'summer10',
62+
null, // Unlimited usage
63+
$this->permissionResolver->getCurrentUserReference()->getUserId(),
64+
$now
65+
);
66+
$discountCode = $this->discountCodeService->createDiscountCode($discountCodeCreateStruct);
67+
68+
$discountCreateStruct = new DiscountCreateStruct();
69+
$discountCreateStruct
70+
->setIdentifier('discount_identifier')
71+
->setType(DiscountType::CART)
72+
->setPriority(10)
73+
->setEnabled(true)
74+
->setUser($this->userService->loadUserByLogin('admin'))
75+
->setRule(new FixedAmount(10))
76+
->setStartDate($now)
77+
->setConditions([
78+
new IsInRegions(['germany', 'france']),
79+
new IsProductInArray(['product-1', 'product-2']),
80+
new IsInCurrency('EUR'),
81+
new IsValidDiscountCode($discountCode->getCode(), $discountCode->getUsedLimit()),
82+
])
83+
->setTranslations([
84+
new DiscountTranslationStruct('eng-GB', 'Discount name', 'This is a discount description', 'Promotion Label', 'Promotion Description'),
85+
new DiscountTranslationStruct('ger-DE', 'Discount name (German)', 'Description (German)', 'Promotion Label (German)', 'Promotion Description (German)'),
86+
])
87+
->setEndDate(null) // Permanent discount
88+
->setCreatedAt($now)
89+
->setUpdatedAt($now)
90+
->setContext(new ArrayMap(['custom_context' => 'custom_value']));
91+
92+
$this->discountService->createDiscount($discountCreateStruct);
93+
94+
return Command::SUCCESS;
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"DiscountCode": {
3+
"code": "summer10"
4+
}
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"DiscountCode": {
3+
"_media-type": "application\/vnd.ibexa.api.DiscountCode+json",
4+
"id": 1,
5+
"code": "summer10",
6+
"created_at": {
7+
"date": "2025-06-10 14:14:06.000000",
8+
"timezone_type": 3,
9+
"timezone": "UTC"
10+
}
11+
}
12+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"Discount": {
3+
"_media-type": "application/vnd.ibexa.api.Discount+json",
4+
"id": 1,
5+
"identifier": "summersale2025",
6+
"name": "SummerSale2025",
7+
"type": "catalog",
8+
"label": "Summer Sale 2025",
9+
"labelDescription": "Summer Sale 2025",
10+
"priority": 1,
11+
"isEnabled": true,
12+
"createdAt": "2025-06-10T09:43:42+00:00",
13+
"updatedAt": "2025-06-10T09:48:23+00:00",
14+
"startDate": "2025-07-01T09:34:19+00:00",
15+
"endDate": "2025-07-31T12:00:00+00:00",
16+
"DiscountExpressionAware": {
17+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
18+
"expressionValues": {
19+
"discount_amount": "10"
20+
}
21+
},
22+
"DiscountConditions": [
23+
{
24+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
25+
"expressionValues": {
26+
"currency_code": "USD"
27+
}
28+
}
29+
],
30+
"DiscountTranslations": [
31+
{
32+
"_media-type": "application/vnd.ibexa.api.DiscountTranslation+json",
33+
"languageCode": {},
34+
"name": "SummerSale2025",
35+
"description": null,
36+
"label": "Summer Sale 2025",
37+
"labelDescription": "Summer Sale 2025"
38+
}
39+
]
40+
},
41+
"isDiscountCodeAware": {
42+
"_media-type": "application/vnd.ibexa.api.isDiscountCodeAware+json",
43+
"isDiscountCodeAware": false
44+
}
45+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
{
2+
"DiscountList": {
3+
"_media-type": "application/vnd.ibexa.api.DiscountList+json",
4+
"Discount": [
5+
{
6+
"_media-type": "application/vnd.ibexa.api.Discount+json",
7+
"id": 1,
8+
"identifier": "summersale2025",
9+
"name": "SummerSale2025",
10+
"type": "catalog",
11+
"label": "Summer Sale 2025",
12+
"labelDescription": "Summer Sale 2025",
13+
"priority": 1,
14+
"isEnabled": true,
15+
"createdAt": "2025-06-10T09:43:42+00:00",
16+
"updatedAt": "2025-06-10T09:48:23+00:00",
17+
"startDate": "2025-07-01T09:34:19+00:00",
18+
"endDate": "2025-07-31T12:00:00+00:00",
19+
"DiscountExpressionAware": {
20+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
21+
"expressionValues": {
22+
"discount_amount": "10"
23+
}
24+
},
25+
"DiscountConditions": [
26+
{
27+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
28+
"expressionValues": {
29+
"currency_code": "USD"
30+
}
31+
}
32+
],
33+
"DiscountTranslations": [
34+
{
35+
"_media-type": "application/vnd.ibexa.api.DiscountTranslation+json",
36+
"languageCode": {},
37+
"name": "SummerSale2025",
38+
"description": null,
39+
"label": "Summer Sale 2025",
40+
"labelDescription": "Summer Sale 2025"
41+
}
42+
]
43+
},
44+
{
45+
"_media-type": "application/vnd.ibexa.api.isDiscountCodeAware+json",
46+
"isDiscountCodeAware": false
47+
},
48+
{
49+
"_media-type": "application/vnd.ibexa.api.Discount+json",
50+
"id": 2,
51+
"identifier": "my_discount",
52+
"name": "Another discount",
53+
"type": "cart",
54+
"label": "another",
55+
"labelDescription": "another label description",
56+
"priority": 10,
57+
"isEnabled": false,
58+
"createdAt": "2025-06-10T11:03:37+00:00",
59+
"updatedAt": "2025-06-10T14:14:06+00:00",
60+
"startDate": "2025-04-01T12:12:12+00:00",
61+
"DiscountExpressionAware": {
62+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
63+
"expressionValues": {
64+
"discount_percentage": "10"
65+
}
66+
},
67+
"DiscountConditions": [
68+
{
69+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
70+
"expressionValues": {
71+
"discount_code": "my_secret_code",
72+
"usage_count": 1
73+
}
74+
},
75+
{
76+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
77+
"expressionValues": {
78+
"categories": [
79+
1,
80+
3
81+
]
82+
}
83+
}
84+
],
85+
"DiscountTranslations": [
86+
{
87+
"_media-type": "application/vnd.ibexa.api.DiscountTranslation+json",
88+
"languageCode": {},
89+
"name": "Another discount",
90+
"description": "another great discount",
91+
"label": "another",
92+
"labelDescription": "another label description"
93+
}
94+
]
95+
},
96+
{
97+
"_media-type": "application/vnd.ibexa.api.isDiscountCodeAware+json",
98+
"isDiscountCodeAware": true
99+
}
100+
]
101+
}
102+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"DiscountCreate": {
3+
"identifier": "my_discount",
4+
"type": "cart",
5+
"priority": 10,
6+
"isEnabled": true,
7+
"userId": 14,
8+
"rule": {
9+
"type": "percentage",
10+
"amount": 10
11+
},
12+
"startDate": "2025-04-01 12:12:12",
13+
"translations": [
14+
{
15+
"languageCode": "eng-GB",
16+
"name": "Another discount",
17+
"description": "another great discount",
18+
"label": "another",
19+
"labelDescription": "another label description"
20+
}
21+
],
22+
"conditions": [
23+
{
24+
"class": "Ibexa\\Discounts\\Value\\DiscountCondition\\IsInCategory",
25+
"parameters": [["1", "2"]]
26+
}
27+
]
28+
}
29+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"Discount": {
3+
"_media-type": "application/vnd.ibexa.api.Discount+json",
4+
"id": 2,
5+
"identifier": "my_discount",
6+
"name": "Another discount",
7+
"type": "cart",
8+
"label": "another",
9+
"labelDescription": "another label description",
10+
"priority": 10,
11+
"isEnabled": true,
12+
"createdAt": "2025-06-10T11:03:37+00:00",
13+
"updatedAt": "2025-06-10T11:03:37+00:00",
14+
"startDate": "2025-04-01T12:12:12+00:00",
15+
"DiscountExpressionAware": {
16+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
17+
"expressionValues": {
18+
"discount_percentage": "10"
19+
}
20+
},
21+
"DiscountConditions": [
22+
{
23+
"_media-type": "application/vnd.ibexa.api.DiscountExpressionAware+json",
24+
"expressionValues": {
25+
"categories": [
26+
"1",
27+
"2"
28+
]
29+
}
30+
}
31+
],
32+
"DiscountTranslations": [
33+
{
34+
"_media-type": "application/vnd.ibexa.api.DiscountTranslation+json",
35+
"languageCode": {},
36+
"name": "Another discount",
37+
"description": "another great discount",
38+
"label": "another",
39+
"labelDescription": "another label description"
40+
}
41+
]
42+
},
43+
"isDiscountCodeAware": {
44+
"_media-type": "application/vnd.ibexa.api.isDiscountCodeAware+json",
45+
"isDiscountCodeAware": false
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"DiscountUpdate": {
3+
"identifier": "my_discount",
4+
"conditions": [
5+
{
6+
"class": "Ibexa\\Discounts\\Value\\DiscountCondition\\IsInCategory",
7+
"parameters": [["1", "3"]]
8+
}
9+
]
10+
}
11+
}

0 commit comments

Comments
 (0)