Skip to content

Discounts 4.6.22 #2810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: 4.6
Choose a base branch
from
Open

Discounts 4.6.22 #2810

wants to merge 9 commits into from

Conversation

mnocon
Copy link
Contributor

@mnocon mnocon commented Jul 2, 2025

Documentation for:

Discount priority:
https://github.com/ibexa/discounts/pull/266
https://github.com/ibexa/discounts-codes/pull/30
https://github.com/ibexa/installer/pull/183

Discount code migrations:
https://github.com/ibexa/discounts-codes/pull/28

Global discount codes:
https://github.com/ibexa/discounts-codes/pull/20

Mention about the TODOs:

  • We don't have the PHP API Reference classes for the new introduced concepts, I will have to add the links once the release is out and the API Ref is regenerated
  • The draft of release notes doesn't contain all the information yet

I'll wait with merging this PR until 4.6.22 is out.

@mnocon mnocon marked this pull request as ready for review July 2, 2025 15:55
Copy link

github-actions bot commented Jul 2, 2025

@mnocon mnocon requested a review from a team July 3, 2025 07:48
@ezrobot ezrobot requested review from adriendupuis, dabrt and julitafalcondusza and removed request for a team July 3, 2025 07:48
@mnocon mnocon added the Wait with merge PRs that shouldn't be merged instantly label Jul 3, 2025
@@ -522,6 +526,28 @@ To use the [latest features](ibexa_dxp_v4.6.md) added to them, update them separ
REFERENCES ezuser (contentobject_id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE;
```

## 4.6.22
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Seing how it ends up in the right ToC, I would change this one and the previous ones to decrease the heading level, give some context, and standardize:

Suggested change
## 4.6.22
### Discounts v4.6.22
     Then apply manually the changes described below.
 
-    ## 4.6.20
+    ### Discounts v4.6.20
 
-    ### Policy changes
+    #### Policy changes
 
     The `discount/view` policy is no longer required for the store customers to use a discount and must be removed from all users who are not managing discounts.
     The policy allows to access all the discount details, including the coupon codes to activate them, which could lead to system abuse.
 
     To learn more, see the [discounts policies overview](policies.md#discounts).
 
-    ### Database update
+    #### Database update
 
     Run the following scripts:
 
-    ## 4.6.22
+    ### Discounts v4.6.22
 
-    ### Database update
+    #### Database update
 
     Run the following scripts:

image


#### Global discount codes

- You can now [limit the number of times](discounts_guide.md#discount-codes) a discount code can be used before it expires
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the default value for discount codes created before the addition of this feature?

Comment on lines 45 to 50
#### Full changelog
[[% include 'snippets/release_46.md' %]]
[[= release_note_entry_end() =]]



Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#### Full changelog
[[% include 'snippets/release_46.md' %]]
[[= release_note_entry_end() =]]
#### Full changelog
[[% include 'snippets/release_46.md' %]]
[[= release_note_entry_end() =]]

@mnocon mnocon force-pushed the discounts-4.6.22 branch from 1975686 to a13c8d7 Compare July 3, 2025 10:05
@mnocon mnocon force-pushed the discounts-4.6.22 branch from a13c8d7 to a35c98c Compare July 3, 2025 10:07
@mnocon
Copy link
Contributor Author

mnocon commented Jul 3, 2025

Thank you @adriendupuis , review suggestions applied in a35c98c

@mnocon mnocon requested a review from adriendupuis July 3, 2025 10:07
Copy link

github-actions bot commented Jul 3, 2025

code_samples/ change report

Before (on target branch)After (in current PR)

code_samples/data_migration/examples/discounts/discount_code_create.yaml


code_samples/data_migration/examples/discounts/discount_code_create.yaml

docs/content_management/data_migration/importing_data.md@533:``` yaml
docs/content_management/data_migration/importing_data.md@534:[[= include_file('code_samples/data_migration/examples/discounts/discount_code_create.yaml') =]]
docs/content_management/data_migration/importing_data.md@535:```

001⫶type: discount_code
002⫶mode: create
003⫶code: summer10
004⫶global_usage_limit: 100 # Optional
005⫶user_usage_limit: 5 # Optional
006⫶created_at: '2023-01-01T12:00:00+00:00' # Optional
007⫶creator_id: 42 # Optional


code_samples/discounts/src/Command/ManageDiscountsCommand.php


code_samples/discounts/src/Command/ManageDiscountsCommand.php

docs/discounts/discounts_api.md@118:``` php hl_lines="60-66 68-92"
docs/discounts/discounts_api.md@118:``` php hl_lines="60-67 69-97"
docs/discounts/discounts_api.md@119:[[= include_file('code_samples/discounts/src/Command/ManageDiscountsCommand.php') =]]
docs/discounts/discounts_api.md@120:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\Command;
006⫶
007⫶use DateTimeImmutable;
008⫶use Ibexa\Contracts\Core\Collection\ArrayMap;
009⫶use Ibexa\Contracts\Core\Repository\PermissionResolver;
010⫶use Ibexa\Contracts\Core\Repository\UserService;
011⫶use Ibexa\Contracts\Discounts\DiscountServiceInterface;
012⫶use Ibexa\Contracts\Discounts\Value\DiscountType;
013⫶use Ibexa\Contracts\Discounts\Value\Struct\DiscountCreateStruct;
014⫶use Ibexa\Contracts\Discounts\Value\Struct\DiscountTranslationStruct;
015⫶use Ibexa\Contracts\DiscountsCodes\DiscountCodeServiceInterface;
016⫶use Ibexa\Contracts\DiscountsCodes\Value\Struct\DiscountCodeCreateStruct;
017⫶use Ibexa\Discounts\Value\DiscountCondition\IsInCurrency;
018⫶use Ibexa\Discounts\Value\DiscountCondition\IsInRegions;
019⫶use Ibexa\Discounts\Value\DiscountCondition\IsProductInArray;
020⫶use Ibexa\Discounts\Value\DiscountRule\FixedAmount;
021⫶use Ibexa\DiscountsCodes\Value\DiscountCondition\IsValidDiscountCode;
022⫶use Symfony\Component\Console\Command\Command;
023⫶use Symfony\Component\Console\Input\InputInterface;
024⫶use Symfony\Component\Console\Output\OutputInterface;
025⫶
026⫶final class ManageDiscountsCommand extends Command
027⫶{
028⫶ protected static $defaultName = 'discounts:manage';
029⫶
030⫶ private DiscountServiceInterface $discountService;
031⫶
032⫶ private DiscountCodeServiceInterface $discountCodeService;
033⫶
034⫶ private PermissionResolver $permissionResolver;
035⫶
036⫶ private UserService $userService;
037⫶
038⫶ public function __construct(
039⫶ UserService $userSerice,
040⫶ PermissionResolver $permissionResolver,
041⫶ DiscountServiceInterface $discountService,
042⫶ DiscountCodeServiceInterface $discountCodeService
043⫶ ) {
044⫶ $this->userService = $userSerice;
045⫶ $this->discountService = $discountService;
046⫶ $this->discountCodeService = $discountCodeService;
047⫶ $this->permissionResolver = $permissionResolver;
048⫶
049⫶ parent::__construct();
050⫶ }
051⫶
052⫶ protected function execute(InputInterface $input, OutputInterface $output): int
053⫶ {
054⫶ $this->permissionResolver->setCurrentUserReference(
055⫶ $this->userService->loadUserByLogin('admin')
056⫶ );
057⫶
058⫶ $now = new DateTimeImmutable();
059⫶
060❇️ $discountCodeCreateStruct = new DiscountCodeCreateStruct(
061❇️ 'summer10',
docs/discounts/discounts_api.md@119:[[= include_file('code_samples/discounts/src/Command/ManageDiscountsCommand.php') =]]
docs/discounts/discounts_api.md@120:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\Command;
006⫶
007⫶use DateTimeImmutable;
008⫶use Ibexa\Contracts\Core\Collection\ArrayMap;
009⫶use Ibexa\Contracts\Core\Repository\PermissionResolver;
010⫶use Ibexa\Contracts\Core\Repository\UserService;
011⫶use Ibexa\Contracts\Discounts\DiscountServiceInterface;
012⫶use Ibexa\Contracts\Discounts\Value\DiscountType;
013⫶use Ibexa\Contracts\Discounts\Value\Struct\DiscountCreateStruct;
014⫶use Ibexa\Contracts\Discounts\Value\Struct\DiscountTranslationStruct;
015⫶use Ibexa\Contracts\DiscountsCodes\DiscountCodeServiceInterface;
016⫶use Ibexa\Contracts\DiscountsCodes\Value\Struct\DiscountCodeCreateStruct;
017⫶use Ibexa\Discounts\Value\DiscountCondition\IsInCurrency;
018⫶use Ibexa\Discounts\Value\DiscountCondition\IsInRegions;
019⫶use Ibexa\Discounts\Value\DiscountCondition\IsProductInArray;
020⫶use Ibexa\Discounts\Value\DiscountRule\FixedAmount;
021⫶use Ibexa\DiscountsCodes\Value\DiscountCondition\IsValidDiscountCode;
022⫶use Symfony\Component\Console\Command\Command;
023⫶use Symfony\Component\Console\Input\InputInterface;
024⫶use Symfony\Component\Console\Output\OutputInterface;
025⫶
026⫶final class ManageDiscountsCommand extends Command
027⫶{
028⫶ protected static $defaultName = 'discounts:manage';
029⫶
030⫶ private DiscountServiceInterface $discountService;
031⫶
032⫶ private DiscountCodeServiceInterface $discountCodeService;
033⫶
034⫶ private PermissionResolver $permissionResolver;
035⫶
036⫶ private UserService $userService;
037⫶
038⫶ public function __construct(
039⫶ UserService $userSerice,
040⫶ PermissionResolver $permissionResolver,
041⫶ DiscountServiceInterface $discountService,
042⫶ DiscountCodeServiceInterface $discountCodeService
043⫶ ) {
044⫶ $this->userService = $userSerice;
045⫶ $this->discountService = $discountService;
046⫶ $this->discountCodeService = $discountCodeService;
047⫶ $this->permissionResolver = $permissionResolver;
048⫶
049⫶ parent::__construct();
050⫶ }
051⫶
052⫶ protected function execute(InputInterface $input, OutputInterface $output): int
053⫶ {
054⫶ $this->permissionResolver->setCurrentUserReference(
055⫶ $this->userService->loadUserByLogin('admin')
056⫶ );
057⫶
058⫶ $now = new DateTimeImmutable();
059⫶
060❇️ $discountCodeCreateStruct = new DiscountCodeCreateStruct(
061❇️ 'summer10',
062❇️            null, // Unlimited usage
063❇️ $this->permissionResolver->getCurrentUserReference()->getUserId(),
064❇️ $now
065❇️ );
066❇️ $discountCode = $this->discountCodeService->createDiscountCode($discountCodeCreateStruct);
067⫶
068❇️ $discountCreateStruct = new DiscountCreateStruct();
069❇️ $discountCreateStruct
070❇️ ->setIdentifier('discount_identifier')
071❇️ ->setType(DiscountType::CART)
072❇️ ->setPriority(10)
073❇️ ->setEnabled(true)
074❇️ ->setUser($this->userService->loadUserByLogin('admin'))
075❇️ ->setRule(new FixedAmount(10))
076❇️ ->setStartDate($now)
077❇️ ->setConditions([
078❇️ new IsInRegions(['germany', 'france']),
079❇️ new IsProductInArray(['product-1', 'product-2']),
080❇️ new IsInCurrency('EUR'),
081❇️ new IsValidDiscountCode($discountCode->getCode(), $discountCode->getUsedLimit()),
082❇️ ])
083❇️ ->setTranslations([
084❇️ new DiscountTranslationStruct('eng-GB', 'Discount name', 'This is a discount description', 'Promotion Label', 'Promotion Description'),
085❇️ new DiscountTranslationStruct('ger-DE', 'Discount name (German)', 'Description (German)', 'Promotion Label (German)', 'Promotion Description (German)'),
086❇️ ])
087❇️ ->setEndDate(null) // Permanent discount
088❇️ ->setCreatedAt($now)
089❇️ ->setUpdatedAt($now)
090❇️ ->setContext(new ArrayMap(['custom_context' => 'custom_value']));
091❇️
092❇️ $this->discountService->createDiscount($discountCreateStruct);
093⫶
094⫶ return Command::SUCCESS;
095⫶ }
096⫶}
062❇️            10, // Global usage limit
063❇️ null, // Unlimited usage per customer
064❇️ $this->permissionResolver->getCurrentUserReference()->getUserId(),
065❇️ $now
066❇️ );
067❇️ $discountCode = $this->discountCodeService->createDiscountCode($discountCodeCreateStruct);
068⫶
069❇️ $discountCreateStruct = new DiscountCreateStruct();
070❇️ $discountCreateStruct
071❇️ ->setIdentifier('discount_identifier')
072❇️ ->setType(DiscountType::CART)
073❇️ ->setPriority(10)
074❇️ ->setEnabled(true)
075❇️ ->setUser($this->userService->loadUserByLogin('admin'))
076❇️ ->setRule(new FixedAmount(10))
077❇️ ->setStartDate($now)
078❇️ ->setConditions([
079❇️ new IsInRegions(['germany', 'france']),
080❇️ new IsProductInArray(['product-1', 'product-2']),
081❇️ new IsInCurrency('EUR'),
082❇️ new IsValidDiscountCode(
083❇️ $discountCode->getCode(),
084❇️ $discountCode->getGlobalLimit(),
085❇️ $discountCode->getUsedLimit()
086❇️ ),
087❇️ ])
088❇️ ->setTranslations([
089❇️ new DiscountTranslationStruct('eng-GB', 'Discount name', 'This is a discount description', 'Promotion Label', 'Promotion Description'),
090❇️ new DiscountTranslationStruct('ger-DE', 'Discount name (German)', 'Description (German)', 'Promotion Label (German)', 'Promotion Description (German)'),
091❇️ ])
092❇️ ->setEndDate(null) // Permanent discount
093❇️ ->setCreatedAt($now)
094❇️ ->setUpdatedAt($now)
095❇️ ->setContext(new ArrayMap(['custom_context' => 'custom_value']));
096❇️
097❇️ $this->discountService->createDiscount($discountCreateStruct);
098⫶
099⫶ return Command::SUCCESS;
100⫶ }
101⫶}


Download colorized diff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs DOC review Wait with merge PRs that shouldn't be merged instantly
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants